Index: lib/src/runner/reporter/expanded.dart |
diff --git a/lib/src/runner/reporter/expanded.dart b/lib/src/runner/reporter/expanded.dart |
index 3bb5f7f43e8451e3be1235fea5e77a2b783d985a..a885c555463d6a735ef5e549b037c93f35660a6d 100644 |
--- a/lib/src/runner/reporter/expanded.dart |
+++ b/lib/src/runner/reporter/expanded.dart |
@@ -4,6 +4,7 @@ |
library test.runner.reporter.no_io_compact; |
+import 'dart:async'; |
import 'dart:isolate'; |
import '../../backend/live_test.dart'; |
@@ -12,6 +13,7 @@ import '../../utils.dart'; |
import '../engine.dart'; |
import '../load_exception.dart'; |
import '../load_suite.dart'; |
+import '../reporter.dart'; |
/// The maximum console line length. |
/// |
@@ -24,7 +26,7 @@ const _lineLength = 100; |
/// which can't transitively import `dart:io` but still needs access to a runner |
/// so that test files can be run directly. This means that until issue 6943 is |
/// fixed, this must not import `dart:io`. |
-class ExpandedReporter { |
+class ExpandedReporter implements Reporter { |
/// Whether the reporter should emit terminal color escapes. |
final bool _color; |
@@ -67,6 +69,12 @@ class ExpandedReporter { |
/// A stopwatch that tracks the duration of the full run. |
final _stopwatch = new Stopwatch(); |
+ /// Whether we've started [_stopwatch]. |
+ /// |
+ /// We can't just use `_stopwatch.isRunning` because the stopwatch is stopped |
+ /// when the reporter is paused. |
+ var _stopwatchStarted = false; |
+ |
/// The size of `_engine.passed` last time a progress notification was |
/// printed. |
int _lastProgressPassed; |
@@ -82,6 +90,12 @@ class ExpandedReporter { |
/// The message printed for the last progress notification. |
String _lastProgressMessage; |
+ /// Whether the reporter is paused. |
+ var _paused = false; |
+ |
+ /// The set of all subscriptions to various streams. |
+ final _subscriptions = new Set<StreamSubscription>(); |
+ |
/// Watches the tests run by [engine] and prints their results to the |
/// terminal. |
/// |
@@ -90,9 +104,10 @@ class ExpandedReporter { |
/// If [printPath] is `true`, this will print the path name as part of the |
/// test description. Likewise, if [printPlatform] is `true`, this will print |
/// the platform as part of the test description. |
- static void watch(Engine engine, {bool color: true, bool verboseTrace: false, |
- bool printPath: true, bool printPlatform: true}) { |
- new ExpandedReporter._( |
+ static ExpandedReporter watch(Engine engine, {bool color: true, |
+ bool verboseTrace: false, bool printPath: true, |
+ bool printPlatform: true}) { |
+ return new ExpandedReporter._( |
engine, |
color: color, |
verboseTrace: verboseTrace, |
@@ -112,8 +127,38 @@ class ExpandedReporter { |
_gray = color ? '\u001b[1;30m' : '', |
_bold = color ? '\u001b[1m' : '', |
_noColor = color ? '\u001b[0m' : '' { |
- _engine.onTestStarted.listen(_onTestStarted); |
- _engine.success.then(_onDone); |
+ _subscriptions.add(_engine.onTestStarted.listen(_onTestStarted)); |
+ |
+ /// Convert the future to a stream so that the subscription can be paused or |
+ /// canceled. |
+ _subscriptions.add(_engine.success.asStream().listen(_onDone)); |
+ } |
+ |
+ void pause() { |
+ if (_paused) return; |
+ _paused = true; |
+ |
+ _stopwatch.stop(); |
+ |
+ for (var subscription in _subscriptions) { |
+ subscription.pause(); |
+ } |
+ } |
+ |
+ void resume() { |
+ if (!_paused) return; |
+ if (_stopwatchStarted) _stopwatch.start(); |
+ |
+ for (var subscription in _subscriptions) { |
+ subscription.resume(); |
+ } |
+ } |
+ |
+ void cancel() { |
+ for (var subscription in _subscriptions) { |
+ subscription.cancel(); |
+ } |
+ _subscriptions.clear(); |
} |
/// A callback called when the engine begins running [liveTest]. |
@@ -128,7 +173,8 @@ class ExpandedReporter { |
// The engine surfaces load tests when there are no other tests running, |
// but because the expanded reporter's output is always visible, we don't |
// emit information about them unless they fail. |
- liveTest.onStateChange.listen((state) => _onStateChange(liveTest, state)); |
+ _subscriptions.add(liveTest.onStateChange |
+ .listen((state) => _onStateChange(liveTest, state))); |
} else if (_engine.active.length == 1 && |
_engine.active.first == liveTest && |
liveTest.test.name.startsWith("compiling ")) { |
@@ -137,13 +183,13 @@ class ExpandedReporter { |
_progressLine(_description(liveTest)); |
} |
- liveTest.onError.listen((error) => |
- _onError(liveTest, error.error, error.stackTrace)); |
+ _subscriptions.add(liveTest.onError.listen((error) => |
+ _onError(liveTest, error.error, error.stackTrace))); |
- liveTest.onPrint.listen((line) { |
+ _subscriptions.add(liveTest.onPrint.listen((line) { |
_progressLine(_description(liveTest)); |
print(line); |
- }); |
+ })); |
} |
/// A callback called when [liveTest]'s state becomes [state]. |