Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: lib/src/runner.dart

Issue 1561073003: Support re-running tests while debugging. (Closed) Base URL: git@github.com:dart-lang/test@debugger-wip
Patch Set: Code review changes Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/src/backend/live_test.dart ('k') | lib/src/runner/browser/iframe_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library test.runner; 5 library test.runner;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:io'; 8 import 'dart:io';
9 9
10 import 'package:async/async.dart'; 10 import 'package:async/async.dart';
11 11
12 import 'backend/group.dart'; 12 import 'backend/group.dart';
13 import 'backend/group_entry.dart'; 13 import 'backend/group_entry.dart';
14 import 'backend/suite.dart'; 14 import 'backend/suite.dart';
15 import 'backend/test.dart'; 15 import 'backend/test.dart';
16 import 'backend/test_platform.dart'; 16 import 'backend/test_platform.dart';
17 import 'runner/application_exception.dart'; 17 import 'runner/application_exception.dart';
18 import 'runner/configuration.dart'; 18 import 'runner/configuration.dart';
19 import 'runner/debugger.dart';
19 import 'runner/engine.dart'; 20 import 'runner/engine.dart';
20 import 'runner/load_exception.dart'; 21 import 'runner/load_exception.dart';
21 import 'runner/load_suite.dart'; 22 import 'runner/load_suite.dart';
22 import 'runner/loader.dart'; 23 import 'runner/loader.dart';
23 import 'runner/reporter.dart'; 24 import 'runner/reporter.dart';
24 import 'runner/reporter/compact.dart'; 25 import 'runner/reporter/compact.dart';
25 import 'runner/reporter/expanded.dart'; 26 import 'runner/reporter/expanded.dart';
26 import 'runner/reporter/json.dart'; 27 import 'runner/reporter/json.dart';
27 import 'runner/runner_suite.dart';
28 import 'util/io.dart'; 28 import 'util/io.dart';
29 import 'utils.dart'; 29 import 'utils.dart';
30 30
31 /// A class that loads and runs tests based on a [Configuration]. 31 /// A class that loads and runs tests based on a [Configuration].
32 /// 32 ///
33 /// This maintains a [Loader] and an [Engine] and passes test suites from one to 33 /// This maintains a [Loader] and an [Engine] and passes test suites from one to
34 /// the other, as well as printing out tests with a [CompactReporter] or an 34 /// the other, as well as printing out tests with a [CompactReporter] or an
35 /// [ExpandedReporter]. 35 /// [ExpandedReporter].
36 class Runner { 36 class Runner {
37 /// The configuration for the runner. 37 /// The configuration for the runner.
(...skipping 11 matching lines...) Expand all
49 /// The subscription to the stream returned by [_loadSuites]. 49 /// The subscription to the stream returned by [_loadSuites].
50 StreamSubscription _suiteSubscription; 50 StreamSubscription _suiteSubscription;
51 51
52 /// The set of suite paths for which [_warnForUnknownTags] has already been 52 /// The set of suite paths for which [_warnForUnknownTags] has already been
53 /// called. 53 /// called.
54 /// 54 ///
55 /// This is used to avoid printing duplicate warnings when a suite is loaded 55 /// This is used to avoid printing duplicate warnings when a suite is loaded
56 /// on multiple platforms. 56 /// on multiple platforms.
57 final _tagWarningSuites = new Set<String>(); 57 final _tagWarningSuites = new Set<String>();
58 58
59 /// The current debug operation, if any.
60 ///
61 /// This is stored so that we can cancel it when the runner is closed.
62 CancelableOperation _debugOperation;
63
59 /// The memoizer for ensuring [close] only runs once. 64 /// The memoizer for ensuring [close] only runs once.
60 final _closeMemo = new AsyncMemoizer(); 65 final _closeMemo = new AsyncMemoizer();
61 bool get _closed => _closeMemo.hasRun; 66 bool get _closed => _closeMemo.hasRun;
62 67
63 /// Creates a new runner based on [configuration]. 68 /// Creates a new runner based on [configuration].
64 factory Runner(Configuration config) { 69 factory Runner(Configuration config) {
65 var loader = new Loader(config); 70 var loader = new Loader(config);
66 var engine = new Engine(concurrency: config.concurrency); 71 var engine = new Engine(concurrency: config.concurrency);
67 72
68 var reporter; 73 var reporter;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 timer = new Timer(new Duration(seconds: 1), () { 154 timer = new Timer(new Duration(seconds: 1), () {
150 // Pause the reporter while we print to ensure that we don't interfere 155 // Pause the reporter while we print to ensure that we don't interfere
151 // with its output. 156 // with its output.
152 _reporter.pause(); 157 _reporter.pause();
153 print("Waiting for current test(s) to finish."); 158 print("Waiting for current test(s) to finish.");
154 print("Press Control-C again to terminate immediately."); 159 print("Press Control-C again to terminate immediately.");
155 _reporter.resume(); 160 _reporter.resume();
156 }); 161 });
157 } 162 }
158 163
164 if (_debugOperation != null) await _debugOperation.cancel();
165
159 if (_suiteSubscription != null) _suiteSubscription.cancel(); 166 if (_suiteSubscription != null) _suiteSubscription.cancel();
160 _suiteSubscription = null; 167 _suiteSubscription = null;
161 168
162 // Make sure we close the engine *before* the loader. Otherwise, 169 // Make sure we close the engine *before* the loader. Otherwise,
163 // LoadSuites provided by the loader may get into bad states. 170 // LoadSuites provided by the loader may get into bad states.
164 await _engine.close(); 171 await _engine.close();
165 if (timer != null) timer.cancel(); 172 if (timer != null) timer.cancel();
166 await _loader.close(); 173 await _loader.close();
167 }); 174 });
168 175
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 290
284 /// Loads each suite in [suites] in order, pausing after load for platforms 291 /// Loads each suite in [suites] in order, pausing after load for platforms
285 /// that support debugging. 292 /// that support debugging.
286 Future<bool> _loadThenPause(Stream<LoadSuite> suites) async { 293 Future<bool> _loadThenPause(Stream<LoadSuite> suites) async {
287 if (_config.platforms.contains(TestPlatform.vm)) { 294 if (_config.platforms.contains(TestPlatform.vm)) {
288 warn("Debugging is currently unsupported on the Dart VM.", 295 warn("Debugging is currently unsupported on the Dart VM.",
289 color: _config.color); 296 color: _config.color);
290 } 297 }
291 298
292 _suiteSubscription = suites.asyncMap((loadSuite) async { 299 _suiteSubscription = suites.asyncMap((loadSuite) async {
293 // Make the underlying suite null so that the engine doesn't start running 300 _debugOperation = debug(_config, _engine, _reporter, loadSuite);
294 // it immediately. 301 await _debugOperation.valueOrCancellation();
295 _engine.suiteSink.add(loadSuite.changeSuite((_) => null));
296
297 var suite = await loadSuite.suite;
298 if (suite == null) return;
299
300 await _pause(suite);
301 if (_closed) return;
302
303 _engine.suiteSink.add(suite);
304 await _engine.onIdle.first;
305 }).listen(null); 302 }).listen(null);
306 303
307 var results = await Future.wait([ 304 var results = await Future.wait([
308 _suiteSubscription.asFuture().then((_) => _engine.suiteSink.close()), 305 _suiteSubscription.asFuture().then((_) => _engine.suiteSink.close()),
309 _engine.run() 306 _engine.run()
310 ]); 307 ]);
311 return results.last; 308 return results.last;
312 } 309 }
313
314 /// Pauses the engine and the reporter so that the user can set breakpoints as
315 /// necessary.
316 ///
317 /// This is a no-op for test suites that aren't on platforms where debugging
318 /// is supported.
319 Future _pause(RunnerSuite suite) async {
320 if (suite.platform == null) return;
321 if (suite.platform == TestPlatform.vm) return;
322
323 try {
324 _reporter.pause();
325
326 var bold = _config.color ? '\u001b[1m' : '';
327 var yellow = _config.color ? '\u001b[33m' : '';
328 var noColor = _config.color ? '\u001b[0m' : '';
329 print('');
330
331 if (suite.platform.isDartVM) {
332 var url = suite.environment.observatoryUrl;
333 if (url == null) {
334 print("${yellow}Observatory URL not found. Make sure you're using "
335 "${suite.platform.name} 1.11 or later.$noColor");
336 } else {
337 print("Observatory URL: $bold$url$noColor");
338 }
339 }
340
341 if (suite.platform.isHeadless) {
342 var url = suite.environment.remoteDebuggerUrl;
343 if (url == null) {
344 print("${yellow}Remote debugger URL not found.$noColor");
345 } else {
346 print("Remote debugger URL: $bold$url$noColor");
347 }
348 }
349
350 var buffer = new StringBuffer(
351 "${bold}The test runner is paused.${noColor} ");
352 if (!suite.platform.isHeadless) {
353 buffer.write("Open the dev console in ${suite.platform} ");
354 } else {
355 buffer.write("Open the remote debugger ");
356 }
357 if (suite.platform.isDartVM) buffer.write("or the Observatory ");
358
359 buffer.write("and set breakpoints. Once you're finished, return to this "
360 "terminal and press Enter.");
361
362 print(wordWrap(buffer.toString()));
363
364 await inCompletionOrder([
365 suite.environment.displayPause(),
366 cancelableNext(stdinLines)
367 ]).first;
368 } finally {
369 _reporter.resume();
370 }
371 }
372 } 310 }
OLDNEW
« no previous file with comments | « lib/src/backend/live_test.dart ('k') | lib/src/runner/browser/iframe_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698