| OLD | NEW |
| 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.engine; | 5 library test.runner.engine; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:async/async.dart' hide Result; | 10 import 'package:async/async.dart' hide Result; |
| 11 import 'package:collection/collection.dart'; | 11 import 'package:collection/collection.dart'; |
| 12 import 'package:pool/pool.dart'; | 12 import 'package:pool/pool.dart'; |
| 13 | 13 |
| 14 import '../backend/live_test.dart'; | 14 import '../backend/live_test.dart'; |
| 15 import '../backend/live_test_controller.dart'; | 15 import '../backend/live_test_controller.dart'; |
| 16 import '../backend/state.dart'; | 16 import '../backend/state.dart'; |
| 17 import '../backend/suite.dart'; | |
| 18 import '../backend/test.dart'; | 17 import '../backend/test.dart'; |
| 19 import 'load_suite.dart'; | 18 import 'load_suite.dart'; |
| 19 import 'runner_suite.dart'; |
| 20 | 20 |
| 21 /// An [Engine] manages a run that encompasses multiple test suites. | 21 /// An [Engine] manages a run that encompasses multiple test suites. |
| 22 /// | 22 /// |
| 23 /// Test suites are provided by passing them into [suiteSink]. Once all suites | 23 /// Test suites are provided by passing them into [suiteSink]. Once all suites |
| 24 /// have been provided, the user should close [suiteSink] to indicate this. | 24 /// have been provided, the user should close [suiteSink] to indicate this. |
| 25 /// [run] won't terminate until [suiteSink] is closed. Suites will be run in the | 25 /// [run] won't terminate until [suiteSink] is closed. Suites will be run in the |
| 26 /// order they're provided to [suiteSink]. Tests within those suites will | 26 /// order they're provided to [suiteSink]. Tests within those suites will |
| 27 /// likewise be run in the order of [Suite.tests]. | 27 /// likewise be run in the order of [Suite.tests]. |
| 28 /// | 28 /// |
| 29 /// The current status of every test is visible via [liveTests]. [onTestStarted] | 29 /// The current status of every test is visible via [liveTests]. [onTestStarted] |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 Future<bool> get success async { | 77 Future<bool> get success async { |
| 78 await _group.future; | 78 await _group.future; |
| 79 if (_closedBeforeDone) return null; | 79 if (_closedBeforeDone) return null; |
| 80 return liveTests.every((liveTest) => | 80 return liveTests.every((liveTest) => |
| 81 liveTest.state.result == Result.success); | 81 liveTest.state.result == Result.success); |
| 82 } | 82 } |
| 83 | 83 |
| 84 /// A group of futures for each test suite. | 84 /// A group of futures for each test suite. |
| 85 final _group = new FutureGroup(); | 85 final _group = new FutureGroup(); |
| 86 | 86 |
| 87 /// A sink used to pass [Suite]s in to the engine to run. | 87 /// A sink used to pass [RunnerSuite]s in to the engine to run. |
| 88 /// | 88 /// |
| 89 /// Suites may be added as quickly as they're available; the Engine will only | 89 /// Suites may be added as quickly as they're available; the Engine will only |
| 90 /// run as many as necessary at a time based on its concurrency settings. | 90 /// run as many as necessary at a time based on its concurrency settings. |
| 91 /// | 91 /// |
| 92 /// Suites added to the sink will be closed by the engine based on its | 92 /// Suites added to the sink will be closed by the engine based on its |
| 93 /// internal logic. | 93 /// internal logic. |
| 94 Sink<Suite> get suiteSink => new DelegatingSink(_suiteController.sink); | 94 Sink<RunnerSuite> get suiteSink => new DelegatingSink(_suiteController.sink); |
| 95 final _suiteController = new StreamController<Suite>(); | 95 final _suiteController = new StreamController<RunnerSuite>(); |
| 96 | 96 |
| 97 /// All the currently-known tests that have run, are running, or will run. | 97 /// All the currently-known tests that have run, are running, or will run. |
| 98 /// | 98 /// |
| 99 /// These are [LiveTest]s, representing the in-progress state of each test. | 99 /// These are [LiveTest]s, representing the in-progress state of each test. |
| 100 /// Tests that have not yet begun running are marked [Status.pending]; tests | 100 /// Tests that have not yet begun running are marked [Status.pending]; tests |
| 101 /// that have finished are marked [Status.complete]. | 101 /// that have finished are marked [Status.complete]. |
| 102 /// | 102 /// |
| 103 /// This is guaranteed to contain the same tests as the union of [passed], | 103 /// This is guaranteed to contain the same tests as the union of [passed], |
| 104 /// [skipped], [failed], and [active]. | 104 /// [skipped], [failed], and [active]. |
| 105 /// | 105 /// |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 }).catchError((_) { | 157 }).catchError((_) { |
| 158 // Don't top-level errors. They'll be thrown via [success] anyway. | 158 // Don't top-level errors. They'll be thrown via [success] anyway. |
| 159 }); | 159 }); |
| 160 } | 160 } |
| 161 | 161 |
| 162 /// Creates an [Engine] that will run all tests in [suites]. | 162 /// Creates an [Engine] that will run all tests in [suites]. |
| 163 /// | 163 /// |
| 164 /// [concurrency] controls how many suites are run at once. An engine | 164 /// [concurrency] controls how many suites are run at once. An engine |
| 165 /// constructed this way will automatically close its [suiteSink], meaning | 165 /// constructed this way will automatically close its [suiteSink], meaning |
| 166 /// that no further suites may be provided. | 166 /// that no further suites may be provided. |
| 167 factory Engine.withSuites(List<Suite> suites, {int concurrency}) { | 167 factory Engine.withSuites(List<RunnerSuite> suites, {int concurrency}) { |
| 168 var engine = new Engine(concurrency: concurrency); | 168 var engine = new Engine(concurrency: concurrency); |
| 169 for (var suite in suites) engine.suiteSink.add(suite); | 169 for (var suite in suites) engine.suiteSink.add(suite); |
| 170 engine.suiteSink.close(); | 170 engine.suiteSink.close(); |
| 171 return engine; | 171 return engine; |
| 172 } | 172 } |
| 173 | 173 |
| 174 /// Runs all tests in all suites defined by this engine. | 174 /// Runs all tests in all suites defined by this engine. |
| 175 /// | 175 /// |
| 176 /// This returns `true` if all tests succeed, and `false` otherwise. It will | 176 /// This returns `true` if all tests succeed, and `false` otherwise. It will |
| 177 /// only return once all tests have finished running and [suiteSink] has been | 177 /// only return once all tests have finished running and [suiteSink] has been |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 | 246 |
| 247 loadResource.allowRelease(() => suite.close()); | 247 loadResource.allowRelease(() => suite.close()); |
| 248 }); | 248 }); |
| 249 })); | 249 })); |
| 250 }, onDone: _group.close); | 250 }, onDone: _group.close); |
| 251 | 251 |
| 252 return success; | 252 return success; |
| 253 } | 253 } |
| 254 | 254 |
| 255 /// Returns a dummy [LiveTest] for a test marked as "skip". | 255 /// Returns a dummy [LiveTest] for a test marked as "skip". |
| 256 LiveTest _skippedTest(Suite suite, Test test) { | 256 LiveTest _skippedTest(RunnerSuite suite, Test test) { |
| 257 var controller; | 257 var controller; |
| 258 controller = new LiveTestController(suite, test, () { | 258 controller = new LiveTestController(suite, test, () { |
| 259 controller.setState(const State(Status.running, Result.success)); | 259 controller.setState(const State(Status.running, Result.success)); |
| 260 controller.setState(const State(Status.complete, Result.success)); | 260 controller.setState(const State(Status.complete, Result.success)); |
| 261 controller.completer.complete(); | 261 controller.completer.complete(); |
| 262 }, () {}); | 262 }, () {}); |
| 263 return controller.liveTest; | 263 return controller.liveTest; |
| 264 } | 264 } |
| 265 | 265 |
| 266 /// Adds listeners for [suite]. | 266 /// Adds listeners for [suite]. |
| 267 /// | 267 /// |
| 268 /// Load suites have specific logic apart from normal test suites. | 268 /// Load suites have specific logic apart from normal test suites. |
| 269 Future<Suite> _addLoadSuite(LoadSuite suite) async { | 269 Future<RunnerSuite> _addLoadSuite(LoadSuite suite) async { |
| 270 var liveTest = await suite.tests.single.load(suite); | 270 var liveTest = await suite.tests.single.load(suite); |
| 271 | 271 |
| 272 _activeLoadTests.add(liveTest); | 272 _activeLoadTests.add(liveTest); |
| 273 | 273 |
| 274 // Only surface the load test if there are no other tests currently running. | 274 // Only surface the load test if there are no other tests currently running. |
| 275 if (_active.isEmpty) { | 275 if (_active.isEmpty) { |
| 276 _liveTests.add(liveTest); | 276 _liveTests.add(liveTest); |
| 277 _active.add(liveTest); | 277 _active.add(liveTest); |
| 278 } | 278 } |
| 279 | 279 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 | 325 |
| 326 // Close the running tests first so that we're sure to wait for them to | 326 // Close the running tests first so that we're sure to wait for them to |
| 327 // finish before we close their suites and cause them to become unloaded. | 327 // finish before we close their suites and cause them to become unloaded. |
| 328 var allLiveTests = liveTests.toSet()..addAll(_activeLoadTests); | 328 var allLiveTests = liveTests.toSet()..addAll(_activeLoadTests); |
| 329 await Future.wait(allLiveTests.map((liveTest) => liveTest.close())); | 329 await Future.wait(allLiveTests.map((liveTest) => liveTest.close())); |
| 330 | 330 |
| 331 var allSuites = allLiveTests.map((liveTest) => liveTest.suite).toSet(); | 331 var allSuites = allLiveTests.map((liveTest) => liveTest.suite).toSet(); |
| 332 await Future.wait(allSuites.map((suite) => suite.close())); | 332 await Future.wait(allSuites.map((suite) => suite.close())); |
| 333 } | 333 } |
| 334 } | 334 } |
| OLD | NEW |