Skip to content
This repository has been archived by the owner on Nov 1, 2024. It is now read-only.

Commit

Permalink
Automatically intercept print calls and append them to reponse.output
Browse files Browse the repository at this point in the history
  • Loading branch information
jakemac53 committed Mar 20, 2017
1 parent 6bbffbc commit 4b4bfa6
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 8 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
## 0.1.3

* Add automatic intercepting of print calls and append them to
`response.output`. This makes more libraries work out of the box, as printing
would previously cause an error due to communication over stdin/stdout.
* Note that using stdin/stdout directly will still cause an error, but that is
less common.

## 0.1.2

* Add better handling for the case where stdin gives an error instead of an EOF.
* Add better handling for the case where stdin gives an error instead of an EOF.

## 0.1.1

Expand Down
11 changes: 10 additions & 1 deletion lib/src/async_worker_loop.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@ abstract class AsyncWorkerLoop implements WorkerLoop {
try {
var request = await connection.readRequest();
if (request == null) break;
response = await performRequest(request);
var printMessages = new StringBuffer();
response = await runZoned(() => performRequest(request),
zoneSpecification:
new ZoneSpecification(print: (self, parent, zone, message) {
printMessages.writeln();
printMessages.write(message);
}));
if (printMessages.isNotEmpty) {
response.output = '${response.output}$printMessages';
}
// In case they forget to set this.
response.exitCode ??= EXIT_CODE_OK;
} catch (e, s) {
Expand Down
12 changes: 10 additions & 2 deletions lib/src/sync_worker_loop.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:io';

import 'constants.dart';
Expand Down Expand Up @@ -39,7 +39,15 @@ abstract class SyncWorkerLoop implements WorkerLoop {
try {
var request = connection.readRequest();
if (request == null) break;
response = performRequest(request);
var printMessages = new StringBuffer();
response = runZoned(() => performRequest(request), zoneSpecification:
new ZoneSpecification(print: (self, parent, zone, message) {
printMessages.writeln();
printMessages.write(message);
}));
if (printMessages.isNotEmpty) {
response.output = '${response.output}$printMessages';
}
// In case they forget to set this.
response.exitCode ??= EXIT_CODE_OK;
} catch (e, s) {
Expand Down
15 changes: 13 additions & 2 deletions lib/testing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ abstract class TestWorkerConnection implements WorkerConnection {
/// Interface for a [TestWorkerLoop] which allows you to enqueue responses.
abstract class TestWorkerLoop implements WorkerLoop {
void enqueueResponse(WorkResponse response);

/// If set, this message will be printed during the call to `performRequest`.
String get printMessage;
}

/// A [StdSyncWorkerConnection] which records its responses.
Expand All @@ -123,12 +126,16 @@ class TestSyncWorkerLoop extends SyncWorkerLoop implements TestWorkerLoop {
final List<WorkRequest> requests = <WorkRequest>[];
final Queue<WorkResponse> _responses = new Queue<WorkResponse>();

TestSyncWorkerLoop(SyncWorkerConnection connection)
@override
final String printMessage;

TestSyncWorkerLoop(SyncWorkerConnection connection, {this.printMessage})
: super(connection: connection);

@override
WorkResponse performRequest(WorkRequest request) {
requests.add(request);
if (printMessage != null) print(printMessage);
return _responses.removeFirst();
}

Expand Down Expand Up @@ -161,12 +168,16 @@ class TestAsyncWorkerLoop extends AsyncWorkerLoop implements TestWorkerLoop {
final List<WorkRequest> requests = <WorkRequest>[];
final Queue<WorkResponse> _responses = new Queue<WorkResponse>();

TestAsyncWorkerLoop(AsyncWorkerConnection connection)
@override
final String printMessage;

TestAsyncWorkerLoop(AsyncWorkerConnection connection, {this.printMessage})
: super(connection: connection);

@override
Future<WorkResponse> performRequest(WorkRequest request) async {
requests.add(request);
if (printMessage != null) print(printMessage);
return _responses.removeFirst();
}

Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: bazel_worker
version: 0.1.2
version: 0.1.3
description: Tools for creating a bazel persistent worker.
author: Dart Team <[email protected]>
homepage: https://github.com/dart-lang/bazel_worker
Expand Down
33 changes: 32 additions & 1 deletion test/worker_loop_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,24 @@ void main() {
(TestAsyncWorkerConnection connection) =>
new TestAsyncWorkerLoop(connection));
});

group('SyncWorkerLoopWithPrint', () {
runTests(
() => new TestStdinSync(),
(Stdin stdinStream, Stdout stdoutStream) =>
new TestSyncWorkerConnection(stdinStream, stdoutStream),
(TestSyncWorkerConnection connection) =>
new TestSyncWorkerLoop(connection, printMessage: 'Goodbye!'));
});

group('AsyncWorkerLoopWithPrint', () {
runTests(
() => new TestStdinAsync(),
(Stdin stdinStream, Stdout stdoutStream) =>
new TestAsyncWorkerConnection(stdinStream, stdoutStream),
(TestAsyncWorkerConnection connection) =>
new TestAsyncWorkerLoop(connection, printMessage: 'Goodbye!'));
});
}

void runTests/*<T extends TestWorkerConnection>*/(
Expand All @@ -54,10 +72,23 @@ void runTests/*<T extends TestWorkerConnection>*/(

var response = new WorkResponse()..output = 'Hello World';
workerLoop.enqueueResponse(response);
await workerLoop.run();

// Make sure `print` never gets called in the parent zone.
var printMessages = <String>[];
await runZoned(() => workerLoop.run(), zoneSpecification:
new ZoneSpecification(print: (self, parent, zone, message) {
printMessages.add(message);
}));
expect(printMessages, isEmpty,
reason: 'The worker loop should hide all print calls from the parent '
'zone.');

expect(connection.responses, hasLength(1));
expect(connection.responses[0], response);
if (workerLoop.printMessage != null) {
expect(response.output, endsWith(workerLoop.printMessage),
reason: 'Print messages should get appended to the response output.');
}

// Check that a serialized version was written to std out.
expect(stdoutStream.writes, hasLength(1));
Expand Down

0 comments on commit 4b4bfa6

Please sign in to comment.