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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 | 7 |
8 import 'package:async/async.dart' hide Result; | 8 import 'package:async/async.dart' hide Result; |
9 import 'package:collection/collection.dart'; | 9 import 'package:collection/collection.dart'; |
10 import 'package:pool/pool.dart'; | 10 import 'package:pool/pool.dart'; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 /// A sink used to pass [RunnerSuite]s in to the engine to run. | 88 /// A sink used to pass [RunnerSuite]s in to the engine to run. |
89 /// | 89 /// |
90 /// Suites may be added as quickly as they're available; the Engine will only | 90 /// Suites may be added as quickly as they're available; the Engine will only |
91 /// run as many as necessary at a time based on its concurrency settings. | 91 /// run as many as necessary at a time based on its concurrency settings. |
92 /// | 92 /// |
93 /// Suites added to the sink will be closed by the engine based on its | 93 /// Suites added to the sink will be closed by the engine based on its |
94 /// internal logic. | 94 /// internal logic. |
95 Sink<RunnerSuite> get suiteSink => new DelegatingSink(_suiteController.sink); | 95 Sink<RunnerSuite> get suiteSink => new DelegatingSink(_suiteController.sink); |
96 final _suiteController = new StreamController<RunnerSuite>(); | 96 final _suiteController = new StreamController<RunnerSuite>(); |
97 | 97 |
| 98 /// All the [RunnerSuite]s added to [suiteSink] so far. |
| 99 /// |
| 100 /// Note that if a [LoadSuite] is added, this will only contain that suite, |
| 101 /// not the suite it loads. |
| 102 Set<RunnerSuite> get addedSuites => new UnmodifiableSetView(_addedSuites); |
| 103 final _addedSuites = new Set<RunnerSuite>(); |
| 104 |
| 105 /// A broadcast that emits each [RunnerSuite] as it's added to the engine via |
| 106 /// [suiteSink]. |
| 107 /// |
| 108 /// Note that if a [LoadSuite] is added, this will only return that suite, not |
| 109 /// the suite it loads. |
| 110 /// |
| 111 /// This is guaranteed to fire after the suite is added to [addedSuites]. |
| 112 Stream<RunnerSuite> get onSuiteAdded => _onSuiteAddedController.stream; |
| 113 final _onSuiteAddedController = new StreamController<RunnerSuite>.broadcast(); |
| 114 |
98 /// All the currently-known tests that have run, are running, or will run. | 115 /// All the currently-known tests that have run, are running, or will run. |
99 /// | 116 /// |
100 /// These are [LiveTest]s, representing the in-progress state of each test. | 117 /// These are [LiveTest]s, representing the in-progress state of each test. |
101 /// Tests that have not yet begun running are marked [Status.pending]; tests | 118 /// Tests that have not yet begun running are marked [Status.pending]; tests |
102 /// that have finished are marked [Status.complete]. | 119 /// that have finished are marked [Status.complete]. |
103 /// | 120 /// |
104 /// This is guaranteed to contain the same tests as the union of [passed], | 121 /// This is guaranteed to contain the same tests as the union of [passed], |
105 /// [skipped], [failed], and [active]. | 122 /// [skipped], [failed], and [active]. |
106 /// | 123 /// |
107 /// [LiveTest.run] must not be called on these tests. | 124 /// [LiveTest.run] must not be called on these tests. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 /// This returns `true` if all tests succeed, and `false` otherwise. It will | 206 /// This returns `true` if all tests succeed, and `false` otherwise. It will |
190 /// only return once all tests have finished running and [suiteSink] has been | 207 /// only return once all tests have finished running and [suiteSink] has been |
191 /// closed. | 208 /// closed. |
192 Future<bool> run() { | 209 Future<bool> run() { |
193 if (_runCalled) { | 210 if (_runCalled) { |
194 throw new StateError("Engine.run() may not be called more than once."); | 211 throw new StateError("Engine.run() may not be called more than once."); |
195 } | 212 } |
196 _runCalled = true; | 213 _runCalled = true; |
197 | 214 |
198 _suiteController.stream.listen((suite) { | 215 _suiteController.stream.listen((suite) { |
| 216 _addedSuites.add(suite); |
| 217 _onSuiteAddedController.add(suite); |
| 218 |
199 _group.add(new Future.sync(() async { | 219 _group.add(new Future.sync(() async { |
200 var loadResource = await _loadPool.request(); | 220 var loadResource = await _loadPool.request(); |
201 | 221 |
202 if (suite is LoadSuite) { | 222 if (suite is LoadSuite) { |
203 suite = await _addLoadSuite(suite); | 223 suite = await _addLoadSuite(suite); |
204 if (suite == null) { | 224 if (suite == null) { |
205 loadResource.release(); | 225 loadResource.release(); |
206 return; | 226 return; |
207 } | 227 } |
208 } | 228 } |
209 | 229 |
210 await _runPool.withResource(() async { | 230 await _runPool.withResource(() async { |
211 if (_closed) return; | 231 if (_closed) return; |
212 await _runGroup(suite, suite.group, []); | 232 await _runGroup(suite, suite.group, []); |
213 loadResource.allowRelease(() => suite.close()); | 233 loadResource.allowRelease(() => suite.close()); |
214 }); | 234 }); |
215 })); | 235 })); |
216 }, onDone: _group.close); | 236 }, onDone: () { |
| 237 _onSuiteAddedController.close(); |
| 238 _group.close(); |
| 239 }); |
217 | 240 |
218 return success; | 241 return success; |
219 } | 242 } |
220 | 243 |
221 /// Runs all the entries in [entries] in sequence. | 244 /// Runs all the entries in [entries] in sequence. |
222 /// | 245 /// |
223 /// [parents] is a list of groups that contain [group]. It may be modified, | 246 /// [parents] is a list of groups that contain [group]. It may be modified, |
224 /// but it's guaranteed to be in its original state once this function has | 247 /// but it's guaranteed to be in its original state once this function has |
225 /// finished. | 248 /// finished. |
226 Future _runGroup(RunnerSuite suite, Group group, List<Group> parents) async { | 249 Future _runGroup(RunnerSuite suite, Group group, List<Group> parents) async { |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 /// Any actively-running tests are also closed. VM tests are allowed to finish | 430 /// Any actively-running tests are also closed. VM tests are allowed to finish |
408 /// running so that any modifications they've made to the filesystem can be | 431 /// running so that any modifications they've made to the filesystem can be |
409 /// cleaned up. | 432 /// cleaned up. |
410 /// | 433 /// |
411 /// **Note that closing the engine is not the same as closing [suiteSink].** | 434 /// **Note that closing the engine is not the same as closing [suiteSink].** |
412 /// Closing [suiteSink] indicates that no more input will be provided, closing | 435 /// Closing [suiteSink] indicates that no more input will be provided, closing |
413 /// the engine indicates that no more output should be emitted. | 436 /// the engine indicates that no more output should be emitted. |
414 Future close() async { | 437 Future close() async { |
415 _closed = true; | 438 _closed = true; |
416 if (_closedBeforeDone != null) _closedBeforeDone = true; | 439 if (_closedBeforeDone != null) _closedBeforeDone = true; |
| 440 _onSuiteAddedController.close(); |
417 _suiteController.close(); | 441 _suiteController.close(); |
418 | 442 |
419 // Close the running tests first so that we're sure to wait for them to | 443 // Close the running tests first so that we're sure to wait for them to |
420 // finish before we close their suites and cause them to become unloaded. | 444 // finish before we close their suites and cause them to become unloaded. |
421 var allLiveTests = liveTests.toSet() | 445 var allLiveTests = liveTests.toSet() |
422 ..addAll(_activeLoadTests) | 446 ..addAll(_activeLoadTests) |
423 ..addAll(_hidden); | 447 ..addAll(_hidden); |
424 var futures = allLiveTests.map((liveTest) => liveTest.close()).toList(); | 448 var futures = allLiveTests.map((liveTest) => liveTest.close()).toList(); |
425 | 449 |
426 // Closing the load pool will close the test suites as soon as their tests | 450 // Closing the load pool will close the test suites as soon as their tests |
427 // are done. For browser suites this is effectively immediate since their | 451 // are done. For browser suites this is effectively immediate since their |
428 // tests shut down as soon as they're closed, but for VM suites we may need | 452 // tests shut down as soon as they're closed, but for VM suites we may need |
429 // to wait for tearDowns or tearDownAlls to run. | 453 // to wait for tearDowns or tearDownAlls to run. |
430 futures.add(_loadPool.close()); | 454 futures.add(_loadPool.close()); |
431 await Future.wait(futures, eagerError: true); | 455 await Future.wait(futures, eagerError: true); |
432 } | 456 } |
433 } | 457 } |
OLD | NEW |