| 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; |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 if (suite is LoadSuite) { | 198 if (suite is LoadSuite) { |
| 199 suite = await _addLoadSuite(suite); | 199 suite = await _addLoadSuite(suite); |
| 200 if (suite == null) { | 200 if (suite == null) { |
| 201 loadResource.release(); | 201 loadResource.release(); |
| 202 return; | 202 return; |
| 203 } | 203 } |
| 204 } | 204 } |
| 205 | 205 |
| 206 await _runPool.withResource(() async { | 206 await _runPool.withResource(() async { |
| 207 if (_closed) return; | 207 if (_closed) return; |
| 208 await _runGroup(suite, suite.group); | 208 await _runGroup(suite, suite.group, []); |
| 209 loadResource.allowRelease(() => suite.close()); | 209 loadResource.allowRelease(() => suite.close()); |
| 210 }); | 210 }); |
| 211 })); | 211 })); |
| 212 }, onDone: _group.close); | 212 }, onDone: _group.close); |
| 213 | 213 |
| 214 return success; | 214 return success; |
| 215 } | 215 } |
| 216 | 216 |
| 217 /// Runs all the entries in [entries] in sequence. | 217 /// Runs all the entries in [entries] in sequence. |
| 218 Future _runGroup(RunnerSuite suite, Group group) async { | 218 /// |
| 219 /// [parents] is a list of groups that contain [group]. It may be modified, |
| 220 /// but it's guaranteed to be in its original state once this function has |
| 221 /// finished. |
| 222 Future _runGroup(RunnerSuite suite, Group group, List<Group> parents) async { |
| 219 if (group.metadata.skip) { | 223 if (group.metadata.skip) { |
| 220 await _runLiveTest(_skippedTest(suite, group)); | 224 await _runLiveTest(_skippedTest(suite, group, parents)); |
| 221 return; | 225 return; |
| 222 } | 226 } |
| 223 | 227 |
| 224 var setUpAllSucceeded = true; | 228 var setUpAllSucceeded = true; |
| 225 if (group.setUpAll != null) { | 229 if (group.setUpAll != null) { |
| 226 var liveTest = group.setUpAll.load(suite); | 230 var liveTest = group.setUpAll.load(suite, groups: parents); |
| 227 await _runLiveTest(liveTest, countSuccess: false); | 231 await _runLiveTest(liveTest, countSuccess: false); |
| 228 setUpAllSucceeded = liveTest.state.result == Result.success; | 232 setUpAllSucceeded = liveTest.state.result == Result.success; |
| 229 } | 233 } |
| 230 | 234 |
| 231 if (!_closed && setUpAllSucceeded) { | 235 if (!_closed && setUpAllSucceeded) { |
| 232 for (var entry in group.entries) { | 236 parents.add(group); |
| 233 if (_closed) return; | 237 try { |
| 238 for (var entry in group.entries) { |
| 239 if (_closed) return; |
| 234 | 240 |
| 235 if (entry is Group) { | 241 if (entry is Group) { |
| 236 await _runGroup(suite, entry); | 242 await _runGroup(suite, entry, parents); |
| 237 } else if (entry.metadata.skip) { | 243 } else if (entry.metadata.skip) { |
| 238 await _runLiveTest(_skippedTest(suite, entry)); | 244 await _runLiveTest(_skippedTest(suite, entry, parents)); |
| 239 } else { | 245 } else { |
| 240 var test = entry as Test; | 246 var test = entry as Test; |
| 241 await _runLiveTest(test.load(suite)); | 247 await _runLiveTest(test.load(suite, groups: parents)); |
| 248 } |
| 242 } | 249 } |
| 250 } finally { |
| 251 parents.remove(group); |
| 243 } | 252 } |
| 244 } | 253 } |
| 245 | 254 |
| 246 // Even if we're closed or setUpAll failed, we want to run all the teardowns | 255 // Even if we're closed or setUpAll failed, we want to run all the teardowns |
| 247 // to ensure that any state is properly cleaned up. | 256 // to ensure that any state is properly cleaned up. |
| 248 if (group.tearDownAll != null) { | 257 if (group.tearDownAll != null) { |
| 249 var liveTest = group.tearDownAll.load(suite); | 258 var liveTest = group.tearDownAll.load(suite, groups: parents); |
| 250 await _runLiveTest(liveTest, countSuccess: false); | 259 await _runLiveTest(liveTest, countSuccess: false); |
| 251 if (_closed) await liveTest.close(); | 260 if (_closed) await liveTest.close(); |
| 252 } | 261 } |
| 253 } | 262 } |
| 254 | 263 |
| 255 /// Returns a dummy [LiveTest] for a test or group marked as "skip". | 264 /// Returns a dummy [LiveTest] for a test or group marked as "skip". |
| 256 LiveTest _skippedTest(RunnerSuite suite, GroupEntry entry) { | 265 /// |
| 266 /// [parents] is a list of groups that contain [entry]. |
| 267 LiveTest _skippedTest(RunnerSuite suite, GroupEntry entry, |
| 268 List<Group> parents) { |
| 257 // The netry name will be `null` for the root group. | 269 // The netry name will be `null` for the root group. |
| 258 var test = new LocalTest(entry.name ?? "(suite)", entry.metadata, () {}); | 270 var test = new LocalTest(entry.name ?? "(suite)", entry.metadata, () {}); |
| 259 | 271 |
| 260 var controller; | 272 var controller; |
| 261 controller = new LiveTestController(suite, test, () { | 273 controller = new LiveTestController(suite, test, () { |
| 262 controller.setState(const State(Status.running, Result.success)); | 274 controller.setState(const State(Status.running, Result.success)); |
| 263 controller.setState(const State(Status.complete, Result.success)); | 275 controller.setState(const State(Status.complete, Result.success)); |
| 264 controller.completer.complete(); | 276 controller.completer.complete(); |
| 265 }, () {}); | 277 }, () {}, groups: parents); |
| 266 return controller.liveTest; | 278 return controller.liveTest; |
| 267 } | 279 } |
| 268 | 280 |
| 269 /// Runs [liveTest]. | 281 /// Runs [liveTest]. |
| 270 /// | 282 /// |
| 271 /// If [countSuccess] is `true` (the default), the test is put into [passed] | 283 /// If [countSuccess] is `true` (the default), the test is put into [passed] |
| 272 /// if it succeeds. Otherwise, it's removed from [liveTests] entirely. | 284 /// if it succeeds. Otherwise, it's removed from [liveTests] entirely. |
| 273 Future _runLiveTest(LiveTest liveTest, {bool countSuccess: true}) async { | 285 Future _runLiveTest(LiveTest liveTest, {bool countSuccess: true}) async { |
| 274 _liveTests.add(liveTest); | 286 _liveTests.add(liveTest); |
| 275 _active.add(liveTest); | 287 _active.add(liveTest); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 var futures = allLiveTests.map((liveTest) => liveTest.close()).toList(); | 397 var futures = allLiveTests.map((liveTest) => liveTest.close()).toList(); |
| 386 | 398 |
| 387 // Closing the load pool will close the test suites as soon as their tests | 399 // Closing the load pool will close the test suites as soon as their tests |
| 388 // are done. For browser suites this is effectively immediate since their | 400 // are done. For browser suites this is effectively immediate since their |
| 389 // tests shut down as soon as they're closed, but for VM suites we may need | 401 // tests shut down as soon as they're closed, but for VM suites we may need |
| 390 // to wait for tearDowns or tearDownAlls to run. | 402 // to wait for tearDowns or tearDownAlls to run. |
| 391 futures.add(_loadPool.close()); | 403 futures.add(_loadPool.close()); |
| 392 await Future.wait(futures, eagerError: true); | 404 await Future.wait(futures, eagerError: true); |
| 393 } | 405 } |
| 394 } | 406 } |
| OLD | NEW |