Automatically intercept print calls and append them to reponse.output
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d81018c..e42904a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/lib/src/async_worker_loop.dart b/lib/src/async_worker_loop.dart
index 4583ba2..bf6c893 100644
--- a/lib/src/async_worker_loop.dart
+++ b/lib/src/async_worker_loop.dart
@@ -41,7 +41,16 @@
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) {
diff --git a/lib/src/sync_worker_loop.dart b/lib/src/sync_worker_loop.dart
index 3b2a05b..a3528a5 100644
--- a/lib/src/sync_worker_loop.dart
+++ b/lib/src/sync_worker_loop.dart
@@ -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';
@@ -39,7 +39,15 @@
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) {
diff --git a/lib/testing.dart b/lib/testing.dart
index 882097f..1afd231 100644
--- a/lib/testing.dart
+++ b/lib/testing.dart
@@ -101,6 +101,9 @@
/// 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.
@@ -123,12 +126,16 @@
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();
}
@@ -161,12 +168,16 @@
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();
}
diff --git a/pubspec.yaml b/pubspec.yaml
index e7e589e..e6ca01b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -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 <misc@dartlang.org>
homepage: https://github.com/dart-lang/bazel_worker
diff --git a/test/worker_loop_test.dart b/test/worker_loop_test.dart
index ac4dd11..1ef2845 100644
--- a/test/worker_loop_test.dart
+++ b/test/worker_loop_test.dart
@@ -28,6 +28,24 @@
(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>*/(
@@ -54,10 +72,23 @@
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));