OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
6 * Classes and methods for executing tests. | 6 * Classes and methods for executing tests. |
7 * | 7 * |
8 * This module includes: | 8 * This module includes: |
9 * - Managing parallel execution of tests, including timeout checks. | 9 * - Managing parallel execution of tests, including timeout checks. |
10 * - Evaluating the output of each test as pass/fail/crash/timeout. | 10 * - Evaluating the output of each test as pass/fail/crash/timeout. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 } | 79 } |
80 | 80 |
81 operator ==(other) => | 81 operator ==(other) => |
82 identical(this, other) || | 82 identical(this, other) || |
83 (runtimeType == other.runtimeType && _equal(other)); | 83 (runtimeType == other.runtimeType && _equal(other)); |
84 | 84 |
85 void _buildHashCode(HashCodeBuilder builder) { | 85 void _buildHashCode(HashCodeBuilder builder) { |
86 builder.addJson(displayName); | 86 builder.addJson(displayName); |
87 } | 87 } |
88 | 88 |
89 bool _equal(Command other) => | 89 bool _equal(covariant Command other) => |
90 hashCode == other.hashCode && displayName == other.displayName; | 90 hashCode == other.hashCode && displayName == other.displayName; |
91 | 91 |
92 String toString() => reproductionCommand; | 92 String toString() => reproductionCommand; |
93 | 93 |
94 Future<bool> get outputIsUpToDate => new Future.value(false); | 94 Future<bool> get outputIsUpToDate => new Future.value(false); |
95 } | 95 } |
96 | 96 |
97 class ProcessCommand extends Command { | 97 class ProcessCommand extends Command { |
98 /** Path to the executable of this command. */ | 98 /** Path to the executable of this command. */ |
99 String executable; | 99 String executable; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 String htmlFile, | 258 String htmlFile, |
259 List<String> options, | 259 List<String> options, |
260 List<String> dartFlags, | 260 List<String> dartFlags, |
261 Map<String, String> environmentOverrides) | 261 Map<String, String> environmentOverrides) |
262 : super._("content_shell", executable, _getArguments(options, htmlFile), | 262 : super._("content_shell", executable, _getArguments(options, htmlFile), |
263 _getEnvironment(environmentOverrides, dartFlags)); | 263 _getEnvironment(environmentOverrides, dartFlags)); |
264 | 264 |
265 // Cache the modified environments in a map from the old environment and | 265 // Cache the modified environments in a map from the old environment and |
266 // the string of Dart flags to the new environment. Avoid creating new | 266 // the string of Dart flags to the new environment. Avoid creating new |
267 // environment object for each command object. | 267 // environment object for each command object. |
268 static Map<AddFlagsKey, Map> environments = new Map<AddFlagsKey, Map>(); | 268 static Map<AddFlagsKey, Map> environments = <AddFlagsKey, Map>{}; |
269 | 269 |
270 static Map _getEnvironment(Map env, List<String> dartFlags) { | 270 static Map<String, String> _getEnvironment( |
| 271 Map<String, String> env, List<String> dartFlags) { |
271 var needDartFlags = dartFlags != null && dartFlags.length > 0; | 272 var needDartFlags = dartFlags != null && dartFlags.length > 0; |
272 if (needDartFlags) { | 273 if (needDartFlags) { |
273 if (env == null) { | 274 if (env == null) { |
274 env = const {}; | 275 env = const <String, String>{}; |
275 } | 276 } |
276 var flags = dartFlags.join(' '); | 277 var flags = dartFlags.join(' '); |
277 return environments.putIfAbsent( | 278 return environments.putIfAbsent( |
278 new AddFlagsKey(flags, env), | 279 new AddFlagsKey(flags, env), |
279 () => new Map.from(env) | 280 () => new Map.from(env) |
280 ..addAll({'DART_FLAGS': flags, 'DART_FORWARDING_PRINT': '1'})); | 281 ..addAll({'DART_FLAGS': flags, 'DART_FORWARDING_PRINT': '1'})); |
281 } | 282 } |
282 return env; | 283 return env; |
283 } | 284 } |
284 | 285 |
285 static List<String> _getArguments(List<String> options, String htmlFile) { | 286 static List<String> _getArguments(List<String> options, String htmlFile) { |
286 var arguments = new List.from(options); | 287 var arguments = options.toList(); |
287 arguments.add(htmlFile); | 288 arguments.add(htmlFile); |
288 return arguments; | 289 return arguments; |
289 } | 290 } |
290 | 291 |
291 int get maxNumRetries => 3; | 292 int get maxNumRetries => 3; |
292 } | 293 } |
293 | 294 |
294 class BrowserTestCommand extends Command { | 295 class BrowserTestCommand extends Command { |
295 final String browser; | 296 final String browser; |
296 final String url; | 297 final String url; |
297 final Map configuration; | 298 final Map configuration; |
298 final bool retry; | 299 final bool retry; |
299 | 300 |
300 BrowserTestCommand._( | 301 BrowserTestCommand._( |
301 String _browser, this.url, this.configuration, this.retry) | 302 String _browser, this.url, this.configuration, this.retry) |
302 : super._(_browser), | 303 : browser = _browser, |
303 browser = _browser; | 304 super._(_browser); |
304 | 305 |
305 void _buildHashCode(HashCodeBuilder builder) { | 306 void _buildHashCode(HashCodeBuilder builder) { |
306 super._buildHashCode(builder); | 307 super._buildHashCode(builder); |
307 builder.addJson(browser); | 308 builder.addJson(browser); |
308 builder.addJson(url); | 309 builder.addJson(url); |
309 builder.add(configuration); | 310 builder.add(configuration); |
310 builder.add(retry); | 311 builder.add(retry); |
311 } | 312 } |
312 | 313 |
313 bool _equal(BrowserTestCommand other) => | 314 bool _equal(BrowserTestCommand other) => |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 String displayName, String executable, List<String> arguments, | 437 String displayName, String executable, List<String> arguments, |
437 [Map<String, String> environmentOverrides = null]) | 438 [Map<String, String> environmentOverrides = null]) |
438 : super._(displayName, executable, arguments, environmentOverrides); | 439 : super._(displayName, executable, arguments, environmentOverrides); |
439 } | 440 } |
440 | 441 |
441 class PubCommand extends ProcessCommand { | 442 class PubCommand extends ProcessCommand { |
442 final String command; | 443 final String command; |
443 | 444 |
444 PubCommand._(String pubCommand, String pubExecutable, | 445 PubCommand._(String pubCommand, String pubExecutable, |
445 String pubspecYamlDirectory, String pubCacheDirectory, List<String> args) | 446 String pubspecYamlDirectory, String pubCacheDirectory, List<String> args) |
446 : super._( | 447 : command = pubCommand, |
| 448 super._( |
447 'pub_$pubCommand', | 449 'pub_$pubCommand', |
448 new io.File(pubExecutable).absolute.path, | 450 new io.File(pubExecutable).absolute.path, |
449 [pubCommand]..addAll(args), | 451 [pubCommand]..addAll(args), |
450 {'PUB_CACHE': pubCacheDirectory}, | 452 {'PUB_CACHE': pubCacheDirectory}, |
451 pubspecYamlDirectory), | 453 pubspecYamlDirectory); |
452 command = pubCommand; | |
453 | 454 |
454 void _buildHashCode(HashCodeBuilder builder) { | 455 void _buildHashCode(HashCodeBuilder builder) { |
455 super._buildHashCode(builder); | 456 super._buildHashCode(builder); |
456 builder.addJson(command); | 457 builder.addJson(command); |
457 } | 458 } |
458 | 459 |
459 bool _equal(PubCommand other) => | 460 bool _equal(PubCommand other) => |
460 super._equal(other) && command == other.command; | 461 super._equal(other) && command == other.command; |
461 } | 462 } |
462 | 463 |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 */ | 912 */ |
912 abstract class CommandOutput { | 913 abstract class CommandOutput { |
913 Command get command; | 914 Command get command; |
914 | 915 |
915 Expectation result(TestCase testCase); | 916 Expectation result(TestCase testCase); |
916 | 917 |
917 bool get hasCrashed; | 918 bool get hasCrashed; |
918 | 919 |
919 bool get hasTimedOut; | 920 bool get hasTimedOut; |
920 | 921 |
921 bool didFail(testcase); | 922 bool didFail(TestCase testCase); |
922 | 923 |
923 bool hasFailed(TestCase testCase); | 924 bool hasFailed(TestCase testCase); |
924 | 925 |
925 bool get canRunDependendCommands; | 926 bool get canRunDependendCommands; |
926 | 927 |
927 bool get successful; // otherwise we might to retry running | 928 bool get successful; // otherwise we might to retry running |
928 | 929 |
929 Duration get time; | 930 Duration get time; |
930 | 931 |
931 int get exitCode; | 932 int get exitCode; |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1065 "zygote crash. Test ignored"); | 1066 "zygote crash. Test ignored"); |
1066 return true; | 1067 return true; |
1067 } | 1068 } |
1068 return false; | 1069 return false; |
1069 } | 1070 } |
1070 | 1071 |
1071 bool _infraFailure; | 1072 bool _infraFailure; |
1072 | 1073 |
1073 BrowserCommandOutputImpl( | 1074 BrowserCommandOutputImpl( |
1074 command, exitCode, timedOut, stdout, stderr, time, compilationSkipped) | 1075 command, exitCode, timedOut, stdout, stderr, time, compilationSkipped) |
1075 : super(command, exitCode, timedOut, stdout, stderr, time, | 1076 : _infraFailure = _failedBecauseOfFlakyInfrastructure(stderr), |
1076 compilationSkipped, 0), | 1077 super(command, exitCode, timedOut, stdout, stderr, time, |
1077 _infraFailure = _failedBecauseOfFlakyInfrastructure(stderr); | 1078 compilationSkipped, 0); |
1078 | 1079 |
1079 Expectation result(TestCase testCase) { | 1080 Expectation result(TestCase testCase) { |
1080 // Handle crashes and timeouts first | 1081 // Handle crashes and timeouts first |
1081 if (hasCrashed) return Expectation.CRASH; | 1082 if (hasCrashed) return Expectation.CRASH; |
1082 if (hasTimedOut) return Expectation.TIMEOUT; | 1083 if (hasTimedOut) return Expectation.TIMEOUT; |
1083 if (hasNonUtf8) return Expectation.NON_UTF8_ERROR; | 1084 if (hasNonUtf8) return Expectation.NON_UTF8_ERROR; |
1084 | 1085 |
1085 if (_infraFailure) { | 1086 if (_infraFailure) { |
1086 return Expectation.IGNORE; | 1087 return Expectation.IGNORE; |
1087 } | 1088 } |
(...skipping 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2238 } | 2239 } |
2239 | 2240 |
2240 void _timeoutHandler() { | 2241 void _timeoutHandler() { |
2241 _processExitHandler = makeExitHandler(">>> TEST TIMEOUT"); | 2242 _processExitHandler = makeExitHandler(">>> TEST TIMEOUT"); |
2242 _process.kill(); | 2243 _process.kill(); |
2243 } | 2244 } |
2244 | 2245 |
2245 _startProcess(callback) { | 2246 _startProcess(callback) { |
2246 assert(_command is ProcessCommand); | 2247 assert(_command is ProcessCommand); |
2247 var executable = _command.executable; | 2248 var executable = _command.executable; |
2248 var arguments = [] | 2249 var arguments = _command.batchArguments.toList(); |
2249 ..addAll(_command.batchArguments) | 2250 arguments.add('--batch'); |
2250 ..add('--batch'); | |
2251 var environment = new Map.from(io.Platform.environment); | 2251 var environment = new Map.from(io.Platform.environment); |
2252 if (_processEnvironmentOverrides != null) { | 2252 if (_processEnvironmentOverrides != null) { |
2253 for (var key in _processEnvironmentOverrides.keys) { | 2253 for (var key in _processEnvironmentOverrides.keys) { |
2254 environment[key] = _processEnvironmentOverrides[key]; | 2254 environment[key] = _processEnvironmentOverrides[key]; |
2255 } | 2255 } |
2256 } | 2256 } |
2257 Future processFuture = | 2257 Future processFuture = |
2258 io.Process.start(executable, arguments, environment: environment); | 2258 io.Process.start(executable, arguments, environment: environment); |
2259 processFuture.then((io.Process p) { | 2259 processFuture.then((io.Process p) { |
2260 _process = p; | 2260 _process = p; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2349 final command2node = new Map<Command, dgraph.Node>(); | 2349 final command2node = new Map<Command, dgraph.Node>(); |
2350 final command2testCases = new Map<Command, List<TestCase>>(); | 2350 final command2testCases = new Map<Command, List<TestCase>>(); |
2351 final remainingTestCases = new Set<TestCase>(); | 2351 final remainingTestCases = new Set<TestCase>(); |
2352 | 2352 |
2353 TestCaseEnqueuer(this.graph, this._onTestCaseAdded); | 2353 TestCaseEnqueuer(this.graph, this._onTestCaseAdded); |
2354 | 2354 |
2355 void enqueueTestSuites(List<TestSuite> testSuites) { | 2355 void enqueueTestSuites(List<TestSuite> testSuites) { |
2356 void newTest(TestCase testCase) { | 2356 void newTest(TestCase testCase) { |
2357 remainingTestCases.add(testCase); | 2357 remainingTestCases.add(testCase); |
2358 | 2358 |
2359 var lastNode; | 2359 dgraph.Node lastNode; |
2360 for (var command in testCase.commands) { | 2360 for (var command in testCase.commands) { |
2361 // Make exactly *one* node in the dependency graph for every command. | 2361 // Make exactly *one* node in the dependency graph for every command. |
2362 // This ensures that we never have two commands c1 and c2 in the graph | 2362 // This ensures that we never have two commands c1 and c2 in the graph |
2363 // with "c1 == c2". | 2363 // with "c1 == c2". |
2364 var node = command2node[command]; | 2364 var node = command2node[command]; |
2365 if (node == null) { | 2365 if (node == null) { |
2366 var requiredNodes = (lastNode != null) ? [lastNode] : []; | 2366 var requiredNodes = (lastNode != null) ? [lastNode] : <dgraph.Node>[]; |
2367 node = graph.newNode(command, requiredNodes); | 2367 node = graph.newNode(command, requiredNodes); |
2368 command2node[command] = node; | 2368 command2node[command] = node; |
2369 command2testCases[command] = <TestCase>[]; | 2369 command2testCases[command] = <TestCase>[]; |
2370 } | 2370 } |
2371 // Keep mapping from command to all testCases that refer to it | 2371 // Keep mapping from command to all testCases that refer to it |
2372 command2testCases[command].add(testCase); | 2372 command2testCases[command].add(testCase); |
2373 | 2373 |
2374 lastNode = node; | 2374 lastNode = node; |
2375 } | 2375 } |
2376 _onTestCaseAdded(testCase); | 2376 _onTestCaseAdded(testCase); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2410 static final FINISHED_STATES = [ | 2410 static final FINISHED_STATES = [ |
2411 dgraph.NodeState.Successful, | 2411 dgraph.NodeState.Successful, |
2412 dgraph.NodeState.Failed, | 2412 dgraph.NodeState.Failed, |
2413 dgraph.NodeState.UnableToRun | 2413 dgraph.NodeState.UnableToRun |
2414 ]; | 2414 ]; |
2415 final dgraph.Graph _graph; | 2415 final dgraph.Graph _graph; |
2416 | 2416 |
2417 CommandEnqueuer(this._graph) { | 2417 CommandEnqueuer(this._graph) { |
2418 var eventCondition = _graph.events.where; | 2418 var eventCondition = _graph.events.where; |
2419 | 2419 |
2420 eventCondition((e) => e is dgraph.NodeAddedEvent).listen((event) { | 2420 eventCondition((e) => e is dgraph.NodeAddedEvent).listen((e) { |
| 2421 var event = e as dgraph.NodeAddedEvent; |
2421 dgraph.Node node = event.node; | 2422 dgraph.Node node = event.node; |
2422 _changeNodeStateIfNecessary(node); | 2423 _changeNodeStateIfNecessary(node); |
2423 }); | 2424 }); |
2424 | 2425 |
2425 eventCondition((e) => e is dgraph.StateChangedEvent).listen((event) { | 2426 eventCondition((e) => e is dgraph.StateChangedEvent).listen((e) { |
| 2427 var event = e as dgraph.StateChangedEvent; |
2426 if ([dgraph.NodeState.Waiting, dgraph.NodeState.Processing] | 2428 if ([dgraph.NodeState.Waiting, dgraph.NodeState.Processing] |
2427 .contains(event.from)) { | 2429 .contains(event.from)) { |
2428 if (FINISHED_STATES.contains(event.to)) { | 2430 if (FINISHED_STATES.contains(event.to)) { |
2429 for (var dependendNode in event.node.neededFor) { | 2431 for (var dependendNode in event.node.neededFor) { |
2430 _changeNodeStateIfNecessary(dependendNode); | 2432 _changeNodeStateIfNecessary(dependendNode); |
2431 } | 2433 } |
2432 } | 2434 } |
2433 } | 2435 } |
2434 }); | 2436 }); |
2435 } | 2437 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2474 * nodes left in the states Initialized/Waiting/Enqueing/Processing | 2476 * nodes left in the states Initialized/Waiting/Enqueing/Processing |
2475 * and the [executor] has cleaned up it's resources. | 2477 * and the [executor] has cleaned up it's resources. |
2476 */ | 2478 */ |
2477 class CommandQueue { | 2479 class CommandQueue { |
2478 final dgraph.Graph graph; | 2480 final dgraph.Graph graph; |
2479 final CommandExecutor executor; | 2481 final CommandExecutor executor; |
2480 final TestCaseEnqueuer enqueuer; | 2482 final TestCaseEnqueuer enqueuer; |
2481 | 2483 |
2482 final Queue<Command> _runQueue = new Queue<Command>(); | 2484 final Queue<Command> _runQueue = new Queue<Command>(); |
2483 final _commandOutputStream = new StreamController<CommandOutput>(sync: true); | 2485 final _commandOutputStream = new StreamController<CommandOutput>(sync: true); |
2484 final _completer = new Completer(); | 2486 final _completer = new Completer<Null>(); |
2485 | 2487 |
2486 int _numProcesses = 0; | 2488 int _numProcesses = 0; |
2487 int _maxProcesses; | 2489 int _maxProcesses; |
2488 int _numBrowserProcesses = 0; | 2490 int _numBrowserProcesses = 0; |
2489 int _maxBrowserProcesses; | 2491 int _maxBrowserProcesses; |
2490 bool _finishing = false; | 2492 bool _finishing = false; |
2491 bool _verbose = false; | 2493 bool _verbose = false; |
2492 | 2494 |
2493 CommandQueue(this.graph, this.enqueuer, this.executor, this._maxProcesses, | 2495 CommandQueue(this.graph, this.enqueuer, this.executor, this._maxProcesses, |
2494 this._maxBrowserProcesses, this._verbose) { | 2496 this._maxBrowserProcesses, this._verbose) { |
2495 var eventCondition = graph.events.where; | 2497 var eventCondition = graph.events.where; |
2496 eventCondition((event) => event is dgraph.StateChangedEvent) | 2498 eventCondition((e) => e is dgraph.StateChangedEvent).listen((e) { |
2497 .listen((event) { | 2499 var event = e as dgraph.StateChangedEvent; |
2498 if (event.to == dgraph.NodeState.Enqueuing) { | 2500 if (event.to == dgraph.NodeState.Enqueuing) { |
2499 assert(event.from == dgraph.NodeState.Initialized || | 2501 assert(event.from == dgraph.NodeState.Initialized || |
2500 event.from == dgraph.NodeState.Waiting); | 2502 event.from == dgraph.NodeState.Waiting); |
2501 graph.changeState(event.node, dgraph.NodeState.Processing); | 2503 graph.changeState(event.node, dgraph.NodeState.Processing); |
2502 var command = event.node.userData; | 2504 var command = event.node.userData; |
2503 if (event.node.dependencies.length > 0) { | 2505 if (event.node.dependencies.length > 0) { |
2504 _runQueue.addFirst(command); | 2506 _runQueue.addFirst(command); |
2505 } else { | 2507 } else { |
2506 _runQueue.add(command); | 2508 _runQueue.add(command); |
2507 } | 2509 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2615 * | 2617 * |
2616 * It provides a [runCommand] method which will complete with a | 2618 * It provides a [runCommand] method which will complete with a |
2617 * [CommandOutput] object. | 2619 * [CommandOutput] object. |
2618 * | 2620 * |
2619 * It provides a [cleanup] method to free all the allocated resources. | 2621 * It provides a [cleanup] method to free all the allocated resources. |
2620 */ | 2622 */ |
2621 abstract class CommandExecutor { | 2623 abstract class CommandExecutor { |
2622 Future cleanup(); | 2624 Future cleanup(); |
2623 // TODO(kustermann): The [timeout] parameter should be a property of Command | 2625 // TODO(kustermann): The [timeout] parameter should be a property of Command |
2624 Future<CommandOutput> runCommand( | 2626 Future<CommandOutput> runCommand( |
2625 dgraph.Node node, Command command, int timeout); | 2627 dgraph.Node node, covariant Command command, int timeout); |
2626 } | 2628 } |
2627 | 2629 |
2628 class CommandExecutorImpl implements CommandExecutor { | 2630 class CommandExecutorImpl implements CommandExecutor { |
2629 final Map globalConfiguration; | 2631 final Map globalConfiguration; |
2630 final int maxProcesses; | 2632 final int maxProcesses; |
2631 final int maxBrowserProcesses; | 2633 final int maxBrowserProcesses; |
2632 AdbDevicePool adbDevicePool; | 2634 AdbDevicePool adbDevicePool; |
2633 | 2635 |
2634 // For dart2js and analyzer batch processing, | 2636 // For dart2js and analyzer batch processing, |
2635 // we keep a list of batch processes. | 2637 // we keep a list of batch processes. |
2636 final _batchProcesses = new Map<String, List<BatchRunnerProcess>>(); | 2638 final _batchProcesses = new Map<String, List<BatchRunnerProcess>>(); |
2637 // We keep a BrowserTestRunner for every configuration. | 2639 // We keep a BrowserTestRunner for every configuration. |
2638 final _browserTestRunners = new Map<Map, BrowserTestRunner>(); | 2640 final _browserTestRunners = new Map<Map, BrowserTestRunner>(); |
2639 | 2641 |
2640 bool _finishing = false; | 2642 bool _finishing = false; |
2641 | 2643 |
2642 CommandExecutorImpl( | 2644 CommandExecutorImpl( |
2643 this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses, | 2645 this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses, |
2644 {this.adbDevicePool}); | 2646 {this.adbDevicePool}); |
2645 | 2647 |
2646 Future cleanup() { | 2648 Future cleanup() { |
2647 assert(!_finishing); | 2649 assert(!_finishing); |
2648 _finishing = true; | 2650 _finishing = true; |
2649 | 2651 |
2650 Future _terminateBatchRunners() { | 2652 Future _terminateBatchRunners() { |
2651 var futures = []; | 2653 var futures = <Future>[]; |
2652 for (var runners in _batchProcesses.values) { | 2654 for (var runners in _batchProcesses.values) { |
2653 futures.addAll(runners.map((runner) => runner.terminate())); | 2655 futures.addAll(runners.map((runner) => runner.terminate())); |
2654 } | 2656 } |
2655 return Future.wait(futures); | 2657 return Future.wait(futures); |
2656 } | 2658 } |
2657 | 2659 |
2658 Future _terminateBrowserRunners() { | 2660 Future _terminateBrowserRunners() { |
2659 var futures = | 2661 var futures = |
2660 _browserTestRunners.values.map((runner) => runner.terminate()); | 2662 _browserTestRunners.values.map((runner) => runner.terminate()); |
2661 return Future.wait(futures); | 2663 return Future.wait(futures); |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2986 _outputs[output.command] = output; | 2988 _outputs[output.command] = output; |
2987 }, onDone: () { | 2989 }, onDone: () { |
2988 _completeTestCasesIfPossible(new List.from(enqueuer.remainingTestCases)); | 2990 _completeTestCasesIfPossible(new List.from(enqueuer.remainingTestCases)); |
2989 finishedRemainingTestCases = true; | 2991 finishedRemainingTestCases = true; |
2990 assert(enqueuer.remainingTestCases.isEmpty); | 2992 assert(enqueuer.remainingTestCases.isEmpty); |
2991 _checkDone(); | 2993 _checkDone(); |
2992 }); | 2994 }); |
2993 | 2995 |
2994 // Listen for NodeState.Processing -> NodeState.{Successful,Failed} | 2996 // Listen for NodeState.Processing -> NodeState.{Successful,Failed} |
2995 // changes. | 2997 // changes. |
2996 eventCondition((event) => event is dgraph.StateChangedEvent) | 2998 eventCondition((event) => event is dgraph.StateChangedEvent).listen((e) { |
2997 .listen((dgraph.StateChangedEvent event) { | 2999 var event = e as dgraph.StateChangedEvent; |
2998 if (event.from == dgraph.NodeState.Processing && | 3000 if (event.from == dgraph.NodeState.Processing && |
2999 !finishedRemainingTestCases) { | 3001 !finishedRemainingTestCases) { |
3000 var command = event.node.userData; | 3002 var command = event.node.userData; |
3001 | 3003 |
3002 assert(COMPLETED_STATES.contains(event.to)); | 3004 assert(COMPLETED_STATES.contains(event.to)); |
3003 assert(_outputs[command] != null); | 3005 assert(_outputs[command] != null); |
3004 | 3006 |
3005 _completeTestCasesIfPossible(enqueuer.command2testCases[command]); | 3007 _completeTestCasesIfPossible(enqueuer.command2testCases[command]); |
3006 _checkDone(); | 3008 _checkDone(); |
3007 } | 3009 } |
3008 }); | 3010 }); |
3009 | 3011 |
3010 // Listen also for GraphSealedEvent's. If there is not a single node in the | 3012 // Listen also for GraphSealedEvent's. If there is not a single node in the |
3011 // graph, we still want to finish after the graph was sealed. | 3013 // graph, we still want to finish after the graph was sealed. |
3012 eventCondition((event) => event is dgraph.GraphSealedEvent) | 3014 eventCondition((event) => event is dgraph.GraphSealedEvent).listen((_) { |
3013 .listen((dgraph.GraphSealedEvent event) { | |
3014 if (!_closed && enqueuer.remainingTestCases.isEmpty) { | 3015 if (!_closed && enqueuer.remainingTestCases.isEmpty) { |
3015 _controller.close(); | 3016 _controller.close(); |
3016 _closed = true; | 3017 _closed = true; |
3017 } | 3018 } |
3018 }); | 3019 }); |
3019 } | 3020 } |
3020 | 3021 |
3021 Stream<TestCase> get finishedTestCases => _controller.stream; | 3022 Stream<TestCase> get finishedTestCases => _controller.stream; |
3022 | 3023 |
3023 void _checkDone() { | 3024 void _checkDone() { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3067 | 3068 |
3068 ProcessQueue(this._globalConfiguration, maxProcesses, maxBrowserProcesses, | 3069 ProcessQueue(this._globalConfiguration, maxProcesses, maxBrowserProcesses, |
3069 DateTime startTime, testSuites, this._eventListener, this._allDone, | 3070 DateTime startTime, testSuites, this._eventListener, this._allDone, |
3070 [bool verbose = false, | 3071 [bool verbose = false, |
3071 String recordingOutputFile, | 3072 String recordingOutputFile, |
3072 String recordedInputFile, | 3073 String recordedInputFile, |
3073 AdbDevicePool adbDevicePool]) { | 3074 AdbDevicePool adbDevicePool]) { |
3074 void setupForListing(TestCaseEnqueuer testCaseEnqueuer) { | 3075 void setupForListing(TestCaseEnqueuer testCaseEnqueuer) { |
3075 _graph.events | 3076 _graph.events |
3076 .where((event) => event is dgraph.GraphSealedEvent) | 3077 .where((event) => event is dgraph.GraphSealedEvent) |
3077 .listen((dgraph.GraphSealedEvent event) { | 3078 .listen((_) { |
3078 var testCases = new List.from(testCaseEnqueuer.remainingTestCases); | 3079 var testCases = new List.from(testCaseEnqueuer.remainingTestCases); |
3079 testCases.sort((a, b) => a.displayName.compareTo(b.displayName)); | 3080 testCases.sort((a, b) => a.displayName.compareTo(b.displayName)); |
3080 | 3081 |
3081 print("\nGenerating all matching test cases ....\n"); | 3082 print("\nGenerating all matching test cases ....\n"); |
3082 | 3083 |
3083 for (TestCase testCase in testCases) { | 3084 for (TestCase testCase in testCases) { |
3084 eventFinishedTestCase(testCase); | 3085 eventFinishedTestCase(testCase); |
3085 print("${testCase.displayName} " | 3086 print("${testCase.displayName} " |
3086 "Expectations: ${testCase.expectedOutcomes.join(', ')} " | 3087 "Expectations: ${testCase.expectedOutcomes.join(', ')} " |
3087 "Configuration: '${testCase.configurationString}'"); | 3088 "Configuration: '${testCase.configurationString}'"); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3241 } | 3242 } |
3242 } | 3243 } |
3243 | 3244 |
3244 void eventAllTestsDone() { | 3245 void eventAllTestsDone() { |
3245 for (var listener in _eventListener) { | 3246 for (var listener in _eventListener) { |
3246 listener.allDone(); | 3247 listener.allDone(); |
3247 } | 3248 } |
3248 _allDone(); | 3249 _allDone(); |
3249 } | 3250 } |
3250 } | 3251 } |
OLD | NEW |