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. |
11 */ | 11 */ |
12 library test_runner; | 12 library test_runner; |
13 | 13 |
14 import "dart:async"; | 14 import "dart:async"; |
15 import "dart:collection" show Queue; | 15 import "dart:collection" show Queue; |
16 import "dart:convert" show LineSplitter, UTF8; | 16 import "dart:convert" show LineSplitter, UTF8; |
17 // We need to use the 'io' prefix here, otherwise io.exitCode will shadow | 17 // We need to use the 'io' prefix here, otherwise io.exitCode will shadow |
18 // CommandOutput.exitCode in subclasses of CommandOutput. | 18 // CommandOutput.exitCode in subclasses of CommandOutput. |
19 import "dart:io" as io; | 19 import "dart:io" as io; |
20 import "dart:math" as math; | 20 import "dart:math" as math; |
21 import 'dependency_graph.dart' as dgraph; | 21 import 'dependency_graph.dart' as dgraph; |
22 import "browser_controller.dart"; | 22 import "browser_controller.dart"; |
23 import "status_file_parser.dart"; | 23 import "status_file_parser.dart"; |
24 import "test_progress.dart"; | 24 import "test_progress.dart"; |
25 import "test_suite.dart"; | 25 import "test_suite.dart"; |
26 import "utils.dart"; | 26 import "utils.dart"; |
27 import 'record_and_replay.dart'; | 27 import 'record_and_replay.dart'; |
28 | 28 |
29 const int CRASHING_BROWSER_EXITCODE = -10; | |
30 const int SLOW_TIMEOUT_MULTIPLIER = 4; | 29 const int SLOW_TIMEOUT_MULTIPLIER = 4; |
31 | 30 |
32 const MESSAGE_CANNOT_OPEN_DISPLAY = 'Gtk-WARNING **: cannot open display'; | 31 const MESSAGE_CANNOT_OPEN_DISPLAY = 'Gtk-WARNING **: cannot open display'; |
33 const MESSAGE_FAILED_TO_RUN_COMMAND = 'Failed to run command. return code=1'; | 32 const MESSAGE_FAILED_TO_RUN_COMMAND = 'Failed to run command. return code=1'; |
34 | 33 |
35 typedef void TestCaseEvent(TestCase testCase); | 34 typedef void TestCaseEvent(TestCase testCase); |
36 typedef void ExitCodeEvent(int exitCode); | 35 typedef void ExitCodeEvent(int exitCode); |
37 typedef void EnqueueMoreWork(ProcessQueue queue); | 36 typedef void EnqueueMoreWork(ProcessQueue queue); |
38 | 37 |
39 // Some IO tests use these variables and get confused if the host environment | 38 // Some IO tests use these variables and get confused if the host environment |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 bool _equal(Command other) { | 301 bool _equal(Command other) { |
303 return | 302 return |
304 other is BrowserTestCommand && | 303 other is BrowserTestCommand && |
305 super._equal(other) && | 304 super._equal(other) && |
306 browser == other.browser && | 305 browser == other.browser && |
307 url == other.url && | 306 url == other.url && |
308 checkedMode == other.checkedMode; | 307 checkedMode == other.checkedMode; |
309 } | 308 } |
310 } | 309 } |
311 | 310 |
312 class SeleniumTestCommand extends Command { | |
313 final String browser; | |
314 final String url; | |
315 | |
316 SeleniumTestCommand._(String _browser, | |
317 this.url, | |
318 String executable, | |
319 List<String> arguments, | |
320 String configurationDir) | |
321 : super._(_browser, executable, arguments, configurationDir), | |
322 browser = _browser; | |
323 | |
324 void _buildHashCode(HashCodeBuilder builder) { | |
325 super._buildHashCode(builder); | |
326 builder.add(browser); | |
327 builder.add(url); | |
328 } | |
329 | |
330 bool _equal(Command other) { | |
331 return | |
332 other is SeleniumTestCommand && | |
333 super._equal(other) && | |
334 browser == other.browser && | |
335 url == other.url; | |
336 } | |
337 } | |
338 | |
339 class AnalysisCommand extends Command { | 311 class AnalysisCommand extends Command { |
340 final String flavor; | 312 final String flavor; |
341 | 313 |
342 // If [fileFilter] is given, only errors/warnings reported by the analyzer | 314 // If [fileFilter] is given, only errors/warnings reported by the analyzer |
343 // for which [fileFilter] returns [:true:] are considered. | 315 // for which [fileFilter] returns [:true:] are considered. |
344 final Function fileFilter; | 316 final Function fileFilter; |
345 | 317 |
346 AnalysisCommand._(this.flavor, | 318 AnalysisCommand._(this.flavor, |
347 String displayName, | 319 String displayName, |
348 String executable, | 320 String executable, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 String executable, | 380 String executable, |
409 List<String> arguments, | 381 List<String> arguments, |
410 String configurationDir, | 382 String configurationDir, |
411 {bool checkedMode: false}) { | 383 {bool checkedMode: false}) { |
412 var command = new BrowserTestCommand._( | 384 var command = new BrowserTestCommand._( |
413 browser, url, executable, arguments, configurationDir, | 385 browser, url, executable, arguments, configurationDir, |
414 checkedMode: checkedMode); | 386 checkedMode: checkedMode); |
415 return _getUniqueCommand(command); | 387 return _getUniqueCommand(command); |
416 } | 388 } |
417 | 389 |
418 SeleniumTestCommand getSeleniumTestCommand(String browser, | |
419 String url, | |
420 String executable, | |
421 List<String> arguments, | |
422 String configurationDir) { | |
423 var command = new SeleniumTestCommand._( | |
424 browser, url, executable, arguments, configurationDir); | |
425 return _getUniqueCommand(command); | |
426 } | |
427 | |
428 CompilationCommand getCompilationCommand(String displayName, | 390 CompilationCommand getCompilationCommand(String displayName, |
429 outputFile, | 391 outputFile, |
430 neverSkipCompilation, | 392 neverSkipCompilation, |
431 List<String> bootstrapDependencies, | 393 List<String> bootstrapDependencies, |
432 String executable, | 394 String executable, |
433 List<String> arguments, | 395 List<String> arguments, |
434 String configurationDir) { | 396 String configurationDir) { |
435 var command = | 397 var command = |
436 new CompilationCommand._(displayName, outputFile, neverSkipCompilation, | 398 new CompilationCommand._(displayName, outputFile, neverSkipCompilation, |
437 bootstrapDependencies, executable, arguments, | 399 bootstrapDependencies, executable, arguments, |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 final compiler = configuration['compiler']; | 518 final compiler = configuration['compiler']; |
557 final runtime = configuration['runtime']; | 519 final runtime = configuration['runtime']; |
558 final mode = configuration['mode']; | 520 final mode = configuration['mode']; |
559 final arch = configuration['arch']; | 521 final arch = configuration['arch']; |
560 final checked = configuration['checked'] ? '-checked' : ''; | 522 final checked = configuration['checked'] ? '-checked' : ''; |
561 return "$compiler-$runtime$checked ${mode}_$arch"; | 523 return "$compiler-$runtime$checked ${mode}_$arch"; |
562 } | 524 } |
563 | 525 |
564 List<String> get batchTestArguments => commands.last.arguments; | 526 List<String> get batchTestArguments => commands.last.arguments; |
565 | 527 |
566 bool get usesWebDriver => TestUtils.usesWebDriver(configuration['runtime']); | |
567 | |
568 bool get isFlaky { | 528 bool get isFlaky { |
569 if (expectedOutcomes.contains(Expectation.SKIP) || | 529 if (expectedOutcomes.contains(Expectation.SKIP) || |
570 expectedOutcomes.contains(Expectation.SKIP_BY_DESIGN)) { | 530 expectedOutcomes.contains(Expectation.SKIP_BY_DESIGN)) { |
571 return false; | 531 return false; |
572 } | 532 } |
573 | 533 |
574 return expectedOutcomes | 534 return expectedOutcomes |
575 .where((expectation) => !expectation.isMetaExpectation).length > 1; | 535 .where((expectation) => !expectation.isMetaExpectation).length > 1; |
576 } | 536 } |
577 | 537 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 bool get hasCrashed { | 656 bool get hasCrashed { |
697 // The Java dartc runner and dart2js exits with code 253 in case | 657 // The Java dartc runner and dart2js exits with code 253 in case |
698 // of unhandled exceptions. | 658 // of unhandled exceptions. |
699 if (exitCode == 253) return true; | 659 if (exitCode == 253) return true; |
700 if (io.Platform.operatingSystem == 'windows') { | 660 if (io.Platform.operatingSystem == 'windows') { |
701 // The VM uses std::abort to terminate on asserts. | 661 // The VM uses std::abort to terminate on asserts. |
702 // std::abort terminates with exit code 3 on Windows. | 662 // std::abort terminates with exit code 3 on Windows. |
703 if (exitCode == 3) { | 663 if (exitCode == 3) { |
704 return !timedOut; | 664 return !timedOut; |
705 } | 665 } |
706 // TODO(ricow): Remove this dirty hack ones we have a selenium | |
707 // replacement. | |
708 if (exitCode == CRASHING_BROWSER_EXITCODE) { | |
709 return !timedOut; | |
710 } | |
711 // If a program receives an uncaught system exception, the program | 666 // If a program receives an uncaught system exception, the program |
712 // terminates with the exception code as exit code. | 667 // terminates with the exception code as exit code. |
713 // The 0x3FFFFF00 mask here tries to determine if an exception indicates | 668 // The 0x3FFFFF00 mask here tries to determine if an exception indicates |
714 // a crash of the program. | 669 // a crash of the program. |
715 // System exception codes can be found in 'winnt.h', for example | 670 // System exception codes can be found in 'winnt.h', for example |
716 // "#define STATUS_ACCESS_VIOLATION ((DWORD) 0xC0000005)" | 671 // "#define STATUS_ACCESS_VIOLATION ((DWORD) 0xC0000005)" |
717 return (!timedOut && (exitCode < 0) && ((0x3FFFFF00 & exitCode) == 0)); | 672 return (!timedOut && (exitCode < 0) && ((0x3FFFFF00 & exitCode) == 0)); |
718 } | 673 } |
719 return !timedOut && ((exitCode < 0)); | 674 return !timedOut && ((exitCode < 0)); |
720 } | 675 } |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1160 Duration time, | 1115 Duration time, |
1161 bool compilationSkipped) { | 1116 bool compilationSkipped) { |
1162 if (command is ContentShellCommand) { | 1117 if (command is ContentShellCommand) { |
1163 return new BrowserCommandOutputImpl( | 1118 return new BrowserCommandOutputImpl( |
1164 command, exitCode, timedOut, stdout, stderr, | 1119 command, exitCode, timedOut, stdout, stderr, |
1165 time, compilationSkipped); | 1120 time, compilationSkipped); |
1166 } else if (command is BrowserTestCommand) { | 1121 } else if (command is BrowserTestCommand) { |
1167 return new HTMLBrowserCommandOutputImpl( | 1122 return new HTMLBrowserCommandOutputImpl( |
1168 command, exitCode, timedOut, stdout, stderr, | 1123 command, exitCode, timedOut, stdout, stderr, |
1169 time, compilationSkipped); | 1124 time, compilationSkipped); |
1170 } else if (command is SeleniumTestCommand) { | |
1171 return new BrowserCommandOutputImpl( | |
1172 command, exitCode, timedOut, stdout, stderr, | |
1173 time, compilationSkipped); | |
1174 } else if (command is AnalysisCommand) { | 1125 } else if (command is AnalysisCommand) { |
1175 return new AnalysisCommandOutputImpl( | 1126 return new AnalysisCommandOutputImpl( |
1176 command, exitCode, timedOut, stdout, stderr, | 1127 command, exitCode, timedOut, stdout, stderr, |
1177 time, compilationSkipped); | 1128 time, compilationSkipped); |
1178 } else if (command is VmCommand) { | 1129 } else if (command is VmCommand) { |
1179 return new VmCommandOutputImpl( | 1130 return new VmCommandOutputImpl( |
1180 command, exitCode, timedOut, stdout, stderr, time); | 1131 command, exitCode, timedOut, stdout, stderr, time); |
1181 } else if (command is CompilationCommand) { | 1132 } else if (command is CompilationCommand) { |
1182 return new CompilationCommandOutputImpl( | 1133 return new CompilationCommandOutputImpl( |
1183 command, exitCode, timedOut, stdout, stderr, time); | 1134 command, exitCode, timedOut, stdout, stderr, time); |
1184 } else if (command is JSCommandlineCommand) { | 1135 } else if (command is JSCommandlineCommand) { |
1185 return new JsCommandlineOutputImpl( | 1136 return new JsCommandlineOutputImpl( |
1186 command, exitCode, timedOut, stdout, stderr, time); | 1137 command, exitCode, timedOut, stdout, stderr, time); |
1187 } | 1138 } |
1188 | 1139 |
1189 return new CommandOutputImpl( | 1140 return new CommandOutputImpl( |
1190 command, exitCode, timedOut, stdout, stderr, | 1141 command, exitCode, timedOut, stdout, stderr, |
1191 time, compilationSkipped); | 1142 time, compilationSkipped); |
1192 } | 1143 } |
1193 | 1144 |
1194 | 1145 |
1195 /** Modifies the --timeout=XX parameter passed to run_selenium.py */ | |
1196 List<String> _modifySeleniumTimeout(List<String> arguments, int timeout) { | |
1197 return arguments.map((argument) { | |
1198 if (argument.startsWith('--timeout=')) { | |
1199 return "--timeout=$timeout"; | |
1200 } else { | |
1201 return argument; | |
1202 } | |
1203 }).toList(); | |
1204 } | |
1205 | |
1206 | |
1207 /** | 1146 /** |
1208 * A RunningProcess actually runs a test, getting the command lines from | 1147 * A RunningProcess actually runs a test, getting the command lines from |
1209 * its [TestCase], starting the test process (and first, a compilation | 1148 * its [TestCase], starting the test process (and first, a compilation |
1210 * process if the TestCase is a [BrowserTestCase]), creating a timeout | 1149 * process if the TestCase is a [BrowserTestCase]), creating a timeout |
1211 * timer, and recording the results in a new [CommandOutput] object, which it | 1150 * timer, and recording the results in a new [CommandOutput] object, which it |
1212 * attaches to the TestCase. The lifetime of the RunningProcess is limited | 1151 * attaches to the TestCase. The lifetime of the RunningProcess is limited |
1213 * to the time it takes to start the process, run the process, and record | 1152 * to the time it takes to start the process, run the process, and record |
1214 * the result; there are no pointers to it, so it should be available to | 1153 * the result; there are no pointers to it, so it should be available to |
1215 * be garbage collected as soon as it is done. | 1154 * be garbage collected as soon as it is done. |
1216 */ | 1155 */ |
(...skipping 17 matching lines...) Expand all Loading... |
1234 return completer.future; | 1173 return completer.future; |
1235 } | 1174 } |
1236 | 1175 |
1237 void _runCommand() { | 1176 void _runCommand() { |
1238 command.outputIsUpToDate.then((bool isUpToDate) { | 1177 command.outputIsUpToDate.then((bool isUpToDate) { |
1239 if (isUpToDate) { | 1178 if (isUpToDate) { |
1240 compilationSkipped = true; | 1179 compilationSkipped = true; |
1241 _commandComplete(0); | 1180 _commandComplete(0); |
1242 } else { | 1181 } else { |
1243 var processEnvironment = _createProcessEnvironment(); | 1182 var processEnvironment = _createProcessEnvironment(); |
1244 var commandArguments = _modifySeleniumTimeout(command.arguments, | |
1245 timeout); | |
1246 Future processFuture = | 1183 Future processFuture = |
1247 io.Process.start(command.executable, | 1184 io.Process.start(command.executable, |
1248 commandArguments, | 1185 command.arguments, |
1249 environment: processEnvironment); | 1186 environment: processEnvironment); |
1250 processFuture.then((io.Process process) { | 1187 processFuture.then((io.Process process) { |
1251 // Close stdin so that tests that try to block on input will fail. | 1188 // Close stdin so that tests that try to block on input will fail. |
1252 process.stdin.close(); | 1189 process.stdin.close(); |
1253 void timeoutHandler() { | 1190 void timeoutHandler() { |
1254 timedOut = true; | 1191 timedOut = true; |
1255 if (process != null) { | 1192 if (process != null) { |
1256 process.kill(); | 1193 process.kill(); |
1257 } | 1194 } |
1258 } | 1195 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1311 } | 1248 } |
1312 | 1249 |
1313 return environment; | 1250 return environment; |
1314 } | 1251 } |
1315 } | 1252 } |
1316 | 1253 |
1317 class BatchRunnerProcess { | 1254 class BatchRunnerProcess { |
1318 static bool isWindows = io.Platform.operatingSystem == 'windows'; | 1255 static bool isWindows = io.Platform.operatingSystem == 'windows'; |
1319 | 1256 |
1320 final batchRunnerTypes = { | 1257 final batchRunnerTypes = { |
1321 'selenium' : { | |
1322 'run_executable' : 'python', | |
1323 'run_arguments' : ['tools/testing/run_selenium.py', '--batch'], | |
1324 'terminate_command' : ['--terminate'], | |
1325 }, | |
1326 'dartanalyzer' : { | 1258 'dartanalyzer' : { |
1327 'run_executable' : | 1259 'run_executable' : |
1328 isWindows ? | 1260 isWindows ? |
1329 'sdk\\bin\\dartanalyzer_developer.bat' | 1261 'sdk\\bin\\dartanalyzer_developer.bat' |
1330 : 'sdk/bin/dartanalyzer_developer', | 1262 : 'sdk/bin/dartanalyzer_developer', |
1331 'run_arguments' : ['--batch'], | 1263 'run_arguments' : ['--batch'], |
1332 'terminate_command' : null, | |
1333 }, | 1264 }, |
1334 'dart2analyzer' : { | 1265 'dart2analyzer' : { |
1335 // This is a unix shell script, no windows equivalent available | 1266 // This is a unix shell script, no windows equivalent available |
1336 'run_executable' : 'editor/tools/analyzer', | 1267 'run_executable' : 'editor/tools/analyzer', |
1337 'run_arguments' : ['--batch'], | 1268 'run_arguments' : ['--batch'], |
1338 'terminate_command' : null, | |
1339 }, | 1269 }, |
1340 }; | 1270 }; |
1341 | 1271 |
1342 Completer<CommandOutput> _completer; | 1272 Completer<CommandOutput> _completer; |
1343 Command _command; | 1273 Command _command; |
1344 List<String> _arguments; | 1274 List<String> _arguments; |
1345 String _runnerType; | 1275 String _runnerType; |
1346 | 1276 |
1347 io.Process _process; | 1277 io.Process _process; |
1348 Map _processEnvironmentOverrides; | 1278 Map _processEnvironmentOverrides; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 } | 1326 } |
1397 | 1327 |
1398 Future terminate() { | 1328 Future terminate() { |
1399 if (_process == null) return new Future.value(true); | 1329 if (_process == null) return new Future.value(true); |
1400 Completer terminateCompleter = new Completer(); | 1330 Completer terminateCompleter = new Completer(); |
1401 Timer killTimer; | 1331 Timer killTimer; |
1402 _processExitHandler = (_) { | 1332 _processExitHandler = (_) { |
1403 if (killTimer != null) killTimer.cancel(); | 1333 if (killTimer != null) killTimer.cancel(); |
1404 terminateCompleter.complete(true); | 1334 terminateCompleter.complete(true); |
1405 }; | 1335 }; |
1406 var shutdownCommand = batchRunnerTypes[_runnerType]['terminate_command']; | 1336 _process.kill(); |
1407 if (shutdownCommand != null && !shutdownCommand.isEmpty) { | |
1408 // Use a graceful shutdown so our Selenium script can close | |
1409 // the open browser processes. On Windows, signals do not exist | |
1410 // and a kill is a hard kill. | |
1411 _process.stdin.writeln(shutdownCommand.join(' ')); | |
1412 | |
1413 // In case the run_selenium process didn't close, kill it after 30s | |
1414 killTimer = new Timer(new Duration(seconds: 30), _process.kill); | |
1415 } else { | |
1416 _process.kill(); | |
1417 } | |
1418 | 1337 |
1419 return terminateCompleter.future; | 1338 return terminateCompleter.future; |
1420 } | 1339 } |
1421 | 1340 |
1422 void doStartTest(Command command, int timeout) { | 1341 void doStartTest(Command command, int timeout) { |
1423 _startTime = new DateTime.now(); | 1342 _startTime = new DateTime.now(); |
1424 _testStdout = []; | 1343 _testStdout = []; |
1425 _testStderr = []; | 1344 _testStderr = []; |
1426 _status = null; | 1345 _status = null; |
1427 _stdoutCompleter = new Completer(); | 1346 _stdoutCompleter = new Completer(); |
1428 _stderrCompleter = new Completer(); | 1347 _stderrCompleter = new Completer(); |
1429 _timer = new Timer(new Duration(seconds: timeout), | 1348 _timer = new Timer(new Duration(seconds: timeout), |
1430 _timeoutHandler); | 1349 _timeoutHandler); |
1431 | 1350 |
1432 var line = _createArgumentsLine(_arguments, timeout); | 1351 var line = _createArgumentsLine(_arguments, timeout); |
1433 _process.stdin.write(line); | 1352 _process.stdin.write(line); |
1434 _stdoutSubscription.resume(); | 1353 _stdoutSubscription.resume(); |
1435 _stderrSubscription.resume(); | 1354 _stderrSubscription.resume(); |
1436 Future.wait([_stdoutCompleter.future, | 1355 Future.wait([_stdoutCompleter.future, |
1437 _stderrCompleter.future]).then((_) => _reportResult()); | 1356 _stderrCompleter.future]).then((_) => _reportResult()); |
1438 } | 1357 } |
1439 | 1358 |
1440 String _createArgumentsLine(List<String> arguments, int timeout) { | 1359 String _createArgumentsLine(List<String> arguments, int timeout) { |
1441 arguments = _modifySeleniumTimeout(arguments, timeout); | |
1442 return arguments.join(' ') + '\n'; | 1360 return arguments.join(' ') + '\n'; |
1443 } | 1361 } |
1444 | 1362 |
1445 void _reportResult() { | 1363 void _reportResult() { |
1446 if (!_currentlyRunning) return; | 1364 if (!_currentlyRunning) return; |
1447 // _status == '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' | 1365 // _status == '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' |
1448 | 1366 |
1449 var outcome = _status.split(" ")[2]; | 1367 var outcome = _status.split(" ")[2]; |
1450 var exitCode = 0; | 1368 var exitCode = 0; |
1451 if (outcome == "CRASH") exitCode = CRASHING_BROWSER_EXITCODE; | |
1452 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; | 1369 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; |
1453 var output = createCommandOutput(_command, | 1370 var output = createCommandOutput(_command, |
1454 exitCode, | 1371 exitCode, |
1455 (outcome == "TIMEOUT"), | 1372 (outcome == "TIMEOUT"), |
1456 _testStdout, | 1373 _testStdout, |
1457 _testStderr, | 1374 _testStderr, |
1458 new DateTime.now().difference(_startTime), | 1375 new DateTime.now().difference(_startTime), |
1459 false); | 1376 false); |
1460 assert(_completer != null); | 1377 assert(_completer != null); |
1461 _completer.complete(output); | 1378 _completer.complete(output); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1760 | 1677 |
1761 Stream<CommandOutput> get completedCommands => _commandOutputStream.stream; | 1678 Stream<CommandOutput> get completedCommands => _commandOutputStream.stream; |
1762 | 1679 |
1763 Future get done => _completer.future; | 1680 Future get done => _completer.future; |
1764 | 1681 |
1765 void _tryRunNextCommand() { | 1682 void _tryRunNextCommand() { |
1766 _checkDone(); | 1683 _checkDone(); |
1767 | 1684 |
1768 if (_numProcesses < _maxProcesses && !_runQueue.isEmpty) { | 1685 if (_numProcesses < _maxProcesses && !_runQueue.isEmpty) { |
1769 Command command = _runQueue.removeFirst(); | 1686 Command command = _runQueue.removeFirst(); |
1770 var isBrowserCommand = | 1687 var isBrowserCommand = command is BrowserTestCommand; |
1771 command is SeleniumTestCommand || | |
1772 command is BrowserTestCommand; | |
1773 | 1688 |
1774 if (isBrowserCommand && _numBrowserProcesses == _maxBrowserProcesses) { | 1689 if (isBrowserCommand && _numBrowserProcesses == _maxBrowserProcesses) { |
1775 // If there is no free browser runner, put it back into the queue. | 1690 // If there is no free browser runner, put it back into the queue. |
1776 _runQueue.add(command); | 1691 _runQueue.add(command); |
1777 // Don't lose a process. | 1692 // Don't lose a process. |
1778 new Timer(new Duration(milliseconds: 100), _tryRunNextCommand); | 1693 new Timer(new Duration(milliseconds: 100), _tryRunNextCommand); |
1779 return; | 1694 return; |
1780 } | 1695 } |
1781 | 1696 |
1782 _numProcesses++; | 1697 _numProcesses++; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1848 // TODO(kustermann): The [timeout] parameter should be a property of Command | 1763 // TODO(kustermann): The [timeout] parameter should be a property of Command |
1849 Future<CommandOutput> runCommand( | 1764 Future<CommandOutput> runCommand( |
1850 dgraph.Node node, Command command, int timeout); | 1765 dgraph.Node node, Command command, int timeout); |
1851 } | 1766 } |
1852 | 1767 |
1853 class CommandExecutorImpl implements CommandExecutor { | 1768 class CommandExecutorImpl implements CommandExecutor { |
1854 final Map globalConfiguration; | 1769 final Map globalConfiguration; |
1855 final int maxProcesses; | 1770 final int maxProcesses; |
1856 final int maxBrowserProcesses; | 1771 final int maxBrowserProcesses; |
1857 | 1772 |
1858 // For dartc/selenium batch processing we keep a list of batch processes. | 1773 // For dartanalyzer batch processing we keep a list of batch processes. |
1859 final _batchProcesses = new Map<String, List<BatchRunnerProcess>>(); | 1774 final _batchProcesses = new Map<String, List<BatchRunnerProcess>>(); |
1860 // We keep a BrowserTestRunner for every "browserName-checked" configuration. | 1775 // We keep a BrowserTestRunner for every "browserName-checked" configuration. |
1861 final _browserTestRunners = new Map<String, BrowserTestRunner>(); | 1776 final _browserTestRunners = new Map<String, BrowserTestRunner>(); |
1862 | 1777 |
1863 bool _finishing = false; | 1778 bool _finishing = false; |
1864 | 1779 |
1865 CommandExecutorImpl( | 1780 CommandExecutorImpl( |
1866 this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses); | 1781 this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses); |
1867 | 1782 |
1868 Future cleanup() { | 1783 Future cleanup() { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1901 }); | 1816 }); |
1902 } | 1817 } |
1903 return runCommand(command.maxNumRetries); | 1818 return runCommand(command.maxNumRetries); |
1904 } | 1819 } |
1905 | 1820 |
1906 Future<CommandOutput> _runCommand(Command command, int timeout) { | 1821 Future<CommandOutput> _runCommand(Command command, int timeout) { |
1907 var batchMode = !globalConfiguration['noBatch']; | 1822 var batchMode = !globalConfiguration['noBatch']; |
1908 | 1823 |
1909 if (command is BrowserTestCommand) { | 1824 if (command is BrowserTestCommand) { |
1910 return _startBrowserControllerTest(command, timeout); | 1825 return _startBrowserControllerTest(command, timeout); |
1911 } else if (command is SeleniumTestCommand && batchMode) { | |
1912 var arguments = ['--force-refresh', '--browser=${command.browser}', | |
1913 '--timeout=${timeout}', '--out', '${command.url}']; | |
1914 return _getBatchRunner(command.browser) | |
1915 .runCommand('selenium', command, timeout, arguments); | |
1916 } else if (command is AnalysisCommand && batchMode) { | 1826 } else if (command is AnalysisCommand && batchMode) { |
1917 return _getBatchRunner(command.flavor) | 1827 return _getBatchRunner(command.flavor) |
1918 .runCommand(command.flavor, command, timeout, command.arguments); | 1828 .runCommand(command.flavor, command, timeout, command.arguments); |
1919 } else { | 1829 } else { |
1920 return new RunningProcess(command, timeout).run(); | 1830 return new RunningProcess(command, timeout).run(); |
1921 } | 1831 } |
1922 } | 1832 } |
1923 | 1833 |
1924 BatchRunnerProcess _getBatchRunner(String identifier) { | 1834 BatchRunnerProcess _getBatchRunner(String identifier) { |
1925 // Start batch processes if needed | 1835 // Start batch processes if needed |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2071 // "xvfb-run" issue 7564, try re-running the test. | 1981 // "xvfb-run" issue 7564, try re-running the test. |
2072 bool containsFailureMsg(String line) { | 1982 bool containsFailureMsg(String line) { |
2073 return line.contains(MESSAGE_CANNOT_OPEN_DISPLAY) || | 1983 return line.contains(MESSAGE_CANNOT_OPEN_DISPLAY) || |
2074 line.contains(MESSAGE_FAILED_TO_RUN_COMMAND); | 1984 line.contains(MESSAGE_FAILED_TO_RUN_COMMAND); |
2075 } | 1985 } |
2076 if (stdout.any(containsFailureMsg) || stderr.any(containsFailureMsg)) { | 1986 if (stdout.any(containsFailureMsg) || stderr.any(containsFailureMsg)) { |
2077 return true; | 1987 return true; |
2078 } | 1988 } |
2079 } | 1989 } |
2080 | 1990 |
2081 // Selenium tests can be flaky. Try re-running. | |
2082 if (command is SeleniumTestCommand) { | |
2083 return true; | |
2084 } | |
2085 | |
2086 // We currently rerun dartium tests, see issue 14074 | 1991 // We currently rerun dartium tests, see issue 14074 |
2087 if (command is BrowserTestCommand && command.displayName == 'dartium') { | 1992 if (command is BrowserTestCommand && command.displayName == 'dartium') { |
2088 return true; | 1993 return true; |
2089 } | 1994 } |
2090 } | 1995 } |
2091 return false; | 1996 return false; |
2092 } | 1997 } |
2093 | 1998 |
2094 /* | 1999 /* |
2095 * [TestCaseCompleter] will listen for | 2000 * [TestCaseCompleter] will listen for |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2309 } | 2214 } |
2310 } | 2215 } |
2311 | 2216 |
2312 void eventAllTestsDone() { | 2217 void eventAllTestsDone() { |
2313 for (var listener in _eventListener) { | 2218 for (var listener in _eventListener) { |
2314 listener.allDone(); | 2219 listener.allDone(); |
2315 } | 2220 } |
2316 _allDone(); | 2221 _allDone(); |
2317 } | 2222 } |
2318 } | 2223 } |
OLD | NEW |