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:pool/pool.dart'; | 10 import 'package:pool/pool.dart'; |
11 | 11 |
12 import '../backend/live_test.dart'; | 12 import '../backend/live_test.dart'; |
| 13 import '../backend/live_test_controller.dart'; |
13 import '../backend/state.dart'; | 14 import '../backend/state.dart'; |
14 import '../backend/suite.dart'; | 15 import '../backend/suite.dart'; |
| 16 import '../backend/test.dart'; |
15 import '../utils.dart'; | 17 import '../utils.dart'; |
16 | 18 |
17 /// An [Engine] manages a run that encompasses multiple test suites. | 19 /// An [Engine] manages a run that encompasses multiple test suites. |
18 /// | 20 /// |
19 /// The current status of every test is visible via [liveTests]. [onTestStarted] | 21 /// The current status of every test is visible via [liveTests]. [onTestStarted] |
20 /// can also be used to be notified when a test is about to be run. | 22 /// can also be used to be notified when a test is about to be run. |
21 /// | 23 /// |
22 /// Suites will be run in the order they're provided to [new Engine]. Tests | 24 /// Suites will be run in the order they're provided to [new Engine]. Tests |
23 /// within those suites will likewise be run in the order of [Suite.tests]. | 25 /// within those suites will likewise be run in the order of [Suite.tests]. |
24 class Engine { | 26 class Engine { |
25 /// Whether [run] has been called yet. | 27 /// Whether [run] has been called yet. |
26 var _runCalled = false; | 28 var _runCalled = false; |
27 | 29 |
28 /// Whether [close] has been called. | 30 /// Whether [close] has been called. |
29 var _closed = false; | 31 var _closed = false; |
30 | 32 |
31 /// A pool that limits the number of test suites running concurrently. | 33 /// A pool that limits the number of test suites running concurrently. |
32 final Pool _pool; | 34 final Pool _pool; |
33 | 35 |
34 /// An unmodifiable list of tests to run. | 36 /// An unmodifiable list of tests to run. |
35 /// | 37 /// |
36 /// These are [LiveTest]s, representing the in-progress state of each test. | 38 /// These are [LiveTest]s, representing the in-progress state of each test. |
37 /// Tests that have not yet begun running are marked [Status.pending]; tests | 39 /// Tests that have not yet begun running are marked [Status.pending]; tests |
38 /// that have finished are marked [Status.complete]. | 40 /// that have finished are marked [Status.complete]. |
39 /// | 41 /// |
40 /// [LiveTest.run] must not be called on these tests. | 42 /// [LiveTest.run] must not be called on these tests. |
41 List<LiveTest> get liveTests => | 43 List<LiveTest> get liveTests => |
42 new UnmodifiableListView(flatten(_liveTestsBySuite)); | 44 new UnmodifiableListView(flatten(_liveTestsBySuite)); |
43 | 45 |
| 46 /// The tests in [liveTests], organized by their original test suite. |
| 47 /// |
| 48 /// This allows test suites to be run in parallel without running multiple |
| 49 /// tests in the same suite at once. |
44 final List<List<LiveTest>> _liveTestsBySuite; | 50 final List<List<LiveTest>> _liveTestsBySuite; |
45 | 51 |
46 /// A stream that emits each [LiveTest] as it's about to start running. | 52 /// A stream that emits each [LiveTest] as it's about to start running. |
47 /// | 53 /// |
48 /// This is guaranteed to fire before [LiveTest.onStateChange] first fires. | 54 /// This is guaranteed to fire before [LiveTest.onStateChange] first fires. |
49 Stream<LiveTest> get onTestStarted => _onTestStartedController.stream; | 55 Stream<LiveTest> get onTestStarted => _onTestStartedController.stream; |
50 final _onTestStartedController = new StreamController<LiveTest>.broadcast(); | 56 final _onTestStartedController = new StreamController<LiveTest>.broadcast(); |
51 | 57 |
| 58 /// Returns the tests in [suites] grouped by suite. |
| 59 /// |
| 60 /// Also replaces tests marked as "skip" with dummy [LiveTest]s. |
| 61 static List<List<LiveTest>> _computeLiveTestsBySuite(Iterable<Suite> suites) { |
| 62 return suites.map((suite) { |
| 63 return suite.tests.map((test) { |
| 64 return test.metadata.skip |
| 65 ? _skippedTest(suite, test) |
| 66 : test.load(suite); |
| 67 }).toList(); |
| 68 }).toList(); |
| 69 } |
| 70 |
| 71 /// Returns a dummy [LiveTest] for a test marked as "skip". |
| 72 static LiveTest _skippedTest(Suite suite, Test test) { |
| 73 var controller; |
| 74 controller = new LiveTestController(suite, test, () { |
| 75 controller.setState(const State(Status.running, Result.success)); |
| 76 controller.setState(const State(Status.complete, Result.success)); |
| 77 controller.completer.complete(); |
| 78 }, () {}); |
| 79 return controller.liveTest; |
| 80 } |
| 81 |
52 /// Creates an [Engine] that will run all tests in [suites]. | 82 /// Creates an [Engine] that will run all tests in [suites]. |
53 Engine(Iterable<Suite> suites, {int concurrency}) | 83 Engine(Iterable<Suite> suites, {int concurrency}) |
54 : _liveTestsBySuite = suites.map((suite) => | 84 : _liveTestsBySuite = _computeLiveTestsBySuite(suites), |
55 suite.tests.map((test) => test.load(suite)).toList()).toList(), | |
56 _pool = new Pool(concurrency == null ? 1 : concurrency); | 85 _pool = new Pool(concurrency == null ? 1 : concurrency); |
57 | 86 |
58 /// Runs all tests in all suites defined by this engine. | 87 /// Runs all tests in all suites defined by this engine. |
59 /// | 88 /// |
60 /// This returns `true` if all tests succeed, and `false` otherwise. It will | 89 /// This returns `true` if all tests succeed, and `false` otherwise. It will |
61 /// only return once all tests have finished running. | 90 /// only return once all tests have finished running. |
62 Future<bool> run() { | 91 Future<bool> run() { |
63 if (_runCalled) { | 92 if (_runCalled) { |
64 throw new StateError("Engine.run() may not be called more than once."); | 93 throw new StateError("Engine.run() may not be called more than once."); |
65 } | 94 } |
(...skipping 23 matching lines...) Expand all Loading... |
89 /// engine should release any resources it has allocated. | 118 /// engine should release any resources it has allocated. |
90 /// | 119 /// |
91 /// Any actively-running tests are also closed. VM tests are allowed to finish | 120 /// Any actively-running tests are also closed. VM tests are allowed to finish |
92 /// running so that any modifications they've made to the filesystem can be | 121 /// running so that any modifications they've made to the filesystem can be |
93 /// cleaned up. | 122 /// cleaned up. |
94 Future close() { | 123 Future close() { |
95 _closed = true; | 124 _closed = true; |
96 return Future.wait(liveTests.map((liveTest) => liveTest.close())); | 125 return Future.wait(liveTests.map((liveTest) => liveTest.close())); |
97 } | 126 } |
98 } | 127 } |
OLD | NEW |