OLD | NEW |
1 Future debug(Configuration config, Engine engine, Reporter reporter, | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 LoadSuite loadSuite) async { | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // Make the underlying suite null so that the engine doesn't start running | 3 // BSD-style license that can be found in the LICENSE file. |
4 // it immediately. | |
5 _engine.suiteSink.add(loadSuite.changeSuite((_) => null)); | |
6 | 4 |
7 var suite = await loadSuite.suite; | 5 library test.runner.debugger; |
8 if (suite == null) return; | |
9 | 6 |
10 var debugger = new _Debugger(config, reporter, suite); | 7 import 'dart:async'; |
11 try { | |
12 await debugger._pause(); | |
13 if (_closed) return; | |
14 | 8 |
15 debugger._listen(); | 9 import 'package:async/async.dart'; |
16 _engine.suiteSink.add(suite); | 10 |
17 await _engine.onIdle.first; | 11 import '../backend/live_test.dart'; |
18 } finally { | 12 import '../backend/test_platform.dart'; |
19 debugger._close(); | 13 import '../util/io.dart'; |
20 } | 14 import '../utils.dart'; |
| 15 import 'configuration.dart'; |
| 16 import 'console.dart'; |
| 17 import 'engine.dart'; |
| 18 import 'load_suite.dart'; |
| 19 import 'reporter.dart'; |
| 20 import 'runner_suite.dart'; |
| 21 |
| 22 /// Runs [loadSuite] in debugging mode. |
| 23 /// |
| 24 /// Runs the suite's tests using [engine]. The [reporter] should already be |
| 25 /// watching [engine], and the [config] should contain the user configuration |
| 26 /// for the test runner. |
| 27 /// |
| 28 /// Returns a [CancelableOperation] that will complete once the suite has |
| 29 /// finished running. If the operation is canceled, the debugger will clean up |
| 30 /// any resources it allocated. |
| 31 CancelableOperation debug(Configuration config, Engine engine, |
| 32 Reporter reporter, LoadSuite loadSuite) { |
| 33 var debugger; |
| 34 var canceled = false; |
| 35 return new CancelableOperation.fromFuture(() async { |
| 36 // Make the underlying suite null so that the engine doesn't start running |
| 37 // it immediately. |
| 38 engine.suiteSink.add(loadSuite.changeSuite((_) => null)); |
| 39 |
| 40 var suite = await loadSuite.suite; |
| 41 if (canceled || suite == null) return; |
| 42 |
| 43 debugger = new _Debugger(config, engine, reporter, suite); |
| 44 await debugger.run(); |
| 45 }(), onCancel: () { |
| 46 canceled = true; |
| 47 if (debugger != null) debugger.close(); |
| 48 }); |
21 } | 49 } |
22 | 50 |
| 51 // TODO(nweiz): Test using the console and restarting a test once sdk#25369 is |
| 52 // fixed and the VM service client is released and we can set Dartium |
| 53 // breakpoints. |
| 54 /// A debugger for a single test suite. |
23 class _Debugger { | 55 class _Debugger { |
| 56 /// The user configuration for the test runner. |
24 final Configuration _config; | 57 final Configuration _config; |
25 | 58 |
| 59 /// The engine that will run the suite. |
| 60 final Engine _engine; |
| 61 |
| 62 /// The reporter that's reporting [_engine]'s progress. |
26 final Reporter _reporter; | 63 final Reporter _reporter; |
27 | 64 |
| 65 /// The suite to run. |
28 final RunnerSuite _suite; | 66 final RunnerSuite _suite; |
29 | 67 |
| 68 /// The console through which the user can control the debugger. |
| 69 /// |
| 70 /// This is only visible when the test environment is paused, so as not to |
| 71 /// overlap with the reporter's reporting. |
| 72 final Console _console; |
| 73 |
| 74 /// The subscription to [_suite.onDebugging]. |
30 StreamSubscription<bool> _onDebuggingSubscription; | 75 StreamSubscription<bool> _onDebuggingSubscription; |
31 | 76 |
32 bool _canDebug => | 77 /// Whether [close] has been called. |
33 _suite.platform != null && _suite.platform != TestPlatform.vm; | 78 bool _closed = false; |
34 | 79 |
35 _Debugger(this._config, this._reporter, this._suite); | 80 _Debugger(Configuration config, this._engine, this._reporter, this._suite) |
| 81 : _config = config, |
| 82 _console = new Console(color: config.color) { |
| 83 _console.registerCommand( |
| 84 "restart", "Restart the current test after it finishes running.", |
| 85 _restartTest); |
36 | 86 |
| 87 _onDebuggingSubscription = _suite.onDebugging.listen((debugging) { |
| 88 if (debugging) { |
| 89 _onDebugging(); |
| 90 } else { |
| 91 _onNotDebugging(); |
| 92 } |
| 93 }); |
| 94 } |
| 95 |
| 96 /// Runs the debugger. |
| 97 /// |
| 98 /// This prints information about the suite's debugger, then once the user has |
| 99 /// had a chance to set breakpoints, runs the suite's tests. |
| 100 Future run() async { |
| 101 try { |
| 102 await _pause(); |
| 103 if (_closed) return; |
| 104 |
| 105 _engine.suiteSink.add(_suite); |
| 106 await _engine.onIdle.first; |
| 107 } finally { |
| 108 close(); |
| 109 } |
| 110 } |
| 111 |
| 112 /// Prints URLs for the [_suite]'s debugger and waits for the user to tell the |
| 113 /// suite to run. |
37 Future _pause() async { | 114 Future _pause() async { |
38 if (_suite.platform == null) return; | 115 if (_suite.platform == null) return; |
39 if (_suite.platform == TestPlatform.vm) return; | 116 if (_suite.platform == TestPlatform.vm) return; |
40 | 117 |
41 try { | 118 try { |
42 _reporter.pause(); | 119 _reporter.pause(); |
43 | 120 |
44 var bold = _config.color ? '\u001b[1m' : ''; | 121 var bold = _config.color ? '\u001b[1m' : ''; |
45 var yellow = _config.color ? '\u001b[33m' : ''; | 122 var yellow = _config.color ? '\u001b[33m' : ''; |
46 var noColor = _config.color ? '\u001b[0m' : ''; | 123 var noColor = _config.color ? '\u001b[0m' : ''; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 | 158 |
82 await inCompletionOrder([ | 159 await inCompletionOrder([ |
83 _suite.environment.displayPause(), | 160 _suite.environment.displayPause(), |
84 cancelableNext(stdinLines) | 161 cancelableNext(stdinLines) |
85 ]).first; | 162 ]).first; |
86 } finally { | 163 } finally { |
87 _reporter.resume(); | 164 _reporter.resume(); |
88 } | 165 } |
89 } | 166 } |
90 | 167 |
91 void _listen() { | 168 /// Handles the environment pausing to debug. |
92 _suite.onDebugging.listen((debugging) { | 169 /// |
93 if (debugging) { | 170 /// This starts the interactive console. |
94 _onDebugging(); | 171 void _onDebugging() { |
95 } else { | 172 _reporter.pause(); |
96 _onNotDebugging(); | 173 |
97 } | 174 print('\nEntering debugging console. Type "help" for help.'); |
98 }); | 175 _console.start(); |
99 } | 176 } |
100 | 177 |
101 void _onDebugging(bool debugging) { | 178 /// Handles the environment starting up again. |
102 _reporter.pause(); | 179 /// |
| 180 /// This closes the interactive console. |
| 181 void _onNotDebugging() { |
| 182 _reporter.resume(); |
| 183 _console.stop(); |
103 } | 184 } |
104 | 185 |
105 void _close() { | 186 /// Restarts the current test. |
| 187 void _restartTest() { |
| 188 var liveTest = _engine.active.single; |
| 189 _engine.restartTest(liveTest); |
| 190 print(wordWrap( |
| 191 'Will restart "${liveTest.test.name}" once it finishes running.')); |
| 192 } |
| 193 |
| 194 /// Closes the debugger and releases its resources. |
| 195 void close() { |
| 196 _closed = true; |
106 _onDebuggingSubscription.cancel(); | 197 _onDebuggingSubscription.cancel(); |
| 198 _console.stop(); |
107 } | 199 } |
108 } | 200 } |
OLD | NEW |