| 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 |