| Index: lib/src/executable.dart
|
| diff --git a/lib/src/executable.dart b/lib/src/executable.dart
|
| index b1a792e2948a473b35c1f7c6df7e044a6980d17b..0664f23a87a2e588ac2d5c35eb907c72dd03d5f5 100644
|
| --- a/lib/src/executable.dart
|
| +++ b/lib/src/executable.dart
|
| @@ -7,22 +7,14 @@
|
| // bin.
|
| library test.executable;
|
|
|
| -import 'dart:async';
|
| import 'dart:io';
|
|
|
| -import 'package:async/async.dart';
|
| import 'package:stack_trace/stack_trace.dart';
|
| import 'package:yaml/yaml.dart';
|
|
|
| -import 'backend/metadata.dart';
|
| +import 'runner.dart';
|
| import 'runner/application_exception.dart';
|
| import 'runner/configuration.dart';
|
| -import 'runner/engine.dart';
|
| -import 'runner/load_exception.dart';
|
| -import 'runner/load_suite.dart';
|
| -import 'runner/loader.dart';
|
| -import 'runner/reporter/compact.dart';
|
| -import 'runner/reporter/expanded.dart';
|
| import 'util/exit_codes.dart' as exit_codes;
|
| import 'utils.dart';
|
|
|
| @@ -66,23 +58,22 @@ bool get _usesTransformer {
|
| });
|
| }
|
|
|
| -Configuration _configuration;
|
| -
|
| main(List<String> args) async {
|
| + var configuration;
|
| try {
|
| - _configuration = new Configuration.parse(args);
|
| + configuration = new Configuration.parse(args);
|
| } on FormatException catch (error) {
|
| _printUsage(error.message);
|
| exitCode = exit_codes.usage;
|
| return;
|
| }
|
|
|
| - if (_configuration.help) {
|
| + if (configuration.help) {
|
| _printUsage();
|
| return;
|
| }
|
|
|
| - if (_configuration.version) {
|
| + if (configuration.version) {
|
| if (!_printVersion()) {
|
| stderr.writeln("Couldn't find version number.");
|
| exitCode = exit_codes.data;
|
| @@ -90,7 +81,7 @@ main(List<String> args) async {
|
| return;
|
| }
|
|
|
| - if (_configuration.pubServeUrl != null && !_usesTransformer) {
|
| + if (configuration.pubServeUrl != null && !_usesTransformer) {
|
| stderr.write('''
|
| When using --pub-serve, you must include the "test/pub_serve" transformer in
|
| your pubspec:
|
| @@ -103,97 +94,28 @@ transformers:
|
| return;
|
| }
|
|
|
| - if (!_configuration.explicitPaths &&
|
| - !new Directory(_configuration.paths.single).existsSync()) {
|
| + if (!configuration.explicitPaths &&
|
| + !new Directory(configuration.paths.single).existsSync()) {
|
| _printUsage('No test files were passed and the default "test/" '
|
| "directory doesn't exist.");
|
| exitCode = exit_codes.data;
|
| return;
|
| }
|
|
|
| - var metadata = new Metadata(
|
| - verboseTrace: _configuration.verboseTrace);
|
| - var loader = new Loader(_configuration.platforms,
|
| - pubServeUrl: _configuration.pubServeUrl,
|
| - packageRoot: _configuration.packageRoot,
|
| - color: _configuration.color,
|
| - metadata: metadata,
|
| - jsTrace: _configuration.jsTrace);
|
| + var runner = new Runner(configuration);
|
|
|
| - var closed = false;
|
| var signalSubscription;
|
| - signalSubscription = _signals.listen((_) {
|
| - closed = true;
|
| + close() async {
|
| + if (signalSubscription == null) return;
|
| signalSubscription.cancel();
|
| - loader.close();
|
| - });
|
| -
|
| - try {
|
| - var engine = new Engine(concurrency: _configuration.concurrency);
|
| -
|
| - var watch = _configuration.reporter == "compact"
|
| - ? CompactReporter.watch
|
| - : ExpandedReporter.watch;
|
| -
|
| - watch(
|
| - engine,
|
| - color: _configuration.color,
|
| - verboseTrace: _configuration.verboseTrace,
|
| - printPath: _configuration.paths.length > 1 ||
|
| - new Directory(_configuration.paths.single).existsSync(),
|
| - printPlatform: _configuration.platforms.length > 1);
|
| -
|
| - // Override the signal handler to close [reporter]. [loader] will still be
|
| - // closed in the [whenComplete] below.
|
| - signalSubscription.onData((_) async {
|
| - closed = true;
|
| - signalSubscription.cancel();
|
| -
|
| - // Wait a bit to print this message, since printing it eagerly looks weird
|
| - // if the tests then finish immediately.
|
| - var timer = new Timer(new Duration(seconds: 1), () {
|
| - // Print a blank line first to ensure that this doesn't interfere with
|
| - // the compact reporter's unfinished line.
|
| - print("");
|
| - print("Waiting for current test(s) to finish.");
|
| - print("Press Control-C again to terminate immediately.");
|
| - });
|
| -
|
| - // Make sure we close the engine *before* the loader. Otherwise,
|
| - // LoadSuites provided by the loader may get into bad states.
|
| - await engine.close();
|
| - timer.cancel();
|
| - await loader.close();
|
| - });
|
| -
|
| - try {
|
| - var results = await Future.wait([
|
| - _loadSuites(loader, engine),
|
| - engine.run()
|
| - ], eagerError: true);
|
| -
|
| - if (closed) return;
|
| -
|
| - // Explicitly check "== true" here because [engine.run] can return `null`
|
| - // if the engine was closed prematurely.
|
| - exitCode = results.last == true ? 0 : 1;
|
| - } finally {
|
| - signalSubscription.cancel();
|
| - await engine.close();
|
| - }
|
| + signalSubscription = null;
|
| + await runner.close();
|
| + }
|
|
|
| - if (engine.passed.length == 0 && engine.failed.length == 0 &&
|
| - engine.skipped.length == 0 && _configuration.pattern != null) {
|
| - stderr.write('No tests match ');
|
| + signalSubscription = _signals.listen((_) => close());
|
|
|
| - if (_configuration.pattern is RegExp) {
|
| - var pattern = (_configuration.pattern as RegExp).pattern;
|
| - stderr.writeln('regular expression "$pattern".');
|
| - } else {
|
| - stderr.writeln('"${_configuration.pattern}".');
|
| - }
|
| - exitCode = exit_codes.data;
|
| - }
|
| + try {
|
| + exitCode = (await runner.run()) ? 0 : 1;
|
| } on ApplicationException catch (error) {
|
| stderr.writeln(error.message);
|
| exitCode = exit_codes.data;
|
| @@ -206,46 +128,10 @@ transformers:
|
| "with the stack trace and instructions for reproducing the error.");
|
| exitCode = exit_codes.software;
|
| } finally {
|
| - signalSubscription.cancel();
|
| - await loader.close();
|
| + await close();
|
| }
|
| }
|
|
|
| -/// Load the test suites in [_configuration.paths] that match
|
| -/// [_configuration.pattern] and pass them to [engine].
|
| -///
|
| -/// This completes once all the tests have been added to the engine. It does not
|
| -/// run the engine.
|
| -Future _loadSuites(Loader loader, Engine engine) async {
|
| - var group = new FutureGroup();
|
| -
|
| - mergeStreams(_configuration.paths.map((path) {
|
| - if (new Directory(path).existsSync()) return loader.loadDir(path);
|
| - if (new File(path).existsSync()) return loader.loadFile(path);
|
| -
|
| - return new Stream.fromIterable([
|
| - new LoadSuite("loading $path", () =>
|
| - throw new LoadException(path, 'Does not exist.'))
|
| - ]);
|
| - })).listen((loadSuite) {
|
| - group.add(new Future.sync(() {
|
| - engine.suiteSink.add(loadSuite.changeSuite((suite) {
|
| - if (_configuration.pattern == null) return suite;
|
| - return suite.change(tests: suite.tests.where(
|
| - (test) => test.name.contains(_configuration.pattern)));
|
| - }));
|
| - }));
|
| - }, onError: (error, stackTrace) {
|
| - group.add(new Future.error(error, stackTrace));
|
| - }, onDone: group.close);
|
| -
|
| - await group.future;
|
| -
|
| - // Once we've loaded all the suites, notify the engine that no more will be
|
| - // coming.
|
| - engine.suiteSink.close();
|
| -}
|
| -
|
| /// Print usage information for this command.
|
| ///
|
| /// If [error] is passed, it's used in place of the usage message and the whole
|
|
|