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 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 573 } | 573 } |
| 574 } | 574 } |
| 575 | 575 |
| 576 class CommandBuilder { | 576 class CommandBuilder { |
| 577 static final CommandBuilder instance = new CommandBuilder._(); | 577 static final CommandBuilder instance = new CommandBuilder._(); |
| 578 | 578 |
| 579 final _cachedCommands = new Map<Command, Command>(); | 579 final _cachedCommands = new Map<Command, Command>(); |
| 580 | 580 |
| 581 CommandBuilder._(); | 581 CommandBuilder._(); |
| 582 | 582 |
| 583 void clearCommandCache() { | |
| 584 _cachedCommands.clear(); | |
| 585 } | |
|
kustermann
2014/04/15 12:07:00
Maybe add a boolean '_sealed' and throw if _sealed
Bill Hesse
2014/04/15 12:37:30
Done.
| |
| 586 | |
| 583 ContentShellCommand getContentShellCommand(String executable, | 587 ContentShellCommand getContentShellCommand(String executable, |
| 584 String htmlFile, | 588 String htmlFile, |
| 585 List<String> options, | 589 List<String> options, |
| 586 List<String> dartFlags, | 590 List<String> dartFlags, |
| 587 Map<String, String> environment) { | 591 Map<String, String> environment) { |
| 588 ContentShellCommand command = new ContentShellCommand._( | 592 ContentShellCommand command = new ContentShellCommand._( |
| 589 executable, htmlFile, options, dartFlags, environment); | 593 executable, htmlFile, options, dartFlags, environment); |
| 590 return _getUniqueCommand(command); | 594 return _getUniqueCommand(command); |
| 591 } | 595 } |
| 592 | 596 |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 817 String _testingUrl; | 821 String _testingUrl; |
| 818 | 822 |
| 819 String get testingUrl => _testingUrl; | 823 String get testingUrl => _testingUrl; |
| 820 } | 824 } |
| 821 | 825 |
| 822 class UnittestSuiteMessagesMixin { | 826 class UnittestSuiteMessagesMixin { |
| 823 bool _isAsyncTest(String testOutput) { | 827 bool _isAsyncTest(String testOutput) { |
| 824 return testOutput.contains("unittest-suite-wait-for-done"); | 828 return testOutput.contains("unittest-suite-wait-for-done"); |
| 825 } | 829 } |
| 826 | 830 |
| 827 bool _isAsyncTestSuccessfull(String testOutput) { | 831 bool _isAsyncTestSuccessful(String testOutput) { |
| 828 return testOutput.contains("unittest-suite-success"); | 832 return testOutput.contains("unittest-suite-success"); |
| 829 } | 833 } |
| 830 | 834 |
| 831 Expectation _negateOutcomeIfIncompleteAsyncTest(Expectation outcome, | 835 Expectation _negateOutcomeIfIncompleteAsyncTest(Expectation outcome, |
| 832 String testOutput) { | 836 String testOutput) { |
| 833 // If this is an asynchronous test and the asynchronous operation didn't | 837 // If this is an asynchronous test and the asynchronous operation didn't |
| 834 // complete successfully, it's outcome is Expectation.FAIL. | 838 // complete successfully, it's outcome is Expectation.FAIL. |
| 835 // TODO: maybe we should introduce a AsyncIncomplete marker or so | 839 // TODO: maybe we should introduce a AsyncIncomplete marker or so |
| 836 if (outcome == Expectation.PASS) { | 840 if (outcome == Expectation.PASS) { |
| 837 if (_isAsyncTest(testOutput) && | 841 if (_isAsyncTest(testOutput) && |
| 838 !_isAsyncTestSuccessfull(testOutput)) { | 842 !_isAsyncTestSuccessful(testOutput)) { |
| 839 return Expectation.FAIL; | 843 return Expectation.FAIL; |
| 840 } | 844 } |
| 841 } | 845 } |
| 842 return outcome; | 846 return outcome; |
| 843 } | 847 } |
| 844 } | 848 } |
| 845 | 849 |
| 846 /** | 850 /** |
| 847 * CommandOutput records the output of a completed command: the process's exit | 851 * CommandOutput records the output of a completed command: the process's exit |
| 848 * code, the standard output and standard error, whether the process timed out, | 852 * code, the standard output and standard error, whether the process timed out, |
| (...skipping 1422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2271 _graph.changeState(node, newState); | 2275 _graph.changeState(node, newState); |
| 2272 } | 2276 } |
| 2273 } | 2277 } |
| 2274 } | 2278 } |
| 2275 } | 2279 } |
| 2276 | 2280 |
| 2277 /* | 2281 /* |
| 2278 * [CommandQueue] will listen for nodes entering the NodeState.ENQUEUING state, | 2282 * [CommandQueue] will listen for nodes entering the NodeState.ENQUEUING state, |
| 2279 * queue them up and run them. While nodes are processed they will be in the | 2283 * queue them up and run them. While nodes are processed they will be in the |
| 2280 * NodeState.PROCESSING state. After running a command, the node will change | 2284 * NodeState.PROCESSING state. After running a command, the node will change |
| 2281 * to a state of NodeState.Successfull or NodeState.Failed. | 2285 * to a state of NodeState.Successful or NodeState.Failed. |
| 2282 * | 2286 * |
| 2283 * It provides a synchronous stream [completedCommands] which provides the | 2287 * It provides a synchronous stream [completedCommands] which provides the |
| 2284 * [CommandOutputs] for the finished commands. | 2288 * [CommandOutputs] for the finished commands. |
| 2285 * | 2289 * |
| 2286 * It provides a [done] future, which will complete once there are no more | 2290 * It provides a [done] future, which will complete once there are no more |
| 2287 * nodes left in the states Initialized/Waiting/Enqueing/Processing | 2291 * nodes left in the states Initialized/Waiting/Enqueing/Processing |
| 2288 * and the [executor] has cleaned up it's resources. | 2292 * and the [executor] has cleaned up it's resources. |
| 2289 */ | 2293 */ |
| 2290 class CommandQueue { | 2294 class CommandQueue { |
| 2291 final dgraph.Graph graph; | 2295 final dgraph.Graph graph; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 2315 var command = event.node.userData; | 2319 var command = event.node.userData; |
| 2316 if (event.node.dependencies.length > 0) { | 2320 if (event.node.dependencies.length > 0) { |
| 2317 _runQueue.addFirst(command); | 2321 _runQueue.addFirst(command); |
| 2318 } else { | 2322 } else { |
| 2319 _runQueue.add(command); | 2323 _runQueue.add(command); |
| 2320 } | 2324 } |
| 2321 Timer.run(() => _tryRunNextCommand()); | 2325 Timer.run(() => _tryRunNextCommand()); |
| 2322 } | 2326 } |
| 2323 }); | 2327 }); |
| 2324 // We're finished if the graph is sealed and all nodes are in a finished | 2328 // We're finished if the graph is sealed and all nodes are in a finished |
| 2325 // state (Successfull, Failed or UnableToRun). | 2329 // state (Successful, Failed or UnableToRun). |
| 2326 // So we're calling '_checkDone()' to check whether that condition is met | 2330 // So we're calling '_checkDone()' to check whether that condition is met |
| 2327 // and we can cleanup. | 2331 // and we can cleanup. |
| 2328 graph.events.listen((dgraph.GraphEvent event) { | 2332 graph.events.listen((dgraph.GraphEvent event) { |
| 2329 if (event is dgraph.GraphSealedEvent) { | 2333 if (event is dgraph.GraphSealedEvent) { |
| 2330 _checkDone(); | 2334 _checkDone(); |
| 2331 } else if (event is dgraph.StateChangedEvent) { | 2335 } else if (event is dgraph.StateChangedEvent) { |
| 2332 if (event.to == dgraph.NodeState.UnableToRun) { | 2336 if (event.to == dgraph.NodeState.UnableToRun) { |
| 2333 _checkDone(); | 2337 _checkDone(); |
| 2334 } | 2338 } |
| 2335 } | 2339 } |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2644 // We currently rerun dartium tests, see issue 14074 | 2648 // We currently rerun dartium tests, see issue 14074 |
| 2645 if (command is BrowserTestCommand && command.displayName == 'dartium') { | 2649 if (command is BrowserTestCommand && command.displayName == 'dartium') { |
| 2646 return true; | 2650 return true; |
| 2647 } | 2651 } |
| 2648 } | 2652 } |
| 2649 return false; | 2653 return false; |
| 2650 } | 2654 } |
| 2651 | 2655 |
| 2652 /* | 2656 /* |
| 2653 * [TestCaseCompleter] will listen for | 2657 * [TestCaseCompleter] will listen for |
| 2654 * NodeState.Processing -> NodeState.{Successfull,Failed} state changes and | 2658 * NodeState.Processing -> NodeState.{Successful,Failed} state changes and |
| 2655 * will complete a TestCase if it is finished. | 2659 * will complete a TestCase if it is finished. |
| 2656 * | 2660 * |
| 2657 * It provides a stream [finishedTestCases], which will stream all TestCases | 2661 * It provides a stream [finishedTestCases], which will stream all TestCases |
| 2658 * once they're finished. After all TestCases are done, the stream will be | 2662 * once they're finished. After all TestCases are done, the stream will be |
| 2659 * closed. | 2663 * closed. |
| 2660 */ | 2664 */ |
| 2661 class TestCaseCompleter { | 2665 class TestCaseCompleter { |
| 2662 static final COMPLETED_STATES = [dgraph.NodeState.Failed, | 2666 static final COMPLETED_STATES = [dgraph.NodeState.Failed, |
| 2663 dgraph.NodeState.Successful]; | 2667 dgraph.NodeState.Successful]; |
| 2664 final dgraph.Graph graph; | 2668 final dgraph.Graph graph; |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2677 // (i.e. before state changes in the graph) | 2681 // (i.e. before state changes in the graph) |
| 2678 commandQueue.completedCommands.listen((CommandOutput output) { | 2682 commandQueue.completedCommands.listen((CommandOutput output) { |
| 2679 _outputs[output.command] = output; | 2683 _outputs[output.command] = output; |
| 2680 }, onDone: () { | 2684 }, onDone: () { |
| 2681 _completeTestCasesIfPossible(new List.from(enqueuer.remainingTestCases)); | 2685 _completeTestCasesIfPossible(new List.from(enqueuer.remainingTestCases)); |
| 2682 finishedRemainingTestCases = true; | 2686 finishedRemainingTestCases = true; |
| 2683 assert(enqueuer.remainingTestCases.isEmpty); | 2687 assert(enqueuer.remainingTestCases.isEmpty); |
| 2684 _checkDone(); | 2688 _checkDone(); |
| 2685 }); | 2689 }); |
| 2686 | 2690 |
| 2687 // Listen for NodeState.Processing -> NodeState.{Successfull,Failed} | 2691 // Listen for NodeState.Processing -> NodeState.{Successful,Failed} |
| 2688 // changes. | 2692 // changes. |
| 2689 eventCondition((event) => event is dgraph.StateChangedEvent) | 2693 eventCondition((event) => event is dgraph.StateChangedEvent) |
| 2690 .listen((dgraph.StateChangedEvent event) { | 2694 .listen((dgraph.StateChangedEvent event) { |
| 2691 if (event.from == dgraph.NodeState.Processing && | 2695 if (event.from == dgraph.NodeState.Processing && |
| 2692 !finishedRemainingTestCases ) { | 2696 !finishedRemainingTestCases ) { |
| 2693 var command = event.node.userData; | 2697 var command = event.node.userData; |
| 2694 | 2698 |
| 2695 assert(COMPLETED_STATES.contains(event.to)); | 2699 assert(COMPLETED_STATES.contains(event.to)); |
| 2696 assert(_outputs[command] != null); | 2700 assert(_outputs[command] != null); |
| 2697 | 2701 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2748 completeTestCase(testCase); | 2752 completeTestCase(testCase); |
| 2749 } | 2753 } |
| 2750 } | 2754 } |
| 2751 } | 2755 } |
| 2752 } | 2756 } |
| 2753 | 2757 |
| 2754 | 2758 |
| 2755 class ProcessQueue { | 2759 class ProcessQueue { |
| 2756 Map _globalConfiguration; | 2760 Map _globalConfiguration; |
| 2757 | 2761 |
| 2758 bool _allTestsWereEnqueued = false; | |
| 2759 | |
| 2760 bool _listTests; | 2762 bool _listTests; |
| 2761 Function _allDone; | 2763 Function _allDone; |
| 2762 final dgraph.Graph _graph = new dgraph.Graph(); | 2764 final dgraph.Graph _graph = new dgraph.Graph(); |
| 2763 List<EventListener> _eventListener; | 2765 List<EventListener> _eventListener; |
| 2764 | 2766 |
| 2765 ProcessQueue(this._globalConfiguration, | 2767 ProcessQueue(this._globalConfiguration, |
| 2766 maxProcesses, | 2768 maxProcesses, |
| 2767 maxBrowserProcesses, | 2769 maxBrowserProcesses, |
| 2768 DateTime startTime, | 2770 DateTime startTime, |
| 2769 testSuites, | 2771 testSuites, |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2909 if (_globalConfiguration['list']) { | 2911 if (_globalConfiguration['list']) { |
| 2910 setupForListing(testCaseEnqueuer); | 2912 setupForListing(testCaseEnqueuer); |
| 2911 } else { | 2913 } else { |
| 2912 setupForRunning(testCaseEnqueuer); | 2914 setupForRunning(testCaseEnqueuer); |
| 2913 } | 2915 } |
| 2914 | 2916 |
| 2915 // Start enqueing all TestCases | 2917 // Start enqueing all TestCases |
| 2916 testCaseEnqueuer.enqueueTestSuites(testSuites); | 2918 testCaseEnqueuer.enqueueTestSuites(testSuites); |
| 2917 } | 2919 } |
| 2918 | 2920 |
| 2921 void freeEnqueueingStructures() { | |
| 2922 CommandBuilder.instance.clearCommandCache(); | |
| 2923 } | |
| 2924 | |
| 2919 void eventFinishedTestCase(TestCase testCase) { | 2925 void eventFinishedTestCase(TestCase testCase) { |
| 2920 for (var listener in _eventListener) { | 2926 for (var listener in _eventListener) { |
| 2921 listener.done(testCase); | 2927 listener.done(testCase); |
| 2922 } | 2928 } |
| 2923 } | 2929 } |
| 2924 | 2930 |
| 2925 void eventTestAdded(TestCase testCase) { | 2931 void eventTestAdded(TestCase testCase) { |
| 2926 for (var listener in _eventListener) { | 2932 for (var listener in _eventListener) { |
| 2927 listener.testAdded(); | 2933 listener.testAdded(); |
| 2928 } | 2934 } |
| 2929 } | 2935 } |
| 2930 | 2936 |
| 2931 void eventAllTestsKnown() { | 2937 void eventAllTestsKnown() { |
| 2938 freeEnqueueingStructures(); | |
| 2932 for (var listener in _eventListener) { | 2939 for (var listener in _eventListener) { |
| 2933 listener.allTestsKnown(); | 2940 listener.allTestsKnown(); |
| 2934 } | 2941 } |
| 2935 } | 2942 } |
| 2936 | 2943 |
| 2937 void eventAllTestsDone() { | 2944 void eventAllTestsDone() { |
| 2938 for (var listener in _eventListener) { | 2945 for (var listener in _eventListener) { |
| 2939 listener.allDone(); | 2946 listener.allDone(); |
| 2940 } | 2947 } |
| 2941 _allDone(); | 2948 _allDone(); |
| 2942 } | 2949 } |
| 2943 } | 2950 } |
| OLD | NEW |