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.onExit = exitHandler; | 363 process.exitHandler = 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.onLine = | 369 stdoutStringStream.lineHandler = |
370 makeReadHandler(stdoutStringStream, stdout); | 370 makeReadHandler(stdoutStringStream, stdout); |
371 stderrStringStream.onLine = | 371 stderrStringStream.lineHandler = |
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 28 matching lines...) Expand all Loading... |
410 // Start process if not yet started. | 410 // Start process if not yet started. |
411 _executable = testCase.commands.last().executable; | 411 _executable = testCase.commands.last().executable; |
412 _startProcess(() { | 412 _startProcess(() { |
413 doStartTest(testCase); | 413 doStartTest(testCase); |
414 }); | 414 }); |
415 } else if (testCase.commands.last().executable != _executable) { | 415 } else if (testCase.commands.last().executable != _executable) { |
416 // Restart this runner with the right executable for this test | 416 // Restart this runner with the right executable for this test |
417 // if needed. | 417 // if needed. |
418 _executable = testCase.commands.last().executable; | 418 _executable = testCase.commands.last().executable; |
419 _batchArguments = testCase.batchRunnerArguments; | 419 _batchArguments = testCase.batchRunnerArguments; |
420 _process.onExit = (exitCode) { | 420 _process.exitHandler = (exitCode) { |
421 _process.close(); | 421 _process.close(); |
422 _startProcess(() { | 422 _startProcess(() { |
423 doStartTest(testCase); | 423 doStartTest(testCase); |
424 }); | 424 }); |
425 }; | 425 }; |
426 _process.kill(); | 426 _process.kill(); |
427 } else { | 427 } else { |
428 doStartTest(testCase); | 428 doStartTest(testCase); |
429 } | 429 } |
430 } | 430 } |
431 | 431 |
432 void terminate() { | 432 void terminate() { |
433 if (_process !== null) { | 433 if (_process !== null) { |
434 bool closed = false; | 434 bool closed = false; |
435 _process.onExit = (exitCode) { | 435 _process.exitHandler = (exitCode) { |
436 closed = true; | 436 closed = true; |
437 _process.close(); | 437 _process.close(); |
438 }; | 438 }; |
439 if (_isWebDriver) { | 439 if (_isWebDriver) { |
440 // Use a graceful shutdown so our Selenium script can close | 440 // Use a graceful shutdown so our Selenium script can close |
441 // the open browser processes. TODO(jmesserly): Send a signal once | 441 // the open browser processes. TODO(jmesserly): Send a signal once |
442 // that's supported, see dartbug.com/1756. | 442 // that's supported, see dartbug.com/1756. |
443 _process.stdin.write('--terminate\n'.charCodes()); | 443 _process.stdin.write('--terminate\n'.charCodes()); |
444 | 444 |
445 // In case the run_selenium process didn't close, kill it after 30s | 445 // In case the run_selenium process didn't close, kill it after 30s |
446 bool shutdownMillisecs = 30000; | 446 bool shutdownMillisecs = 30000; |
447 new Timer((e) { if (!closed) _process.kill(); }, shutdownMillisecs); | 447 new Timer((e) { if (!closed) _process.kill(); }, shutdownMillisecs); |
448 } else { | 448 } else { |
449 _process.kill(); | 449 _process.kill(); |
450 } | 450 } |
451 } | 451 } |
452 } | 452 } |
453 | 453 |
454 void doStartTest(TestCase testCase) { | 454 void doStartTest(TestCase testCase) { |
455 _startTime = new Date.now(); | 455 _startTime = new Date.now(); |
456 _testStdout = new List<String>(); | 456 _testStdout = new List<String>(); |
457 _testStderr = new List<String>(); | 457 _testStderr = new List<String>(); |
458 _stderrDrained = false; | 458 _stderrDrained = false; |
459 _stdoutStream.onLine = _readStdout(_stdoutStream, _testStdout); | 459 _stdoutStream.lineHandler = _readStdout(_stdoutStream, _testStdout); |
460 _stderrStream.onLine = _readStderr(_stderrStream, _testStderr); | 460 _stderrStream.lineHandler = _readStderr(_stderrStream, _testStderr); |
461 _timer = new Timer(_timeoutHandler, testCase.timeout * 1000); | 461 _timer = new Timer(_timeoutHandler, testCase.timeout * 1000); |
462 var line = _createArgumentsLine(testCase.batchTestArguments); | 462 var line = _createArgumentsLine(testCase.batchTestArguments); |
463 _process.stdin.write(line.charCodes()); | 463 _process.stdin.write(line.charCodes()); |
464 } | 464 } |
465 | 465 |
466 String _createArgumentsLine(List<String> arguments) { | 466 String _createArgumentsLine(List<String> arguments) { |
467 return Strings.join(arguments, ' ') + '\n'; | 467 return Strings.join(arguments, ' ') + '\n'; |
468 } | 468 } |
469 | 469 |
470 void _testCompleted() { | 470 void _testCompleted() { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
533 | 533 |
534 void _exitHandler(exitCode) { | 534 void _exitHandler(exitCode) { |
535 if (_timer != null) _timer.cancel(); | 535 if (_timer != null) _timer.cancel(); |
536 _process.close(); | 536 _process.close(); |
537 _startProcess(() { | 537 _startProcess(() { |
538 _reportResult(">>> TEST CRASH"); | 538 _reportResult(">>> TEST CRASH"); |
539 }); | 539 }); |
540 } | 540 } |
541 | 541 |
542 void _timeoutHandler(ignore) { | 542 void _timeoutHandler(ignore) { |
543 _process.onExit = (exitCode) { | 543 _process.exitHandler = (exitCode) { |
544 _process.close(); | 544 _process.close(); |
545 _startProcess(() { | 545 _startProcess(() { |
546 _reportResult(">>> TEST TIMEOUT"); | 546 _reportResult(">>> TEST TIMEOUT"); |
547 }); | 547 }); |
548 }; | 548 }; |
549 _process.kill(); | 549 _process.kill(); |
550 } | 550 } |
551 | 551 |
552 void _startProcess(then) { | 552 void _startProcess(then) { |
553 _process = new Process.start(_executable, _batchArguments); | 553 _process = new Process.start(_executable, _batchArguments); |
554 _stdoutStream = new StringInputStream(_process.stdout); | 554 _stdoutStream = new StringInputStream(_process.stdout); |
555 _stderrStream = new StringInputStream(_process.stderr); | 555 _stderrStream = new StringInputStream(_process.stderr); |
556 _testStdout = new List<String>(); | 556 _testStdout = new List<String>(); |
557 _testStderr = new List<String>(); | 557 _testStderr = new List<String>(); |
558 _stderrDrained = false; | 558 _stderrDrained = false; |
559 _stdoutStream.onLine = _readStdout(_stdoutStream, _testStdout); | 559 _stdoutStream.lineHandler = _readStdout(_stdoutStream, _testStdout); |
560 _stderrStream.onLine = _readStderr(_stderrStream, _testStderr); | 560 _stderrStream.lineHandler = _readStderr(_stderrStream, _testStderr); |
561 _process.onExit = _exitHandler; | 561 _process.exitHandler = _exitHandler; |
562 _process.onStart = then; | 562 _process.startHandler = then; |
563 } | 563 } |
564 } | 564 } |
565 | 565 |
566 /** | 566 /** |
567 * ProcessQueue is the master control class, responsible for running all | 567 * ProcessQueue is the master control class, responsible for running all |
568 * the tests in all the TestSuites that have been registered. It includes | 568 * the tests in all the TestSuites that have been registered. It includes |
569 * a rate-limited queue to run a limited number of tests in parallel, | 569 * a rate-limited queue to run a limited number of tests in parallel, |
570 * a ProgressIndicator which prints output when tests are started and | 570 * a ProgressIndicator which prints output when tests are started and |
571 * and completed, and a summary report when all tests are completed, | 571 * and completed, and a summary report when all tests are completed, |
572 * and counters to determine when all of the tests in all of the test suites | 572 * 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... |
665 Process process = null; | 665 Process process = null; |
666 if (new Platform().operatingSystem() == 'windows') { | 666 if (new Platform().operatingSystem() == 'windows') { |
667 process = new Process.start( | 667 process = new Process.start( |
668 'C:\\Windows\\System32\\taskkill.exe', ['/F', '/IM', name + '.exe', | 668 'C:\\Windows\\System32\\taskkill.exe', ['/F', '/IM', name + '.exe', |
669 '/T']); | 669 '/T']); |
670 } else { | 670 } else { |
671 process = new Process.start('killall', ['-9', name]); | 671 process = new Process.start('killall', ['-9', name]); |
672 } | 672 } |
673 | 673 |
674 if (name == processNames[browserUsed].last()) { | 674 if (name == processNames[browserUsed].last()) { |
675 process.onExit = (exitCode) { | 675 process.exitHandler = (exitCode) { |
676 process.close(); | 676 process.close(); |
677 _progress.allDone(); | 677 _progress.allDone(); |
678 }; | 678 }; |
679 process.onError = (error) { | 679 process.errorHandler = (error) { |
680 _progress.allDone(); | 680 _progress.allDone(); |
681 }; | 681 }; |
682 } else { | 682 } else { |
683 process.onExit = (exitCode) { | 683 process.exitHandler = (exitCode) { |
684 process.close(); | 684 process.close(); |
685 }; | 685 }; |
686 } | 686 } |
687 } | 687 } |
688 } | 688 } |
689 | 689 |
690 /** | 690 /** |
691 * Perform any cleanup needed once all tests in a TestSuite have completed | 691 * Perform any cleanup needed once all tests in a TestSuite have completed |
692 * and notify our progress indicator that we are done. | 692 * and notify our progress indicator that we are done. |
693 */ | 693 */ |
(...skipping 17 matching lines...) Expand all Loading... |
711 } else if (!_temporaryDirectory.startsWith('/tmp/') || | 711 } else if (!_temporaryDirectory.startsWith('/tmp/') || |
712 _temporaryDirectory.contains('/../')) { | 712 _temporaryDirectory.contains('/../')) { |
713 // Let's be extra careful, since rm -rf is so dangerous. | 713 // Let's be extra careful, since rm -rf is so dangerous. |
714 print('Temporary directory $_temporaryDirectory unsafe to delete!'); | 714 print('Temporary directory $_temporaryDirectory unsafe to delete!'); |
715 _cleanupAndMarkDone(); | 715 _cleanupAndMarkDone(); |
716 } else { | 716 } else { |
717 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is | 717 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is |
718 // implemented, and add Windows support. | 718 // implemented, and add Windows support. |
719 var deletion = | 719 var deletion = |
720 new Process.start('/bin/rm', ['-rf', _temporaryDirectory]); | 720 new Process.start('/bin/rm', ['-rf', _temporaryDirectory]); |
721 deletion.onExit = (int exitCode) { | 721 deletion.exitHandler = (int exitCode) { |
722 if (exitCode == 0) { | 722 if (exitCode == 0) { |
723 if (!_listTests) { // Output of --list option is used by scripts. | 723 if (!_listTests) { // Output of --list option is used by scripts. |
724 print('\nTemporary directory $_temporaryDirectory deleted.'); | 724 print('\nTemporary directory $_temporaryDirectory deleted.'); |
725 } | 725 } |
726 } else { | 726 } else { |
727 print('\nDeletion of temp dir $_temporaryDirectory failed.'); | 727 print('\nDeletion of temp dir $_temporaryDirectory failed.'); |
728 } | 728 } |
729 _cleanupAndMarkDone(); | 729 _cleanupAndMarkDone(); |
730 }; | 730 }; |
731 } | 731 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 // the developer doesn't waste his or her time trying to fix a bunch of | 801 // the developer doesn't waste his or her time trying to fix a bunch of |
802 // tests that appear to be broken but were actually just flakes that | 802 // tests that appear to be broken but were actually just flakes that |
803 // didn't get retried because there had already been one failure. | 803 // didn't get retried because there had already been one failure. |
804 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; | 804 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; |
805 new RunningProcess(test, allowRetry, this).start(); | 805 new RunningProcess(test, allowRetry, this).start(); |
806 } | 806 } |
807 _numProcesses++; | 807 _numProcesses++; |
808 } | 808 } |
809 } | 809 } |
810 } | 810 } |
OLD | NEW |