Chromium Code Reviews| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 | 92 |
| 93 int get timeout() => configuration['timeout']; | 93 int get timeout() => configuration['timeout']; |
| 94 | 94 |
| 95 String get configurationString() { | 95 String get configurationString() { |
| 96 final component = configuration['component']; | 96 final component = configuration['component']; |
| 97 final mode = configuration['mode']; | 97 final mode = configuration['mode']; |
| 98 final arch = configuration['arch']; | 98 final arch = configuration['arch']; |
| 99 return "$component ${mode}_$arch"; | 99 return "$component ${mode}_$arch"; |
| 100 } | 100 } |
| 101 | 101 |
| 102 List<String> get batchRunnerArguments() => ['-batch']; | |
|
Emily Fortuna
2012/02/21 18:19:35
Why use one dash here (-batch) and two dashes belo
Jennifer Messerly
2012/02/21 18:58:43
I didn't want to change the DartC test runner. Lik
Emily Fortuna
2012/02/21 19:35:33
Ah, okay. Carry on!
| |
| 103 List<String> get batchTestArguments() => arguments; | |
| 104 | |
| 102 void completed() { completedHandler(this); } | 105 void completed() { completedHandler(this); } |
| 103 } | 106 } |
| 104 | 107 |
| 105 | 108 |
| 106 /** | 109 /** |
| 107 * BrowserTestCase has an extra compilation command that is run in a separate | 110 * BrowserTestCase has an extra compilation command that is run in a separate |
| 108 * process, before the regular test is run as in the base class [TestCase]. | 111 * process, before the regular test is run as in the base class [TestCase]. |
| 109 * If the compilation command fails, then the rest of the test is not run. | 112 * If the compilation command fails, then the rest of the test is not run. |
| 110 */ | 113 */ |
| 111 class BrowserTestCase extends TestCase { | 114 class BrowserTestCase extends TestCase { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 139 expectedOutcomes, | 142 expectedOutcomes, |
| 140 isNegative) { | 143 isNegative) { |
| 141 if (compilerPath != null) { | 144 if (compilerPath != null) { |
| 142 commandLine = 'execution command: $commandLine'; | 145 commandLine = 'execution command: $commandLine'; |
| 143 String compilationCommand = | 146 String compilationCommand = |
| 144 '$compilerPath ${Strings.join(compilerArguments, " ")}'; | 147 '$compilerPath ${Strings.join(compilerArguments, " ")}'; |
| 145 commandLine = 'compilation command: $compilationCommand\n$commandLine'; | 148 commandLine = 'compilation command: $compilationCommand\n$commandLine'; |
| 146 } | 149 } |
| 147 numRetries = 2; // Allow two retries to compensate for flaky browser tests. | 150 numRetries = 2; // Allow two retries to compensate for flaky browser tests. |
| 148 } | 151 } |
| 152 | |
| 153 List<String> get batchRunnerArguments() => [arguments[0], '--batch']; | |
| 154 List<String> get batchTestArguments() => | |
| 155 arguments.getRange(1, arguments.length - 1); | |
| 149 } | 156 } |
| 150 | 157 |
| 151 | 158 |
| 152 /** | 159 /** |
| 153 * TestOutput records the output of a completed test: the process's exit code, | 160 * TestOutput records the output of a completed test: the process's exit code, |
| 154 * the standard output and standard error, whether the process timed out, and | 161 * the standard output and standard error, whether the process timed out, and |
| 155 * the time the process took to run. It also contains a pointer to the | 162 * the time the process took to run. It also contains a pointer to the |
| 156 * [TestCase] this is the output of. | 163 * [TestCase] this is the output of. |
| 157 */ | 164 */ |
| 158 class TestOutput { | 165 class TestOutput { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 previous_line = line; | 217 previous_line = line; |
| 211 } | 218 } |
| 212 | 219 |
| 213 // If the browser test failed, it may have been because DumpRenderTree | 220 // If the browser test failed, it may have been because DumpRenderTree |
| 214 // and the virtual framebuffer X server didn't hook up, or DRT crashed with | 221 // and the virtual framebuffer X server didn't hook up, or DRT crashed with |
| 215 // a core dump. | 222 // a core dump. |
| 216 for (String line in stderr) { | 223 for (String line in stderr) { |
| 217 if (line.contains('Gtk-WARNING **: cannot open display: :99') || | 224 if (line.contains('Gtk-WARNING **: cannot open display: :99') || |
| 218 line.contains('Failed to run command. return code=1')) { | 225 line.contains('Failed to run command. return code=1')) { |
| 219 // If we get the X server error, or DRT crashes with a core dump, retry | 226 // If we get the X server error, or DRT crashes with a core dump, retry |
| 220 // the test. | 227 // the test. |
| 221 requestRetry = true; | 228 requestRetry = true; |
| 222 return true; | 229 return true; |
| 223 } | 230 } |
| 224 } | 231 } |
| 225 return true; | 232 return true; |
| 226 } | 233 } |
| 227 | 234 |
| 228 // Reverse result of a negative test. | 235 // Reverse result of a negative test. |
| 229 bool get hasFailed() => (testCase.isNegative ? !didFail : didFail); | 236 bool get hasFailed() => (testCase.isNegative ? !didFail : didFail); |
| 230 } | 237 } |
| 231 | 238 |
| 232 /** | 239 /** |
| 233 * A RunningProcess actually runs a test, getting the command lines from | 240 * A RunningProcess actually runs a test, getting the command lines from |
| 234 * its [TestCase], starting the test process (and first, a compilation | 241 * its [TestCase], starting the test process (and first, a compilation |
| 235 * process if the TestCase is a [BrowserTestCase]), creating a timeout | 242 * process if the TestCase is a [BrowserTestCase]), creating a timeout |
| 236 * timer, and recording the results in a new [TestOutput] object, which it | 243 * timer, and recording the results in a new [TestOutput] object, which it |
| 237 * attaches to the TestCase. The lifetime of the RunningProcess is limited | 244 * attaches to the TestCase. The lifetime of the RunningProcess is limited |
| 238 * to the time it takes to start the process, run the process, and record | 245 * to the time it takes to start the process, run the process, and record |
| 239 * the result; there are no pointers to it, so it should be available to | 246 * the result; there are no pointers to it, so it should be available to |
| 240 * be garbage collected as soon as it is done. | 247 * be garbage collected as soon as it is done. |
| 241 */ | 248 */ |
| 242 class RunningProcess { | 249 class RunningProcess { |
| 250 ProcessQueue processQueue; | |
| 243 Process process; | 251 Process process; |
| 244 TestCase testCase; | 252 TestCase testCase; |
| 245 bool timedOut = false; | 253 bool timedOut = false; |
| 246 Date startTime; | 254 Date startTime; |
| 247 Timer timeoutTimer; | 255 Timer timeoutTimer; |
| 248 List<String> stdout; | 256 List<String> stdout; |
| 249 List<String> stderr; | 257 List<String> stderr; |
| 250 List<Function> handlers; | 258 List<Function> handlers; |
| 251 | 259 |
| 252 RunningProcess(TestCase this.testCase); | 260 RunningProcess(TestCase this.testCase, this.processQueue); |
|
Emily Fortuna
2012/02/21 18:19:35
Careful here. The VM uses the RunningProcess class
Jennifer Messerly
2012/02/21 18:58:43
Done.
Emily Fortuna
2012/02/21 19:35:33
FYI: I know this because I made the same mistake w
| |
| 253 | 261 |
| 254 void exitHandler(int exitCode) { | 262 void exitHandler(int exitCode) { |
| 255 new TestOutput(testCase, exitCode, timedOut, stdout, | 263 new TestOutput(testCase, exitCode, timedOut, stdout, |
| 256 stderr, new Date.now().difference(startTime)); | 264 stderr, new Date.now().difference(startTime)); |
| 257 process.close(); | 265 process.close(); |
| 258 timeoutTimer.cancel(); | 266 timeoutTimer.cancel(); |
| 259 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) { | 267 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) { |
| 260 print(testCase.displayName); | 268 print(testCase.displayName); |
| 261 for (var line in testCase.output.stderr) print(line); | 269 for (var line in testCase.output.stderr) print(line); |
| 262 for (var line in testCase.output.stdout) print(line); | 270 for (var line in testCase.output.stdout) print(line); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 278 } | 286 } |
| 279 | 287 |
| 280 void compilerExitHandler(int exitCode) { | 288 void compilerExitHandler(int exitCode) { |
| 281 if (exitCode != 0) { | 289 if (exitCode != 0) { |
| 282 stderr.add('test.dart: Compilation step failed (exit code $exitCode)\n'); | 290 stderr.add('test.dart: Compilation step failed (exit code $exitCode)\n'); |
| 283 exitHandler(exitCode); | 291 exitHandler(exitCode); |
| 284 } else { | 292 } else { |
| 285 process.close(); | 293 process.close(); |
| 286 stderr.add('test.dart: Compilation finished, starting execution\n'); | 294 stderr.add('test.dart: Compilation finished, starting execution\n'); |
| 287 stdout.add('test.dart: Compilation finished, starting execution\n'); | 295 stdout.add('test.dart: Compilation finished, starting execution\n'); |
| 288 runCommand(testCase.executablePath, testCase.arguments, exitHandler); | 296 if (testCase.configuration['component'] == 'webdriver') { |
| 297 processQueue._getBatchRunner(testCase).startTest(testCase); | |
|
Emily Fortuna
2012/02/21 19:35:33
probably need to add a check to make sure processQ
| |
| 298 } else { | |
| 299 runCommand(testCase.executablePath, testCase.arguments, exitHandler); | |
| 300 } | |
| 289 } | 301 } |
| 290 } | 302 } |
| 291 | 303 |
| 292 Function makeReadHandler(StringInputStream source, List<String> destination) { | 304 Function makeReadHandler(StringInputStream source, List<String> destination) { |
| 293 return () { | 305 return () { |
| 294 if (source.closed) return; // TODO(whesse): Remove when bug is fixed. | 306 if (source.closed) return; // TODO(whesse): Remove when bug is fixed. |
| 295 var line = source.readLine(); | 307 var line = source.readLine(); |
| 296 while (null != line) { | 308 while (null != line) { |
| 297 destination.add(line); | 309 destination.add(line); |
| 298 line = source.readLine(); | 310 line = source.readLine(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 makeReadHandler(stderrStringStream, stderr); | 347 makeReadHandler(stderrStringStream, stderr); |
| 336 timeoutTimer = new Timer(timeoutHandler, 1000 * testCase.timeout); | 348 timeoutTimer = new Timer(timeoutHandler, 1000 * testCase.timeout); |
| 337 } | 349 } |
| 338 | 350 |
| 339 void timeoutHandler(Timer unusedTimer) { | 351 void timeoutHandler(Timer unusedTimer) { |
| 340 timedOut = true; | 352 timedOut = true; |
| 341 process.kill(); | 353 process.kill(); |
| 342 } | 354 } |
| 343 } | 355 } |
| 344 | 356 |
| 345 | 357 class BatchRunnerProcess { |
| 346 class DartcBatchRunnerProcess { | |
| 347 String _executable; | 358 String _executable; |
| 359 List<String> _batchArguments; | |
| 348 | 360 |
| 349 Process _process; | 361 Process _process; |
| 350 StringInputStream _stdoutStream; | 362 StringInputStream _stdoutStream; |
| 351 StringInputStream _stderrStream; | 363 StringInputStream _stderrStream; |
| 352 | 364 |
| 353 TestCase _currentTest; | 365 TestCase _currentTest; |
| 354 List<String> _testStdout; | 366 List<String> _testStdout; |
| 355 List<String> _testStderr; | 367 List<String> _testStderr; |
| 356 Date _startTime; | 368 Date _startTime; |
| 357 Timer _timer; | 369 Timer _timer; |
| 358 | 370 |
| 359 DartcBatchRunnerProcess(String this._executable); | 371 bool _isWebDriver; |
| 372 | |
| 373 BatchRunnerProcess(TestCase testCase) { | |
| 374 _executable = testCase.executablePath; | |
| 375 _batchArguments = testCase.batchRunnerArguments; | |
| 376 _isWebDriver = testCase.configuration['component'] == 'webdriver'; | |
| 377 } | |
| 360 | 378 |
| 361 bool get active() => _currentTest != null; | 379 bool get active() => _currentTest != null; |
| 362 | 380 |
| 363 void startTest(TestCase testCase) { | 381 void startTest(TestCase testCase) { |
| 364 _currentTest = testCase; | 382 _currentTest = testCase; |
| 365 if (_process === null) { | 383 if (_process === null) { |
| 366 // Start process if not yet started. | 384 // Start process if not yet started. |
| 367 _executable = testCase.executablePath; | 385 _executable = testCase.executablePath; |
| 368 _startProcess(() { | 386 _startProcess(() { |
| 369 doStartTest(testCase); | 387 doStartTest(testCase); |
| 370 }); | 388 }); |
| 371 } else if (testCase.executablePath != _executable) { | 389 } else if (testCase.executablePath != _executable) { |
| 372 // Restart this runner with the right executable for this test | 390 // Restart this runner with the right executable for this test |
| 373 // if needed. | 391 // if needed. |
| 374 _executable = testCase.executablePath; | 392 _executable = testCase.executablePath; |
| 393 _batchArguments = testCase.batchRunnerArguments; | |
| 375 _process.exitHandler = (exitCode) { | 394 _process.exitHandler = (exitCode) { |
| 376 _process.close(); | 395 _process.close(); |
| 377 _startProcess(() { | 396 _startProcess(() { |
| 378 doStartTest(testCase); | 397 doStartTest(testCase); |
| 379 }); | 398 }); |
| 380 }; | 399 }; |
| 381 _process.kill(); | 400 _process.kill(); |
| 382 } else { | 401 } else { |
| 383 doStartTest(testCase); | 402 doStartTest(testCase); |
| 384 } | 403 } |
| 385 } | 404 } |
| 386 | 405 |
| 387 void terminate() { | 406 void terminate() { |
| 388 if (_process !== null) { | 407 if (_process !== null) { |
| 408 bool closed = false; | |
| 389 _process.exitHandler = (exitCode) { | 409 _process.exitHandler = (exitCode) { |
| 410 closed = true; | |
| 390 _process.close(); | 411 _process.close(); |
| 391 }; | 412 }; |
| 392 _process.kill(); | 413 if (_isWebDriver) { |
| 414 // Use a graceful shutdown so our Selenium script can close browser | |
|
Emily Fortuna
2012/02/21 19:35:33
I just reread this comment -- I think you left out
Jennifer Messerly
2012/02/21 21:29:56
fixed.
Side note: what's the deal with this capit
Emily Fortuna
2012/02/21 21:40:33
Ah, perhaps, I'm being overzealous in applying cap
| |
| 415 // the open browser processes. TODO(jmesserly): send a signal once | |
| 416 // that's supported, see dartbug.com/1756. | |
| 417 new Timer((e) { if (!closed) _process.kill(); }, 30000); | |
|
Emily Fortuna
2012/02/21 18:19:35
Where's 30000 coming from?
Jennifer Messerly
2012/02/21 18:58:43
Needed a timeout :) Unfortunately, we don't have a
Emily Fortuna
2012/02/21 19:35:33
Call me a curmudgeon, but I'd like it if you made
Jennifer Messerly
2012/02/21 21:29:56
Added a comment to that effect. Also moved the tim
| |
| 418 _process.stdin.write('--terminate\n'.charCodes()); | |
| 419 } else { | |
| 420 _process.kill(); | |
| 421 } | |
| 393 } | 422 } |
| 394 } | 423 } |
| 395 | 424 |
| 396 void doStartTest(TestCase testCase) { | 425 void doStartTest(TestCase testCase) { |
| 397 _startTime = new Date.now(); | 426 _startTime = new Date.now(); |
| 398 _testStdout = new List<String>(); | 427 _testStdout = new List<String>(); |
| 399 _testStderr = new List<String>(); | 428 _testStderr = new List<String>(); |
| 400 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout); | 429 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout); |
| 401 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr); | 430 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr); |
| 402 _timer = new Timer(_timeoutHandler(testCase), testCase.timeout * 1000); | 431 _timer = new Timer(_timeoutHandler, testCase.timeout * 1000); |
| 403 _process.stdin.write(_createArgumentsLine(testCase.arguments).charCodes()); | 432 var line = _createArgumentsLine(testCase.batchTestArguments); |
| 433 _process.stdin.write(line.charCodes()); | |
| 404 } | 434 } |
| 405 | 435 |
| 406 String _createArgumentsLine(List<String> arguments) { | 436 String _createArgumentsLine(List<String> arguments) { |
| 407 return Strings.join(arguments, ' ') + '\n'; | 437 return Strings.join(arguments, ' ') + '\n'; |
| 408 } | 438 } |
| 409 | 439 |
| 410 int _reportResult(String output) { | 440 int _reportResult(String output) { |
| 411 var test = _currentTest; | 441 var test = _currentTest; |
| 412 _currentTest = null; | 442 _currentTest = null; |
| 413 | 443 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 449 } | 479 } |
| 450 | 480 |
| 451 void _exitHandler(exitCode) { | 481 void _exitHandler(exitCode) { |
| 452 if (_timer != null) _timer.cancel(); | 482 if (_timer != null) _timer.cancel(); |
| 453 _process.close(); | 483 _process.close(); |
| 454 _startProcess(() { | 484 _startProcess(() { |
| 455 _reportResult(">>> TEST CRASH"); | 485 _reportResult(">>> TEST CRASH"); |
| 456 }); | 486 }); |
| 457 } | 487 } |
| 458 | 488 |
| 459 Function _timeoutHandler(TestCase test) { | 489 void _timeoutHandler(ignore) { |
| 460 return (ignore) { | 490 _process.exitHandler = (exitCode) { |
| 461 _process.exitHandler = (exitCode) { | 491 _process.close(); |
| 462 _process.close(); | 492 _startProcess(() { |
| 463 _startProcess(() { | 493 _reportResult(">>> TEST TIMEOUT"); |
| 464 _reportResult(">>> TEST TIMEOUT"); | 494 }); |
| 465 }); | |
| 466 }; | |
| 467 _process.kill(); | |
| 468 }; | 495 }; |
| 496 _process.kill(); | |
| 469 } | 497 } |
| 470 | 498 |
| 471 void _startProcess(then) { | 499 void _startProcess(then) { |
| 472 _process = new Process.start(_executable, ['-batch']); | 500 _process = new Process.start(_executable, _batchArguments); |
| 473 _stdoutStream = new StringInputStream(_process.stdout); | 501 _stdoutStream = new StringInputStream(_process.stdout); |
| 474 _stderrStream = new StringInputStream(_process.stderr); | 502 _stderrStream = new StringInputStream(_process.stderr); |
| 475 _testStdout = new List<String>(); | 503 _testStdout = new List<String>(); |
| 476 _testStderr = new List<String>(); | 504 _testStderr = new List<String>(); |
| 477 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout); | 505 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout); |
| 478 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr); | 506 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr); |
| 479 _process.exitHandler = _exitHandler; | 507 _process.exitHandler = _exitHandler; |
| 480 _process.startHandler = then; | 508 _process.startHandler = then; |
| 481 } | 509 } |
| 482 } | 510 } |
| 483 | 511 |
| 484 | |
| 485 /** | 512 /** |
| 486 * ProcessQueue is the master control class, responsible for running all | 513 * ProcessQueue is the master control class, responsible for running all |
| 487 * the tests in all the TestSuites that have been registered. It includes | 514 * the tests in all the TestSuites that have been registered. It includes |
| 488 * a rate-limited queue to run a limited number of tests in parallel, | 515 * a rate-limited queue to run a limited number of tests in parallel, |
| 489 * a ProgressIndicator which prints output when tests are started and | 516 * a ProgressIndicator which prints output when tests are started and |
| 490 * and completed, and a summary report when all tests are completed, | 517 * and completed, and a summary report when all tests are completed, |
| 491 * and counters to determine when all of the tests in all of the test suites | 518 * and counters to determine when all of the tests in all of the test suites |
| 492 * have completed. | 519 * have completed. |
| 493 * | 520 * |
| 494 * Because multiple configurations may be run on each test suite, the | 521 * Because multiple configurations may be run on each test suite, the |
| 495 * ProcessQueue contains a cache in which a test suite may record information | 522 * ProcessQueue contains a cache in which a test suite may record information |
| 496 * about its list of tests, and may retrieve that information when it is called | 523 * about its list of tests, and may retrieve that information when it is called |
| 497 * upon to enqueue its tests again. | 524 * upon to enqueue its tests again. |
| 498 */ | 525 */ |
| 499 class ProcessQueue { | 526 class ProcessQueue { |
| 500 int _numProcesses = 0; | 527 int _numProcesses = 0; |
| 501 int _activeTestListers = 0; | 528 int _activeTestListers = 0; |
| 502 int _maxProcesses; | 529 int _maxProcesses; |
| 503 bool _verbose; | 530 bool _verbose; |
| 504 bool _listTests; | 531 bool _listTests; |
| 505 bool _keepGeneratedTests; | 532 bool _keepGeneratedTests; |
| 506 Function _enqueueMoreWork; | 533 Function _enqueueMoreWork; |
| 507 Queue<TestCase> _tests; | 534 Queue<TestCase> _tests; |
| 508 ProgressIndicator _progress; | 535 ProgressIndicator _progress; |
| 509 String _temporaryDirectory; | 536 String _temporaryDirectory; |
| 510 // For dartc batch processing we keep a list of batch processes. | 537 // For dartc/selenium batch processing we keep a list of batch processes. |
| 511 List<DartcBatchRunnerProcess> _batchProcesses; | 538 Map<String, List<BatchRunnerProcess>> _batchProcesses; |
| 539 | |
| 512 // Cache information about test cases per test suite. For multiple | 540 // Cache information about test cases per test suite. For multiple |
| 513 // configurations there is no need to repeatedly search the file | 541 // configurations there is no need to repeatedly search the file |
| 514 // system, generate tests, and search test files for options. | 542 // system, generate tests, and search test files for options. |
| 515 Map<String, List<TestInformation>> _testCache; | 543 Map<String, List<TestInformation>> _testCache; |
| 516 /** | 544 /** |
| 517 * String indicating the browser used to run the tests. Empty if no browser | 545 * String indicating the browser used to run the tests. Empty if no browser |
| 518 * used. | 546 * used. |
| 519 */ | 547 */ |
| 520 String browserUsed; | 548 String browserUsed; |
| 521 | 549 |
| 522 ProcessQueue(int this._maxProcesses, | 550 ProcessQueue(int this._maxProcesses, |
| 523 String progress, | 551 String progress, |
| 524 Date startTime, | 552 Date startTime, |
| 525 bool printTiming, | 553 bool printTiming, |
| 526 Function this._enqueueMoreWork, | 554 Function this._enqueueMoreWork, |
| 527 [bool this._verbose = false, | 555 [bool this._verbose = false, |
| 528 bool this._listTests = false, | 556 bool this._listTests = false, |
| 529 bool this._keepGeneratedTests = false]) | 557 bool this._keepGeneratedTests = false]) |
| 530 : _tests = new Queue<TestCase>(), | 558 : _tests = new Queue<TestCase>(), |
| 531 _progress = new ProgressIndicator.fromName(progress, | 559 _progress = new ProgressIndicator.fromName(progress, |
| 532 startTime, | 560 startTime, |
| 533 printTiming), | 561 printTiming), |
| 534 _batchProcesses = new List<DartcBatchRunnerProcess>(), | 562 _batchProcesses = new Map<String, List<BatchRunnerProcess>>(), |
| 535 _testCache = new Map<String, List<TestInformation>>() { | 563 _testCache = new Map<String, List<TestInformation>>() { |
| 536 if (!_enqueueMoreWork(this)) _progress.allDone(); | 564 if (!_enqueueMoreWork(this)) _progress.allDone(); |
| 537 browserUsed = ''; | 565 browserUsed = ''; |
| 538 } | 566 } |
| 539 | 567 |
| 540 /** | 568 /** |
| 541 * Registers a TestSuite so that all of its tests will be run. | 569 * Registers a TestSuite so that all of its tests will be run. |
| 542 */ | 570 */ |
| 543 void addTestSuite(TestSuite testSuite) { | 571 void addTestSuite(TestSuite testSuite) { |
| 544 _activeTestListers++; | 572 _activeTestListers++; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 567 /** | 595 /** |
| 568 * Sometimes Webdriver doesn't close every browser window when it's done | 596 * Sometimes Webdriver doesn't close every browser window when it's done |
| 569 * with a test. At the end of all tests we clear out any neglected processes | 597 * with a test. At the end of all tests we clear out any neglected processes |
| 570 * that are still running. | 598 * that are still running. |
| 571 */ | 599 */ |
| 572 void killZombieBrowsers() { | 600 void killZombieBrowsers() { |
| 573 String chromeName = 'chrome'; | 601 String chromeName = 'chrome'; |
| 574 if (new Platform().operatingSystem() == 'macos') { | 602 if (new Platform().operatingSystem() == 'macos') { |
| 575 chromeName = 'Google\ Chrome'; | 603 chromeName = 'Google\ Chrome'; |
| 576 } | 604 } |
| 577 Map<String, List<String>> processNames = {'ie': ['iexplore'], 'safari': | 605 Map<String, List<String>> processNames = {'ie': ['iexplore'], |
| 578 ['Safari'], 'ff': ['firefox'], 'chrome': ['chromedriver', chromeName]}; | 606 'safari': ['Safari'], 'ff': ['firefox', 'firefox-bin'], |
|
Emily Fortuna
2012/02/21 18:19:35
(+ firefox-bin) yay.
| |
| 607 'chrome': ['chromedriver', chromeName]}; | |
| 579 for (String name in processNames[browserUsed]) { | 608 for (String name in processNames[browserUsed]) { |
| 580 Process process = null; | 609 Process process = null; |
| 581 if (new Platform().operatingSystem() == 'windows') { | 610 if (new Platform().operatingSystem() == 'windows') { |
| 582 process = new Process.start( | 611 process = new Process.start( |
| 583 'C:\\Windows\\System32\\taskkill.exe', ['/F', '/IM', name + '.exe', | 612 'C:\\Windows\\System32\\taskkill.exe', ['/F', '/IM', name + '.exe', |
| 584 '/T']); | 613 '/T']); |
| 585 } else { | 614 } else { |
| 586 process = new Process.start('killall', ['-9', name]); | 615 process = new Process.start('killall', ['-9', name]); |
| 587 } | 616 } |
| 588 | 617 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 613 _progress.allDone(); | 642 _progress.allDone(); |
| 614 } | 643 } |
| 615 } | 644 } |
| 616 | 645 |
| 617 void _checkDone() { | 646 void _checkDone() { |
| 618 // When there are no more active test listers ask for more work | 647 // When there are no more active test listers ask for more work |
| 619 // from process queue users. | 648 // from process queue users. |
| 620 if (_activeTestListers == 0 && !_enqueueMoreWork(this)) { | 649 if (_activeTestListers == 0 && !_enqueueMoreWork(this)) { |
| 621 _progress.allTestsKnown(); | 650 _progress.allTestsKnown(); |
| 622 if (_tests.isEmpty() && _numProcesses == 0) { | 651 if (_tests.isEmpty() && _numProcesses == 0) { |
| 623 _terminateDartcBatchRunners(); | 652 _terminateBatchRunners(); |
| 624 if (_keepGeneratedTests || _temporaryDirectory == null) { | 653 if (_keepGeneratedTests || _temporaryDirectory == null) { |
| 625 _cleanupAndMarkDone(); | 654 _cleanupAndMarkDone(); |
| 626 } else if (!_temporaryDirectory.startsWith('/tmp/') || | 655 } else if (!_temporaryDirectory.startsWith('/tmp/') || |
| 627 _temporaryDirectory.contains('/../')) { | 656 _temporaryDirectory.contains('/../')) { |
| 628 // Let's be extra careful, since rm -rf is so dangerous. | 657 // Let's be extra careful, since rm -rf is so dangerous. |
| 629 print('Temporary directory $_temporaryDirectory unsafe to delete!'); | 658 print('Temporary directory $_temporaryDirectory unsafe to delete!'); |
| 630 _cleanupAndMarkDone(); | 659 _cleanupAndMarkDone(); |
| 631 } else { | 660 } else { |
| 632 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is | 661 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is |
| 633 // implemented, and add Windows support. | 662 // implemented, and add Windows support. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 650 | 679 |
| 651 void _runTest(TestCase test) { | 680 void _runTest(TestCase test) { |
| 652 if (test.configuration['component'] == 'webdriver') { | 681 if (test.configuration['component'] == 'webdriver') { |
| 653 browserUsed = test.configuration['browser']; | 682 browserUsed = test.configuration['browser']; |
| 654 } | 683 } |
| 655 _progress.testAdded(); | 684 _progress.testAdded(); |
| 656 _tests.add(test); | 685 _tests.add(test); |
| 657 _tryRunTest(); | 686 _tryRunTest(); |
| 658 } | 687 } |
| 659 | 688 |
| 660 void _terminateDartcBatchRunners() { | 689 void _terminateBatchRunners() { |
| 661 _batchProcesses.forEach((runner) => runner.terminate()); | 690 for (var runners in _batchProcesses.getValues()) { |
| 662 } | 691 for (var runner in runners) { |
| 663 | 692 runner.terminate(); |
| 664 void _ensureDartcBatchRunnersStarted(String executable) { | |
| 665 if (_batchProcesses.length == 0) { | |
| 666 for (int i = 0; i < _maxProcesses; i++) { | |
| 667 _batchProcesses.add(new DartcBatchRunnerProcess(executable)); | |
| 668 } | 693 } |
| 669 } | 694 } |
| 670 } | 695 } |
| 671 | 696 |
| 672 DartcBatchRunnerProcess _getDartcBatchRunnerProcess() { | 697 BatchRunnerProcess _getBatchRunner(TestCase test) { |
| 673 for (int i = 0; i < _batchProcesses.length; i++) { | 698 // Start batch processes if needed |
| 674 var runner = _batchProcesses[i]; | 699 var component = test.configuration['component']; |
| 700 var runners = _batchProcesses[component]; | |
| 701 if (runners == null) { | |
| 702 runners = new List<BatchRunnerProcess>(_maxProcesses); | |
| 703 for (int i = 0; i < _maxProcesses; i++) { | |
| 704 runners[i] = new BatchRunnerProcess(test); | |
| 705 } | |
| 706 _batchProcesses[component] = runners; | |
| 707 } | |
| 708 | |
| 709 for (var runner in runners) { | |
| 675 if (!runner.active) return runner; | 710 if (!runner.active) return runner; |
| 676 } | 711 } |
| 677 throw new Exception('Unable to find inactive batch runner.'); | 712 throw new Exception('Unable to find inactive batch runner.'); |
| 678 } | 713 } |
| 679 | 714 |
| 680 void _tryRunTest() { | 715 void _tryRunTest() { |
| 681 _checkDone(); | 716 _checkDone(); |
| 682 if (_numProcesses < _maxProcesses && !_tests.isEmpty()) { | 717 if (_numProcesses < _maxProcesses && !_tests.isEmpty()) { |
| 683 TestCase test = _tests.removeFirst(); | 718 TestCase test = _tests.removeFirst(); |
| 684 if (_verbose) print(test.commandLine); | 719 if (_verbose) print(test.commandLine); |
| 685 if (_listTests) { | 720 if (_listTests) { |
| 686 final String tab = '\t'; | 721 final String tab = '\t'; |
| 687 String outcomes = | 722 String outcomes = |
| 688 Strings.join(new List.from(test.expectedOutcomes), ','); | 723 Strings.join(new List.from(test.expectedOutcomes), ','); |
| 689 print(test.displayName + tab + outcomes + tab + test.isNegative + | 724 print(test.displayName + tab + outcomes + tab + test.isNegative + |
| 690 tab + Strings.join(test.arguments, tab)); | 725 tab + Strings.join(test.arguments, tab)); |
| 691 return; | 726 return; |
| 692 } | 727 } |
| 693 _progress.start(test); | 728 _progress.start(test); |
| 694 Function oldCallback = test.completedHandler; | 729 Function oldCallback = test.completedHandler; |
| 695 Function wrapper = (TestCase test_arg) { | 730 Function wrapper = (TestCase test_arg) { |
| 696 _numProcesses--; | 731 _numProcesses--; |
| 697 _progress.done(test_arg); | 732 _progress.done(test_arg); |
| 698 _tryRunTest(); | 733 _tryRunTest(); |
| 699 oldCallback(test_arg); | 734 oldCallback(test_arg); |
| 700 }; | 735 }; |
| 701 test.completedHandler = wrapper; | 736 test.completedHandler = wrapper; |
| 702 if (test.configuration['component'] == 'dartc' && | 737 if (test.configuration['component'] == 'dartc' && |
| 703 test.displayName != 'dartc/junit_tests') { | 738 test.displayName != 'dartc/junit_tests') { |
| 704 _ensureDartcBatchRunnersStarted(test.executablePath); | 739 _getBatchRunner(test).startTest(test); |
| 705 _getDartcBatchRunnerProcess().startTest(test); | |
| 706 } else { | 740 } else { |
| 707 new RunningProcess(test).start(); | 741 new RunningProcess(test, this).start(); |
| 708 } | 742 } |
| 709 _numProcesses++; | 743 _numProcesses++; |
| 710 } | 744 } |
| 711 } | 745 } |
| 712 } | 746 } |
| OLD | NEW |