| Index: lib/src/runner/debugger.dart
|
| diff --git a/lib/src/runner/debugger.dart b/lib/src/runner/debugger.dart
|
| index 31ce04123b0052c8690e0dd7a322b8a3eb8f2e01..efea0c8da61c83cd8ee514b5bf75e3a13a3f315c 100644
|
| --- a/lib/src/runner/debugger.dart
|
| +++ b/lib/src/runner/debugger.dart
|
| @@ -1,39 +1,116 @@
|
| -Future debug(Configuration config, Engine engine, Reporter reporter,
|
| - LoadSuite loadSuite) async {
|
| - // Make the underlying suite null so that the engine doesn't start running
|
| - // it immediately.
|
| - _engine.suiteSink.add(loadSuite.changeSuite((_) => null));
|
| -
|
| - var suite = await loadSuite.suite;
|
| - if (suite == null) return;
|
| -
|
| - var debugger = new _Debugger(config, reporter, suite);
|
| - try {
|
| - await debugger._pause();
|
| - if (_closed) return;
|
| -
|
| - debugger._listen();
|
| - _engine.suiteSink.add(suite);
|
| - await _engine.onIdle.first;
|
| - } finally {
|
| - debugger._close();
|
| - }
|
| +// 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.
|
| +
|
| +library test.runner.debugger;
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'package:async/async.dart';
|
| +
|
| +import '../backend/live_test.dart';
|
| +import '../backend/test_platform.dart';
|
| +import '../util/io.dart';
|
| +import '../utils.dart';
|
| +import 'configuration.dart';
|
| +import 'console.dart';
|
| +import 'engine.dart';
|
| +import 'load_suite.dart';
|
| +import 'reporter.dart';
|
| +import 'runner_suite.dart';
|
| +
|
| +/// Runs [loadSuite] in debugging mode.
|
| +///
|
| +/// Runs the suite's tests using [engine]. The [reporter] should already be
|
| +/// watching [engine], and the [config] should contain the user configuration
|
| +/// for the test runner.
|
| +///
|
| +/// Returns a [CancelableOperation] that will complete once the suite has
|
| +/// finished running. If the operation is canceled, the debugger will clean up
|
| +/// any resources it allocated.
|
| +CancelableOperation debug(Configuration config, Engine engine,
|
| + Reporter reporter, LoadSuite loadSuite) {
|
| + var debugger;
|
| + var canceled = false;
|
| + return new CancelableOperation.fromFuture(() async {
|
| + // Make the underlying suite null so that the engine doesn't start running
|
| + // it immediately.
|
| + engine.suiteSink.add(loadSuite.changeSuite((_) => null));
|
| +
|
| + var suite = await loadSuite.suite;
|
| + if (canceled || suite == null) return;
|
| +
|
| + debugger = new _Debugger(config, engine, reporter, suite);
|
| + await debugger.run();
|
| + }(), onCancel: () {
|
| + canceled = true;
|
| + if (debugger != null) debugger.close();
|
| + });
|
| }
|
|
|
| +// TODO(nweiz): Test using the console and restarting a test once sdk#25369 is
|
| +// fixed and the VM service client is released and we can set Dartium
|
| +// breakpoints.
|
| +/// A debugger for a single test suite.
|
| class _Debugger {
|
| + /// The user configuration for the test runner.
|
| final Configuration _config;
|
|
|
| + /// The engine that will run the suite.
|
| + final Engine _engine;
|
| +
|
| + /// The reporter that's reporting [_engine]'s progress.
|
| final Reporter _reporter;
|
|
|
| + /// The suite to run.
|
| final RunnerSuite _suite;
|
|
|
| + /// The console through which the user can control the debugger.
|
| + ///
|
| + /// This is only visible when the test environment is paused, so as not to
|
| + /// overlap with the reporter's reporting.
|
| + final Console _console;
|
| +
|
| + /// The subscription to [_suite.onDebugging].
|
| StreamSubscription<bool> _onDebuggingSubscription;
|
|
|
| - bool _canDebug =>
|
| - _suite.platform != null && _suite.platform != TestPlatform.vm;
|
| + /// Whether [close] has been called.
|
| + bool _closed = false;
|
| +
|
| + _Debugger(Configuration config, this._engine, this._reporter, this._suite)
|
| + : _config = config,
|
| + _console = new Console(color: config.color) {
|
| + _console.registerCommand(
|
| + "restart", "Restart the current test after it finishes running.",
|
| + _restartTest);
|
| +
|
| + _onDebuggingSubscription = _suite.onDebugging.listen((debugging) {
|
| + if (debugging) {
|
| + _onDebugging();
|
| + } else {
|
| + _onNotDebugging();
|
| + }
|
| + });
|
| + }
|
| +
|
| + /// Runs the debugger.
|
| + ///
|
| + /// This prints information about the suite's debugger, then once the user has
|
| + /// had a chance to set breakpoints, runs the suite's tests.
|
| + Future run() async {
|
| + try {
|
| + await _pause();
|
| + if (_closed) return;
|
|
|
| - _Debugger(this._config, this._reporter, this._suite);
|
| + _engine.suiteSink.add(_suite);
|
| + await _engine.onIdle.first;
|
| + } finally {
|
| + close();
|
| + }
|
| + }
|
|
|
| + /// Prints URLs for the [_suite]'s debugger and waits for the user to tell the
|
| + /// suite to run.
|
| Future _pause() async {
|
| if (_suite.platform == null) return;
|
| if (_suite.platform == TestPlatform.vm) return;
|
| @@ -88,21 +165,36 @@ class _Debugger {
|
| }
|
| }
|
|
|
| - void _listen() {
|
| - _suite.onDebugging.listen((debugging) {
|
| - if (debugging) {
|
| - _onDebugging();
|
| - } else {
|
| - _onNotDebugging();
|
| - }
|
| - });
|
| + /// Handles the environment pausing to debug.
|
| + ///
|
| + /// This starts the interactive console.
|
| + void _onDebugging() {
|
| + _reporter.pause();
|
| +
|
| + print('\nEntering debugging console. Type "help" for help.');
|
| + _console.start();
|
| }
|
|
|
| - void _onDebugging(bool debugging) {
|
| - _reporter.pause();
|
| + /// Handles the environment starting up again.
|
| + ///
|
| + /// This closes the interactive console.
|
| + void _onNotDebugging() {
|
| + _reporter.resume();
|
| + _console.stop();
|
| + }
|
| +
|
| + /// Restarts the current test.
|
| + void _restartTest() {
|
| + var liveTest = _engine.active.single;
|
| + _engine.restartTest(liveTest);
|
| + print(wordWrap(
|
| + 'Will restart "${liveTest.test.name}" once it finishes running.'));
|
| }
|
|
|
| - void _close() {
|
| + /// Closes the debugger and releases its resources.
|
| + void close() {
|
| + _closed = true;
|
| _onDebuggingSubscription.cancel();
|
| + _console.stop();
|
| }
|
| }
|
|
|