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 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 | 353 |
354 void runCommand(Command command, | 354 void runCommand(Command command, |
355 void exitHandler(int exitCode)) { | 355 void exitHandler(int exitCode)) { |
356 if (new Platform().operatingSystem() == 'windows') { | 356 if (new Platform().operatingSystem() == 'windows') { |
357 // Windows can't handle the first command if it is a .bat file or the like | 357 // Windows can't handle the first command if it is a .bat file or the like |
358 // with the slashes going the other direction. | 358 // with the slashes going the other direction. |
359 // TODO(efortuna): Remove this when fixed (Issue 1306). | 359 // TODO(efortuna): Remove this when fixed (Issue 1306). |
360 command.executable = command.executable.replaceAll('/', '\\'); | 360 command.executable = command.executable.replaceAll('/', '\\'); |
361 } | 361 } |
362 process = new Process.start(command.executable, command.arguments); | 362 process = new Process.start(command.executable, command.arguments); |
363 process.exitHandler = exitHandler; | 363 process.onExit = exitHandler; |
364 startTime = new Date.now(); | 364 startTime = new Date.now(); |
365 InputStream stdoutStream = process.stdout; | 365 InputStream stdoutStream = process.stdout; |
366 InputStream stderrStream = process.stderr; | 366 InputStream stderrStream = process.stderr; |
367 StringInputStream stdoutStringStream = new StringInputStream(stdoutStream); | 367 StringInputStream stdoutStringStream = new StringInputStream(stdoutStream); |
368 StringInputStream stderrStringStream = new StringInputStream(stderrStream); | 368 StringInputStream stderrStringStream = new StringInputStream(stderrStream); |
369 stdoutStringStream.lineHandler = | 369 stdoutStringStream.onLine = |
370 makeReadHandler(stdoutStringStream, stdout); | 370 makeReadHandler(stdoutStringStream, stdout); |
371 stderrStringStream.lineHandler = | 371 stderrStringStream.onLine = |
372 makeReadHandler(stderrStringStream, stderr); | 372 makeReadHandler(stderrStringStream, stderr); |
373 timeoutTimer = new Timer(timeoutHandler, 1000 * testCase.timeout); | 373 timeoutTimer = new Timer(timeoutHandler, 1000 * testCase.timeout); |
374 } | 374 } |
375 | 375 |
376 void timeoutHandler(Timer unusedTimer) { | 376 void timeoutHandler(Timer unusedTimer) { |
377 timedOut = true; | 377 timedOut = true; |
378 process.kill(); | 378 process.kill(); |
379 } | 379 } |
380 } | 380 } |
381 | 381 |
(...skipping 27 matching lines...) Expand all Loading... |
409 // Start process if not yet started. | 409 // Start process if not yet started. |
410 _executable = testCase.commands.last().executable; | 410 _executable = testCase.commands.last().executable; |
411 _startProcess(() { | 411 _startProcess(() { |
412 doStartTest(testCase); | 412 doStartTest(testCase); |
413 }); | 413 }); |
414 } else if (testCase.commands.last().executable != _executable) { | 414 } else if (testCase.commands.last().executable != _executable) { |
415 // Restart this runner with the right executable for this test | 415 // Restart this runner with the right executable for this test |
416 // if needed. | 416 // if needed. |
417 _executable = testCase.commands.last().executable; | 417 _executable = testCase.commands.last().executable; |
418 _batchArguments = testCase.batchRunnerArguments; | 418 _batchArguments = testCase.batchRunnerArguments; |
419 _process.exitHandler = (exitCode) { | 419 _process.onExit = (exitCode) { |
420 _process.close(); | 420 _process.close(); |
421 _startProcess(() { | 421 _startProcess(() { |
422 doStartTest(testCase); | 422 doStartTest(testCase); |
423 }); | 423 }); |
424 }; | 424 }; |
425 _process.kill(); | 425 _process.kill(); |
426 } else { | 426 } else { |
427 doStartTest(testCase); | 427 doStartTest(testCase); |
428 } | 428 } |
429 } | 429 } |
430 | 430 |
431 void terminate() { | 431 void terminate() { |
432 if (_process !== null) { | 432 if (_process !== null) { |
433 bool closed = false; | 433 bool closed = false; |
434 _process.exitHandler = (exitCode) { | 434 _process.onExit = (exitCode) { |
435 closed = true; | 435 closed = true; |
436 _process.close(); | 436 _process.close(); |
437 }; | 437 }; |
438 if (_isWebDriver) { | 438 if (_isWebDriver) { |
439 // Use a graceful shutdown so our Selenium script can close | 439 // Use a graceful shutdown so our Selenium script can close |
440 // the open browser processes. TODO(jmesserly): Send a signal once | 440 // the open browser processes. TODO(jmesserly): Send a signal once |
441 // that's supported, see dartbug.com/1756. | 441 // that's supported, see dartbug.com/1756. |
442 _process.stdin.write('--terminate\n'.charCodes()); | 442 _process.stdin.write('--terminate\n'.charCodes()); |
443 | 443 |
444 // In case the run_selenium process didn't close, kill it after 30s | 444 // In case the run_selenium process didn't close, kill it after 30s |
445 bool shutdownMillisecs = 30000; | 445 bool shutdownMillisecs = 30000; |
446 new Timer((e) { if (!closed) _process.kill(); }, shutdownMillisecs); | 446 new Timer((e) { if (!closed) _process.kill(); }, shutdownMillisecs); |
447 } else { | 447 } else { |
448 _process.kill(); | 448 _process.kill(); |
449 } | 449 } |
450 } | 450 } |
451 } | 451 } |
452 | 452 |
453 void doStartTest(TestCase testCase) { | 453 void doStartTest(TestCase testCase) { |
454 _startTime = new Date.now(); | 454 _startTime = new Date.now(); |
455 _testStdout = new List<String>(); | 455 _testStdout = new List<String>(); |
456 _testStderr = new List<String>(); | 456 _testStderr = new List<String>(); |
457 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout); | 457 _stdoutStream.onLine = _readOutput(_stdoutStream, _testStdout); |
458 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr); | 458 _stderrStream.onLine = _readOutput(_stderrStream, _testStderr); |
459 _timer = new Timer(_timeoutHandler, testCase.timeout * 1000); | 459 _timer = new Timer(_timeoutHandler, testCase.timeout * 1000); |
460 var line = _createArgumentsLine(testCase.batchTestArguments); | 460 var line = _createArgumentsLine(testCase.batchTestArguments); |
461 _process.stdin.write(line.charCodes()); | 461 _process.stdin.write(line.charCodes()); |
462 } | 462 } |
463 | 463 |
464 String _createArgumentsLine(List<String> arguments) { | 464 String _createArgumentsLine(List<String> arguments) { |
465 return Strings.join(arguments, ' ') + '\n'; | 465 return Strings.join(arguments, ' ') + '\n'; |
466 } | 466 } |
467 | 467 |
468 int _reportResult(String output) { | 468 int _reportResult(String output) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 | 508 |
509 void _exitHandler(exitCode) { | 509 void _exitHandler(exitCode) { |
510 if (_timer != null) _timer.cancel(); | 510 if (_timer != null) _timer.cancel(); |
511 _process.close(); | 511 _process.close(); |
512 _startProcess(() { | 512 _startProcess(() { |
513 _reportResult(">>> TEST CRASH"); | 513 _reportResult(">>> TEST CRASH"); |
514 }); | 514 }); |
515 } | 515 } |
516 | 516 |
517 void _timeoutHandler(ignore) { | 517 void _timeoutHandler(ignore) { |
518 _process.exitHandler = (exitCode) { | 518 _process.onExit = (exitCode) { |
519 _process.close(); | 519 _process.close(); |
520 _startProcess(() { | 520 _startProcess(() { |
521 _reportResult(">>> TEST TIMEOUT"); | 521 _reportResult(">>> TEST TIMEOUT"); |
522 }); | 522 }); |
523 }; | 523 }; |
524 _process.kill(); | 524 _process.kill(); |
525 } | 525 } |
526 | 526 |
527 void _startProcess(then) { | 527 void _startProcess(then) { |
528 _process = new Process.start(_executable, _batchArguments); | 528 _process = new Process.start(_executable, _batchArguments); |
529 _stdoutStream = new StringInputStream(_process.stdout); | 529 _stdoutStream = new StringInputStream(_process.stdout); |
530 _stderrStream = new StringInputStream(_process.stderr); | 530 _stderrStream = new StringInputStream(_process.stderr); |
531 _testStdout = new List<String>(); | 531 _testStdout = new List<String>(); |
532 _testStderr = new List<String>(); | 532 _testStderr = new List<String>(); |
533 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout); | 533 _stdoutStream.onLine = _readOutput(_stdoutStream, _testStdout); |
534 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr); | 534 _stderrStream.onLine = _readOutput(_stderrStream, _testStderr); |
535 _process.exitHandler = _exitHandler; | 535 _process.onExit = _exitHandler; |
536 _process.startHandler = then; | 536 _process.onStart = then; |
537 } | 537 } |
538 } | 538 } |
539 | 539 |
540 /** | 540 /** |
541 * ProcessQueue is the master control class, responsible for running all | 541 * ProcessQueue is the master control class, responsible for running all |
542 * the tests in all the TestSuites that have been registered. It includes | 542 * the tests in all the TestSuites that have been registered. It includes |
543 * a rate-limited queue to run a limited number of tests in parallel, | 543 * a rate-limited queue to run a limited number of tests in parallel, |
544 * a ProgressIndicator which prints output when tests are started and | 544 * a ProgressIndicator which prints output when tests are started and |
545 * and completed, and a summary report when all tests are completed, | 545 * and completed, and a summary report when all tests are completed, |
546 * and counters to determine when all of the tests in all of the test suites | 546 * and counters to determine when all of the tests in all of the test suites |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 Process process = null; | 639 Process process = null; |
640 if (new Platform().operatingSystem() == 'windows') { | 640 if (new Platform().operatingSystem() == 'windows') { |
641 process = new Process.start( | 641 process = new Process.start( |
642 'C:\\Windows\\System32\\taskkill.exe', ['/F', '/IM', name + '.exe', | 642 'C:\\Windows\\System32\\taskkill.exe', ['/F', '/IM', name + '.exe', |
643 '/T']); | 643 '/T']); |
644 } else { | 644 } else { |
645 process = new Process.start('killall', ['-9', name]); | 645 process = new Process.start('killall', ['-9', name]); |
646 } | 646 } |
647 | 647 |
648 if (name == processNames[browserUsed].last()) { | 648 if (name == processNames[browserUsed].last()) { |
649 process.exitHandler = (exitCode) { | 649 process.onExit = (exitCode) { |
650 process.close(); | 650 process.close(); |
651 _progress.allDone(); | 651 _progress.allDone(); |
652 }; | 652 }; |
653 process.errorHandler = (error) { | 653 process.onError = (error) { |
654 _progress.allDone(); | 654 _progress.allDone(); |
655 }; | 655 }; |
656 } else { | 656 } else { |
657 process.exitHandler = (exitCode) { | 657 process.onExit = (exitCode) { |
658 process.close(); | 658 process.close(); |
659 }; | 659 }; |
660 } | 660 } |
661 } | 661 } |
662 } | 662 } |
663 | 663 |
664 /** | 664 /** |
665 * Perform any cleanup needed once all tests in a TestSuite have completed | 665 * Perform any cleanup needed once all tests in a TestSuite have completed |
666 * and notify our progress indicator that we are done. | 666 * and notify our progress indicator that we are done. |
667 */ | 667 */ |
(...skipping 17 matching lines...) Expand all Loading... |
685 } else if (!_temporaryDirectory.startsWith('/tmp/') || | 685 } else if (!_temporaryDirectory.startsWith('/tmp/') || |
686 _temporaryDirectory.contains('/../')) { | 686 _temporaryDirectory.contains('/../')) { |
687 // Let's be extra careful, since rm -rf is so dangerous. | 687 // Let's be extra careful, since rm -rf is so dangerous. |
688 print('Temporary directory $_temporaryDirectory unsafe to delete!'); | 688 print('Temporary directory $_temporaryDirectory unsafe to delete!'); |
689 _cleanupAndMarkDone(); | 689 _cleanupAndMarkDone(); |
690 } else { | 690 } else { |
691 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is | 691 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is |
692 // implemented, and add Windows support. | 692 // implemented, and add Windows support. |
693 var deletion = | 693 var deletion = |
694 new Process.start('/bin/rm', ['-rf', _temporaryDirectory]); | 694 new Process.start('/bin/rm', ['-rf', _temporaryDirectory]); |
695 deletion.exitHandler = (int exitCode) { | 695 deletion.onExit = (int exitCode) { |
696 if (exitCode == 0) { | 696 if (exitCode == 0) { |
697 if (!_listTests) { // Output of --list option is used by scripts. | 697 if (!_listTests) { // Output of --list option is used by scripts. |
698 print('\nTemporary directory $_temporaryDirectory deleted.'); | 698 print('\nTemporary directory $_temporaryDirectory deleted.'); |
699 } | 699 } |
700 } else { | 700 } else { |
701 print('\nDeletion of temp dir $_temporaryDirectory failed.'); | 701 print('\nDeletion of temp dir $_temporaryDirectory failed.'); |
702 } | 702 } |
703 _cleanupAndMarkDone(); | 703 _cleanupAndMarkDone(); |
704 }; | 704 }; |
705 } | 705 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
775 // the developer doesn't waste his or her time trying to fix a bunch of | 775 // the developer doesn't waste his or her time trying to fix a bunch of |
776 // tests that appear to be broken but were actually just flakes that | 776 // tests that appear to be broken but were actually just flakes that |
777 // didn't get retried because there had already been one failure. | 777 // didn't get retried because there had already been one failure. |
778 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; | 778 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; |
779 new RunningProcess(test, allowRetry, this).start(); | 779 new RunningProcess(test, allowRetry, this).start(); |
780 } | 780 } |
781 _numProcesses++; | 781 _numProcesses++; |
782 } | 782 } |
783 } | 783 } |
784 } | 784 } |
OLD | NEW |