| 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 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 timedOut = true; | 594 timedOut = true; |
| 595 process.kill(); | 595 process.kill(); |
| 596 } | 596 } |
| 597 } | 597 } |
| 598 | 598 |
| 599 class BatchRunnerProcess { | 599 class BatchRunnerProcess { |
| 600 String _executable; | 600 String _executable; |
| 601 List<String> _batchArguments; | 601 List<String> _batchArguments; |
| 602 | 602 |
| 603 Process _process; | 603 Process _process; |
| 604 bool _processDone = true; |
| 604 StringInputStream _stdoutStream; | 605 StringInputStream _stdoutStream; |
| 605 StringInputStream _stderrStream; | 606 StringInputStream _stderrStream; |
| 606 | 607 |
| 607 TestCase _currentTest; | 608 TestCase _currentTest; |
| 608 List<String> _testStdout; | 609 List<String> _testStdout; |
| 609 List<String> _testStderr; | 610 List<String> _testStderr; |
| 610 bool _stdoutDrained = false; | 611 bool _stdoutDrained = false; |
| 611 bool _stderrDrained = false; | 612 bool _stderrDrained = false; |
| 613 String _status; |
| 612 Date _startTime; | 614 Date _startTime; |
| 613 Timer _timer; | 615 Timer _timer; |
| 614 | 616 |
| 615 bool _isWebDriver; | 617 bool _isWebDriver; |
| 616 | 618 |
| 617 BatchRunnerProcess(TestCase testCase) { | 619 BatchRunnerProcess(TestCase testCase) { |
| 618 _executable = testCase.commands.last().executable; | 620 _executable = testCase.commands.last().executable; |
| 619 _batchArguments = testCase.batchRunnerArguments; | 621 _batchArguments = testCase.batchRunnerArguments; |
| 620 _isWebDriver = testCase.usesWebDriver; | 622 _isWebDriver = testCase.usesWebDriver; |
| 621 } | 623 } |
| 622 | 624 |
| 623 bool get active() => _currentTest != null; | 625 bool get active() => _currentTest != null; |
| 624 | 626 |
| 625 void startTest(TestCase testCase) { | 627 void startTest(TestCase testCase) { |
| 626 _currentTest = testCase; | 628 _currentTest = testCase; |
| 627 if (_process === null) { | 629 if (_processDone) { |
| 628 // Start process if not yet started. | 630 // Start process if not yet started. |
| 629 _executable = testCase.commands.last().executable; | 631 _executable = testCase.commands.last().executable; |
| 630 _startProcess(() { | 632 _startProcess(() { |
| 631 doStartTest(testCase); | 633 doStartTest(testCase); |
| 632 }); | 634 }); |
| 633 } else if (testCase.commands.last().executable != _executable) { | 635 } else if (testCase.commands.last().executable != _executable) { |
| 634 // Restart this runner with the right executable for this test | 636 // Restart this runner with the right executable for this test |
| 635 // if needed. | 637 // if needed. |
| 636 _executable = testCase.commands.last().executable; | 638 _executable = testCase.commands.last().executable; |
| 637 _batchArguments = testCase.batchRunnerArguments; | 639 _batchArguments = testCase.batchRunnerArguments; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 return Strings.join(arguments, ' ') + '\n'; | 688 return Strings.join(arguments, ' ') + '\n'; |
| 687 } | 689 } |
| 688 | 690 |
| 689 void _testCompleted() { | 691 void _testCompleted() { |
| 690 var test = _currentTest; | 692 var test = _currentTest; |
| 691 _currentTest = null; | 693 _currentTest = null; |
| 692 test.completed(); | 694 test.completed(); |
| 693 } | 695 } |
| 694 | 696 |
| 695 int _reportResult(String output) { | 697 int _reportResult(String output) { |
| 696 _stdoutDrained = true; | |
| 697 // output = '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' | 698 // output = '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' |
| 698 var outcome = output.split(" ")[2]; | 699 var outcome = output.split(" ")[2]; |
| 699 var exitCode = 0; | 700 var exitCode = 0; |
| 700 if (outcome == "CRASH") exitCode = -10; | 701 if (outcome == "CRASH") exitCode = -10; |
| 701 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; | 702 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; |
| 702 new TestOutput.fromCase(_currentTest, exitCode, outcome == "TIMEOUT", | 703 new TestOutput.fromCase(_currentTest, exitCode, outcome == "TIMEOUT", |
| 703 _testStdout, _testStderr, new Date.now().difference(_startTim
e)); | 704 _testStdout, _testStderr, new Date.now().difference(_startTim
e)); |
| 704 // Move on when both stdout and stderr has been drained. If the test | 705 // Move on when both stdout and stderr has been drained. If the test |
| 705 // crashed, we restarted the process and therefore do not attempt to | 706 // crashed, we restarted the process and therefore do not attempt to |
| 706 // drain stderr. | 707 // drain stderr. |
| 707 if (_stderrDrained || (_currentTest.output.hasCrashed)) _testCompleted(); | 708 if (_stderrDrained) _testCompleted(); |
| 708 } | |
| 709 | |
| 710 void _stderrDone() { | |
| 711 _stderrDrained = true; | |
| 712 // Move on when both stdout and stderr has been drained. | |
| 713 if (_stdoutDrained) _testCompleted(); | |
| 714 } | 709 } |
| 715 | 710 |
| 716 Function _readStdout(StringInputStream stream, List<String> buffer) { | 711 Function _readStdout(StringInputStream stream, List<String> buffer) { |
| 717 return () { | 712 return () { |
| 718 var status; | 713 var status; |
| 719 var line = stream.readLine(); | 714 var line = stream.readLine(); |
| 720 while (line != null) { | 715 while (line != null) { |
| 721 if (line.startsWith('>>> TEST')) { | 716 if (line.startsWith('>>> TEST')) { |
| 722 status = line; | 717 status = line; |
| 718 _stdoutDrained = true; |
| 723 } else if (line.startsWith('>>> BATCH START')) { | 719 } else if (line.startsWith('>>> BATCH START')) { |
| 724 // ignore | 720 // ignore |
| 725 } else if (line.startsWith('>>> ')) { | 721 } else if (line.startsWith('>>> ')) { |
| 726 throw new Exception('Unexpected command from dartc batch runner.'); | 722 throw new Exception('Unexpected command from dartc batch runner.'); |
| 727 } else { | 723 } else { |
| 728 buffer.add(line); | 724 buffer.add(line); |
| 729 } | 725 } |
| 730 line = stream.readLine(); | 726 line = stream.readLine(); |
| 731 } | 727 } |
| 732 if (status != null) { | 728 if (status != null) { |
| 733 _timer.cancel(); | 729 _timer.cancel(); |
| 734 // For crashing processes, let the exit handler deal with it. | 730 this._status = status; |
| 735 if (!status.contains("CRASH")) { | 731 if (_stderrDrained) { |
| 736 _reportResult(status); | 732 _reportResult(status); |
| 733 if (_processDone) { |
| 734 _startProcess(); |
| 735 } |
| 737 } | 736 } |
| 738 } | 737 } |
| 739 }; | 738 }; |
| 740 } | 739 } |
| 741 | 740 |
| 742 Function _readStderr(StringInputStream stream, List<String> buffer) { | 741 Function _readStderr(StringInputStream stream, List<String> buffer) { |
| 743 return () { | 742 return () { |
| 744 var line = stream.readLine(); | 743 var line = stream.readLine(); |
| 745 while (line != null) { | 744 while (line != null) { |
| 745 var status; |
| 746 if (line.startsWith('>>> EOF STDERR')) { | 746 if (line.startsWith('>>> EOF STDERR')) { |
| 747 _stderrDone(); | 747 _stderrDrained = true; |
| 748 if (_stdoutDrained) { |
| 749 _reportResult(this._status); |
| 750 if (_processDone) { |
| 751 _startProcess(); |
| 752 } |
| 753 } |
| 748 } else { | 754 } else { |
| 749 buffer.add(line); | 755 buffer.add(line); |
| 750 } | 756 } |
| 751 line = stream.readLine(); | 757 line = stream.readLine(); |
| 752 } | 758 } |
| 753 }; | 759 }; |
| 754 } | 760 } |
| 755 | 761 |
| 756 void _exitHandler(exitCode) { | 762 void _exitHandler(exitCode) { |
| 757 if (_timer != null) _timer.cancel(); | 763 if (_timer != null) _timer.cancel(); |
| 758 _process.close(); | 764 _process.close(); |
| 759 _startProcess(() { | 765 _processDone = true; |
| 760 _reportResult(">>> TEST CRASH"); | 766 if (_stdoutDrained && _stderrDrained) { |
| 761 }); | 767 _startProcess(); |
| 768 } |
| 762 } | 769 } |
| 763 | 770 |
| 764 void _timeoutHandler(ignore) { | 771 void _timeoutHandler(ignore) { |
| 765 _process.onExit = (exitCode) { | 772 _process.onExit = (exitCode) { |
| 766 _process.close(); | 773 _process.close(); |
| 767 _startProcess(() { | 774 _startProcess(() { |
| 768 _reportResult(">>> TEST TIMEOUT"); | 775 _reportResult(">>> TEST TIMEOUT"); |
| 769 }); | 776 }); |
| 770 }; | 777 }; |
| 771 _process.kill(); | 778 _process.kill(); |
| 772 } | 779 } |
| 773 | 780 |
| 774 void _startProcess(then) { | 781 void _startProcess([then = null]) { |
| 775 _process = new Process.start(_executable, _batchArguments); | 782 _process = new Process.start(_executable, _batchArguments); |
| 783 _processDone = false; |
| 776 _stdoutStream = new StringInputStream(_process.stdout); | 784 _stdoutStream = new StringInputStream(_process.stdout); |
| 777 _stderrStream = new StringInputStream(_process.stderr); | 785 _stderrStream = new StringInputStream(_process.stderr); |
| 778 _testStdout = new List<String>(); | 786 _testStdout = new List<String>(); |
| 779 _testStderr = new List<String>(); | 787 _testStderr = new List<String>(); |
| 780 _stdoutDrained = false; | 788 _stdoutDrained = false; |
| 781 _stderrDrained = false; | 789 _stderrDrained = false; |
| 782 _stdoutStream.onLine = _readStdout(_stdoutStream, _testStdout); | 790 _stdoutStream.onLine = _readStdout(_stdoutStream, _testStdout); |
| 783 _stderrStream.onLine = _readStderr(_stderrStream, _testStderr); | 791 _stderrStream.onLine = _readStderr(_stderrStream, _testStderr); |
| 784 _process.onExit = _exitHandler; | 792 _process.onExit = _exitHandler; |
| 785 _process.onStart = then; | 793 _process.onStart = then; |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1110 // the developer doesn't waste his or her time trying to fix a bunch of | 1118 // the developer doesn't waste his or her time trying to fix a bunch of |
| 1111 // tests that appear to be broken but were actually just flakes that | 1119 // tests that appear to be broken but were actually just flakes that |
| 1112 // didn't get retried because there had already been one failure. | 1120 // didn't get retried because there had already been one failure. |
| 1113 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; | 1121 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; |
| 1114 new RunningProcess(test, allowRetry, this).start(); | 1122 new RunningProcess(test, allowRetry, this).start(); |
| 1115 } | 1123 } |
| 1116 _numProcesses++; | 1124 _numProcesses++; |
| 1117 } | 1125 } |
| 1118 } | 1126 } |
| 1119 } | 1127 } |
| OLD | NEW |