| 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 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 other is MakeSymlinkCommand && | 569 other is MakeSymlinkCommand && |
| 570 super._equal(other) && | 570 super._equal(other) && |
| 571 _link == other._link && | 571 _link == other._link && |
| 572 _target == other._target; | 572 _target == other._target; |
| 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 bool _cleared = false; |
| 579 final _cachedCommands = new Map<Command, Command>(); | 580 final _cachedCommands = new Map<Command, Command>(); |
| 580 | 581 |
| 581 CommandBuilder._(); | 582 CommandBuilder._(); |
| 582 | 583 |
| 584 void clearCommandCache() { |
| 585 _cachedCommands.clear(); |
| 586 _cleared = true; |
| 587 } |
| 588 |
| 583 ContentShellCommand getContentShellCommand(String executable, | 589 ContentShellCommand getContentShellCommand(String executable, |
| 584 String htmlFile, | 590 String htmlFile, |
| 585 List<String> options, | 591 List<String> options, |
| 586 List<String> dartFlags, | 592 List<String> dartFlags, |
| 587 Map<String, String> environment) { | 593 Map<String, String> environment) { |
| 588 ContentShellCommand command = new ContentShellCommand._( | 594 ContentShellCommand command = new ContentShellCommand._( |
| 589 executable, htmlFile, options, dartFlags, environment); | 595 executable, htmlFile, options, dartFlags, environment); |
| 590 return _getUniqueCommand(command); | 596 return _getUniqueCommand(command); |
| 591 } | 597 } |
| 592 | 598 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 if (destinationFile == null) destinationFile = pubspecYamlFile; | 673 if (destinationFile == null) destinationFile = pubspecYamlFile; |
| 668 return _getUniqueCommand(new ModifyPubspecYamlCommand._( | 674 return _getUniqueCommand(new ModifyPubspecYamlCommand._( |
| 669 pubspecYamlFile, destinationFile, depsOverrides)); | 675 pubspecYamlFile, destinationFile, depsOverrides)); |
| 670 } | 676 } |
| 671 | 677 |
| 672 Command _getUniqueCommand(Command command) { | 678 Command _getUniqueCommand(Command command) { |
| 673 // All Command classes implement hashCode and operator==. | 679 // All Command classes implement hashCode and operator==. |
| 674 // We check if this command has already been built. | 680 // We check if this command has already been built. |
| 675 // If so, we return the cached one. Otherwise we | 681 // If so, we return the cached one. Otherwise we |
| 676 // store the one given as [command] argument. | 682 // store the one given as [command] argument. |
| 683 if (_cleared) { |
| 684 throw new Exception( |
| 685 "CommandBuilder.get[type]Command called after cache cleared"); |
| 686 } |
| 677 var cachedCommand = _cachedCommands[command]; | 687 var cachedCommand = _cachedCommands[command]; |
| 678 if (cachedCommand != null) { | 688 if (cachedCommand != null) { |
| 679 return cachedCommand; | 689 return cachedCommand; |
| 680 } | 690 } |
| 681 _cachedCommands[command] = command; | 691 _cachedCommands[command] = command; |
| 682 return command; | 692 return command; |
| 683 } | 693 } |
| 684 } | 694 } |
| 685 | 695 |
| 686 /** | 696 /** |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 String _testingUrl; | 827 String _testingUrl; |
| 818 | 828 |
| 819 String get testingUrl => _testingUrl; | 829 String get testingUrl => _testingUrl; |
| 820 } | 830 } |
| 821 | 831 |
| 822 class UnittestSuiteMessagesMixin { | 832 class UnittestSuiteMessagesMixin { |
| 823 bool _isAsyncTest(String testOutput) { | 833 bool _isAsyncTest(String testOutput) { |
| 824 return testOutput.contains("unittest-suite-wait-for-done"); | 834 return testOutput.contains("unittest-suite-wait-for-done"); |
| 825 } | 835 } |
| 826 | 836 |
| 827 bool _isAsyncTestSuccessfull(String testOutput) { | 837 bool _isAsyncTestSuccessful(String testOutput) { |
| 828 return testOutput.contains("unittest-suite-success"); | 838 return testOutput.contains("unittest-suite-success"); |
| 829 } | 839 } |
| 830 | 840 |
| 831 Expectation _negateOutcomeIfIncompleteAsyncTest(Expectation outcome, | 841 Expectation _negateOutcomeIfIncompleteAsyncTest(Expectation outcome, |
| 832 String testOutput) { | 842 String testOutput) { |
| 833 // If this is an asynchronous test and the asynchronous operation didn't | 843 // If this is an asynchronous test and the asynchronous operation didn't |
| 834 // complete successfully, it's outcome is Expectation.FAIL. | 844 // complete successfully, it's outcome is Expectation.FAIL. |
| 835 // TODO: maybe we should introduce a AsyncIncomplete marker or so | 845 // TODO: maybe we should introduce a AsyncIncomplete marker or so |
| 836 if (outcome == Expectation.PASS) { | 846 if (outcome == Expectation.PASS) { |
| 837 if (_isAsyncTest(testOutput) && | 847 if (_isAsyncTest(testOutput) && |
| 838 !_isAsyncTestSuccessfull(testOutput)) { | 848 !_isAsyncTestSuccessful(testOutput)) { |
| 839 return Expectation.FAIL; | 849 return Expectation.FAIL; |
| 840 } | 850 } |
| 841 } | 851 } |
| 842 return outcome; | 852 return outcome; |
| 843 } | 853 } |
| 844 } | 854 } |
| 845 | 855 |
| 846 /** | 856 /** |
| 847 * CommandOutput records the output of a completed command: the process's exit | 857 * 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, | 858 * 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); | 2281 _graph.changeState(node, newState); |
| 2272 } | 2282 } |
| 2273 } | 2283 } |
| 2274 } | 2284 } |
| 2275 } | 2285 } |
| 2276 | 2286 |
| 2277 /* | 2287 /* |
| 2278 * [CommandQueue] will listen for nodes entering the NodeState.ENQUEUING state, | 2288 * [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 | 2289 * 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 | 2290 * NodeState.PROCESSING state. After running a command, the node will change |
| 2281 * to a state of NodeState.Successfull or NodeState.Failed. | 2291 * to a state of NodeState.Successful or NodeState.Failed. |
| 2282 * | 2292 * |
| 2283 * It provides a synchronous stream [completedCommands] which provides the | 2293 * It provides a synchronous stream [completedCommands] which provides the |
| 2284 * [CommandOutputs] for the finished commands. | 2294 * [CommandOutputs] for the finished commands. |
| 2285 * | 2295 * |
| 2286 * It provides a [done] future, which will complete once there are no more | 2296 * It provides a [done] future, which will complete once there are no more |
| 2287 * nodes left in the states Initialized/Waiting/Enqueing/Processing | 2297 * nodes left in the states Initialized/Waiting/Enqueing/Processing |
| 2288 * and the [executor] has cleaned up it's resources. | 2298 * and the [executor] has cleaned up it's resources. |
| 2289 */ | 2299 */ |
| 2290 class CommandQueue { | 2300 class CommandQueue { |
| 2291 final dgraph.Graph graph; | 2301 final dgraph.Graph graph; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2315 var command = event.node.userData; | 2325 var command = event.node.userData; |
| 2316 if (event.node.dependencies.length > 0) { | 2326 if (event.node.dependencies.length > 0) { |
| 2317 _runQueue.addFirst(command); | 2327 _runQueue.addFirst(command); |
| 2318 } else { | 2328 } else { |
| 2319 _runQueue.add(command); | 2329 _runQueue.add(command); |
| 2320 } | 2330 } |
| 2321 Timer.run(() => _tryRunNextCommand()); | 2331 Timer.run(() => _tryRunNextCommand()); |
| 2322 } | 2332 } |
| 2323 }); | 2333 }); |
| 2324 // We're finished if the graph is sealed and all nodes are in a finished | 2334 // We're finished if the graph is sealed and all nodes are in a finished |
| 2325 // state (Successfull, Failed or UnableToRun). | 2335 // state (Successful, Failed or UnableToRun). |
| 2326 // So we're calling '_checkDone()' to check whether that condition is met | 2336 // So we're calling '_checkDone()' to check whether that condition is met |
| 2327 // and we can cleanup. | 2337 // and we can cleanup. |
| 2328 graph.events.listen((dgraph.GraphEvent event) { | 2338 graph.events.listen((dgraph.GraphEvent event) { |
| 2329 if (event is dgraph.GraphSealedEvent) { | 2339 if (event is dgraph.GraphSealedEvent) { |
| 2330 _checkDone(); | 2340 _checkDone(); |
| 2331 } else if (event is dgraph.StateChangedEvent) { | 2341 } else if (event is dgraph.StateChangedEvent) { |
| 2332 if (event.to == dgraph.NodeState.UnableToRun) { | 2342 if (event.to == dgraph.NodeState.UnableToRun) { |
| 2333 _checkDone(); | 2343 _checkDone(); |
| 2334 } | 2344 } |
| 2335 } | 2345 } |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2644 // We currently rerun dartium tests, see issue 14074 | 2654 // We currently rerun dartium tests, see issue 14074 |
| 2645 if (command is BrowserTestCommand && command.displayName == 'dartium') { | 2655 if (command is BrowserTestCommand && command.displayName == 'dartium') { |
| 2646 return true; | 2656 return true; |
| 2647 } | 2657 } |
| 2648 } | 2658 } |
| 2649 return false; | 2659 return false; |
| 2650 } | 2660 } |
| 2651 | 2661 |
| 2652 /* | 2662 /* |
| 2653 * [TestCaseCompleter] will listen for | 2663 * [TestCaseCompleter] will listen for |
| 2654 * NodeState.Processing -> NodeState.{Successfull,Failed} state changes and | 2664 * NodeState.Processing -> NodeState.{Successful,Failed} state changes and |
| 2655 * will complete a TestCase if it is finished. | 2665 * will complete a TestCase if it is finished. |
| 2656 * | 2666 * |
| 2657 * It provides a stream [finishedTestCases], which will stream all TestCases | 2667 * It provides a stream [finishedTestCases], which will stream all TestCases |
| 2658 * once they're finished. After all TestCases are done, the stream will be | 2668 * once they're finished. After all TestCases are done, the stream will be |
| 2659 * closed. | 2669 * closed. |
| 2660 */ | 2670 */ |
| 2661 class TestCaseCompleter { | 2671 class TestCaseCompleter { |
| 2662 static final COMPLETED_STATES = [dgraph.NodeState.Failed, | 2672 static final COMPLETED_STATES = [dgraph.NodeState.Failed, |
| 2663 dgraph.NodeState.Successful]; | 2673 dgraph.NodeState.Successful]; |
| 2664 final dgraph.Graph graph; | 2674 final dgraph.Graph graph; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2677 // (i.e. before state changes in the graph) | 2687 // (i.e. before state changes in the graph) |
| 2678 commandQueue.completedCommands.listen((CommandOutput output) { | 2688 commandQueue.completedCommands.listen((CommandOutput output) { |
| 2679 _outputs[output.command] = output; | 2689 _outputs[output.command] = output; |
| 2680 }, onDone: () { | 2690 }, onDone: () { |
| 2681 _completeTestCasesIfPossible(new List.from(enqueuer.remainingTestCases)); | 2691 _completeTestCasesIfPossible(new List.from(enqueuer.remainingTestCases)); |
| 2682 finishedRemainingTestCases = true; | 2692 finishedRemainingTestCases = true; |
| 2683 assert(enqueuer.remainingTestCases.isEmpty); | 2693 assert(enqueuer.remainingTestCases.isEmpty); |
| 2684 _checkDone(); | 2694 _checkDone(); |
| 2685 }); | 2695 }); |
| 2686 | 2696 |
| 2687 // Listen for NodeState.Processing -> NodeState.{Successfull,Failed} | 2697 // Listen for NodeState.Processing -> NodeState.{Successful,Failed} |
| 2688 // changes. | 2698 // changes. |
| 2689 eventCondition((event) => event is dgraph.StateChangedEvent) | 2699 eventCondition((event) => event is dgraph.StateChangedEvent) |
| 2690 .listen((dgraph.StateChangedEvent event) { | 2700 .listen((dgraph.StateChangedEvent event) { |
| 2691 if (event.from == dgraph.NodeState.Processing && | 2701 if (event.from == dgraph.NodeState.Processing && |
| 2692 !finishedRemainingTestCases ) { | 2702 !finishedRemainingTestCases ) { |
| 2693 var command = event.node.userData; | 2703 var command = event.node.userData; |
| 2694 | 2704 |
| 2695 assert(COMPLETED_STATES.contains(event.to)); | 2705 assert(COMPLETED_STATES.contains(event.to)); |
| 2696 assert(_outputs[command] != null); | 2706 assert(_outputs[command] != null); |
| 2697 | 2707 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2748 completeTestCase(testCase); | 2758 completeTestCase(testCase); |
| 2749 } | 2759 } |
| 2750 } | 2760 } |
| 2751 } | 2761 } |
| 2752 } | 2762 } |
| 2753 | 2763 |
| 2754 | 2764 |
| 2755 class ProcessQueue { | 2765 class ProcessQueue { |
| 2756 Map _globalConfiguration; | 2766 Map _globalConfiguration; |
| 2757 | 2767 |
| 2758 bool _allTestsWereEnqueued = false; | |
| 2759 | |
| 2760 bool _listTests; | 2768 bool _listTests; |
| 2761 Function _allDone; | 2769 Function _allDone; |
| 2762 final dgraph.Graph _graph = new dgraph.Graph(); | 2770 final dgraph.Graph _graph = new dgraph.Graph(); |
| 2763 List<EventListener> _eventListener; | 2771 List<EventListener> _eventListener; |
| 2764 | 2772 |
| 2765 ProcessQueue(this._globalConfiguration, | 2773 ProcessQueue(this._globalConfiguration, |
| 2766 maxProcesses, | 2774 maxProcesses, |
| 2767 maxBrowserProcesses, | 2775 maxBrowserProcesses, |
| 2768 DateTime startTime, | 2776 DateTime startTime, |
| 2769 testSuites, | 2777 testSuites, |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2909 if (_globalConfiguration['list']) { | 2917 if (_globalConfiguration['list']) { |
| 2910 setupForListing(testCaseEnqueuer); | 2918 setupForListing(testCaseEnqueuer); |
| 2911 } else { | 2919 } else { |
| 2912 setupForRunning(testCaseEnqueuer); | 2920 setupForRunning(testCaseEnqueuer); |
| 2913 } | 2921 } |
| 2914 | 2922 |
| 2915 // Start enqueing all TestCases | 2923 // Start enqueing all TestCases |
| 2916 testCaseEnqueuer.enqueueTestSuites(testSuites); | 2924 testCaseEnqueuer.enqueueTestSuites(testSuites); |
| 2917 } | 2925 } |
| 2918 | 2926 |
| 2927 void freeEnqueueingStructures() { |
| 2928 CommandBuilder.instance.clearCommandCache(); |
| 2929 } |
| 2930 |
| 2919 void eventFinishedTestCase(TestCase testCase) { | 2931 void eventFinishedTestCase(TestCase testCase) { |
| 2920 for (var listener in _eventListener) { | 2932 for (var listener in _eventListener) { |
| 2921 listener.done(testCase); | 2933 listener.done(testCase); |
| 2922 } | 2934 } |
| 2923 } | 2935 } |
| 2924 | 2936 |
| 2925 void eventTestAdded(TestCase testCase) { | 2937 void eventTestAdded(TestCase testCase) { |
| 2926 for (var listener in _eventListener) { | 2938 for (var listener in _eventListener) { |
| 2927 listener.testAdded(); | 2939 listener.testAdded(); |
| 2928 } | 2940 } |
| 2929 } | 2941 } |
| 2930 | 2942 |
| 2931 void eventAllTestsKnown() { | 2943 void eventAllTestsKnown() { |
| 2944 freeEnqueueingStructures(); |
| 2932 for (var listener in _eventListener) { | 2945 for (var listener in _eventListener) { |
| 2933 listener.allTestsKnown(); | 2946 listener.allTestsKnown(); |
| 2934 } | 2947 } |
| 2935 } | 2948 } |
| 2936 | 2949 |
| 2937 void eventAllTestsDone() { | 2950 void eventAllTestsDone() { |
| 2938 for (var listener in _eventListener) { | 2951 for (var listener in _eventListener) { |
| 2939 listener.allDone(); | 2952 listener.allDone(); |
| 2940 } | 2953 } |
| 2941 _allDone(); | 2954 _allDone(); |
| 2942 } | 2955 } |
| 2943 } | 2956 } |
| OLD | NEW |