| 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 | 86 |
| 87 bool _equal(Command other) { | 87 bool _equal(Command other) { |
| 88 return hashCode == other.hashCode && | 88 return hashCode == other.hashCode && |
| 89 commandLine == other.commandLine && | 89 commandLine == other.commandLine && |
| 90 displayName == other.displayName; | 90 displayName == other.displayName; |
| 91 } | 91 } |
| 92 | 92 |
| 93 String toString() => reproductionCommand; | 93 String toString() => reproductionCommand; |
| 94 | 94 |
| 95 Future<bool> get outputIsUpToDate => new Future.value(false); | 95 Future<bool> get outputIsUpToDate => new Future.value(false); |
| 96 |
| 97 Future<String> get cachedOutput => new Future.value(null); |
| 98 Future writeCachedOutput(CommandOutput output) => new Future.value(null); |
| 96 } | 99 } |
| 97 | 100 |
| 98 class ProcessCommand extends Command { | 101 class ProcessCommand extends Command { |
| 99 /** Path to the executable of this command. */ | 102 /** Path to the executable of this command. */ |
| 100 String executable; | 103 String executable; |
| 101 | 104 |
| 102 /** Command line arguments to the executable. */ | 105 /** Command line arguments to the executable. */ |
| 103 List<String> arguments; | 106 List<String> arguments; |
| 104 | 107 |
| 105 /** Environment for the command */ | 108 /** Environment for the command */ |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } | 168 } |
| 166 | 169 |
| 167 Future<bool> get outputIsUpToDate => new Future.value(false); | 170 Future<bool> get outputIsUpToDate => new Future.value(false); |
| 168 } | 171 } |
| 169 | 172 |
| 170 class CompilationCommand extends ProcessCommand { | 173 class CompilationCommand extends ProcessCommand { |
| 171 String _outputFile; | 174 String _outputFile; |
| 172 bool _neverSkipCompilation; | 175 bool _neverSkipCompilation; |
| 173 List<Uri> _bootstrapDependencies; | 176 List<Uri> _bootstrapDependencies; |
| 174 | 177 |
| 178 Future writeCachedOutput(CommandOutput output) { |
| 179 var file = new io.File(TestUtils.cachedOutputFile(_outputFile)); |
| 180 return file.writeAsString(output.json) |
| 181 .catchError((error) { |
| 182 DebugLogger.warning("Could not write cached output: $error"); |
| 183 return null; |
| 184 }); |
| 185 } |
| 186 |
| 187 Future<CommandOutput> get cachedOutput { |
| 188 var file = new io.File(TestUtils.cachedOutputFile(_outputFile)); |
| 189 return file.exists().then((exists) { |
| 190 if (exists) return file.readAsString().then((content) { |
| 191 return new CompilationCommandOutputImpl.fromJson(this, content); |
| 192 });; |
| 193 }); |
| 194 } |
| 195 |
| 175 CompilationCommand._(String displayName, | 196 CompilationCommand._(String displayName, |
| 176 this._outputFile, | 197 this._outputFile, |
| 177 this._neverSkipCompilation, | 198 this._neverSkipCompilation, |
| 178 List<Uri> bootstrapDependencies, | 199 List<Uri> bootstrapDependencies, |
| 179 String executable, | 200 String executable, |
| 180 List<String> arguments, | 201 List<String> arguments, |
| 181 Map<String, String> environmentOverrides) | 202 Map<String, String> environmentOverrides) |
| 182 : super._(displayName, executable, arguments, environmentOverrides) { | 203 : super._(displayName, executable, arguments, environmentOverrides) { |
| 183 // We sort here, so we can do a fast hashCode/operator== | 204 // We sort here, so we can do a fast hashCode/operator== |
| 184 _bootstrapDependencies = new List.from(bootstrapDependencies); | 205 _bootstrapDependencies = new List.from(bootstrapDependencies); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 198 for (var line in lines) { | 219 for (var line in lines) { |
| 199 line = line.trim(); | 220 line = line.trim(); |
| 200 if (line.length > 0) { | 221 if (line.length > 0) { |
| 201 dependencies.add(Uri.parse(line)); | 222 dependencies.add(Uri.parse(line)); |
| 202 } | 223 } |
| 203 } | 224 } |
| 204 return dependencies; | 225 return dependencies; |
| 205 }); | 226 }); |
| 206 } | 227 } |
| 207 | 228 |
| 229 bool isUpToDate(lastModified, dependencies) { |
| 230 if (lastModified == null) return false; |
| 231 for (var dependency in dependencies) { |
| 232 var dependencyLastModified = |
| 233 TestUtils.lastModifiedCache.getLastModified(dependency); |
| 234 if (dependencyLastModified == null || |
| 235 dependencyLastModified.isAfter(lastModified)) { |
| 236 return false; |
| 237 } |
| 238 } |
| 239 return true; |
| 240 } |
| 241 |
| 208 return readDepsFile("$_outputFile.deps").then((dependencies) { | 242 return readDepsFile("$_outputFile.deps").then((dependencies) { |
| 209 if (dependencies != null) { | 243 if (dependencies != null) { |
| 210 dependencies.addAll(_bootstrapDependencies); | 244 dependencies.addAll(_bootstrapDependencies); |
| 211 var jsOutputLastModified = TestUtils.lastModifiedCache.getLastModified( | 245 // We check if the cached output is up to date, if so we return true |
| 212 new Uri(scheme: 'file', path: _outputFile)); | 246 var cachedOutputFile = TestUtils.cachedOutputFile(_outputFile); |
| 213 if (jsOutputLastModified != null) { | 247 var cachedOutputUri = new Uri(scheme: 'file', path: cachedOutputFile); |
| 214 for (var dependency in dependencies) { | 248 var cachedOutputLastModified = |
| 215 var dependencyLastModified = | 249 TestUtils.lastModifiedCache.getLastModified(cachedOutputUri); |
| 216 TestUtils.lastModifiedCache.getLastModified(dependency); | 250 return isUpToDate(cachedOutputLastModified, dependencies); |
| 217 if (dependencyLastModified == null || | |
| 218 dependencyLastModified.isAfter(jsOutputLastModified)) { | |
| 219 return false; | |
| 220 } | |
| 221 } | |
| 222 return true; | |
| 223 } | |
| 224 } | 251 } |
| 225 return false; | 252 return false; |
| 226 }); | 253 }); |
| 227 } | 254 } |
| 228 | 255 |
| 229 void _buildHashCode(HashCodeBuilder builder) { | 256 void _buildHashCode(HashCodeBuilder builder) { |
| 230 super._buildHashCode(builder); | 257 super._buildHashCode(builder); |
| 231 builder.add(_outputFile); | 258 builder.add(_outputFile); |
| 232 builder.add(_neverSkipCompilation); | 259 builder.add(_neverSkipCompilation); |
| 233 for (var uri in _bootstrapDependencies) builder.add(uri); | 260 for (var uri in _bootstrapDependencies) builder.add(uri); |
| (...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 912 | 939 |
| 913 int get pid; | 940 int get pid; |
| 914 | 941 |
| 915 List<int> get stdout; | 942 List<int> get stdout; |
| 916 | 943 |
| 917 List<int> get stderr; | 944 List<int> get stderr; |
| 918 | 945 |
| 919 List<String> get diagnostics; | 946 List<String> get diagnostics; |
| 920 | 947 |
| 921 bool get compilationSkipped; | 948 bool get compilationSkipped; |
| 949 |
| 950 String get json; |
| 922 } | 951 } |
| 923 | 952 |
| 924 class CommandOutputImpl extends UniqueObject implements CommandOutput { | 953 class CommandOutputImpl extends UniqueObject implements CommandOutput { |
| 925 Command command; | 954 Command command; |
| 926 int exitCode; | 955 int exitCode; |
| 927 | 956 |
| 928 bool timedOut; | 957 bool timedOut; |
| 929 List<int> stdout; | 958 List<int> stdout; |
| 930 List<int> stderr; | 959 List<int> stderr; |
| 931 Duration time; | 960 Duration time; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 | 1030 |
| 1002 Expectation _negateOutcomeIfNegativeTest(Expectation outcome, | 1031 Expectation _negateOutcomeIfNegativeTest(Expectation outcome, |
| 1003 bool isNegative) { | 1032 bool isNegative) { |
| 1004 if (!isNegative) return outcome; | 1033 if (!isNegative) return outcome; |
| 1005 | 1034 |
| 1006 if (outcome.canBeOutcomeOf(Expectation.FAIL)) { | 1035 if (outcome.canBeOutcomeOf(Expectation.FAIL)) { |
| 1007 return Expectation.PASS; | 1036 return Expectation.PASS; |
| 1008 } | 1037 } |
| 1009 return Expectation.FAIL; | 1038 return Expectation.FAIL; |
| 1010 } | 1039 } |
| 1040 |
| 1041 String get json => null; |
| 1042 |
| 1011 } | 1043 } |
| 1012 | 1044 |
| 1013 class BrowserCommandOutputImpl extends CommandOutputImpl { | 1045 class BrowserCommandOutputImpl extends CommandOutputImpl { |
| 1014 // Although tests are reported as passing, content shell sometimes exits with | 1046 // Although tests are reported as passing, content shell sometimes exits with |
| 1015 // a nonzero exitcode which makes our dartium builders extremely falky. | 1047 // a nonzero exitcode which makes our dartium builders extremely falky. |
| 1016 // See: http://dartbug.com/15139. | 1048 // See: http://dartbug.com/15139. |
| 1017 static int WHITELISTED_CONTENTSHELL_EXITCODE = -1073740022; | 1049 static int WHITELISTED_CONTENTSHELL_EXITCODE = -1073740022; |
| 1018 static bool isWindows = io.Platform.operatingSystem == 'windows'; | 1050 static bool isWindows = io.Platform.operatingSystem == 'windows'; |
| 1019 | 1051 |
| 1020 bool _failedBecauseOfMissingXDisplay; | 1052 bool _failedBecauseOfMissingXDisplay; |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1598 // We expected to run the test, but we got an compile time error. | 1630 // We expected to run the test, but we got an compile time error. |
| 1599 // If the compilation succeeded, we wouldn't be in here! | 1631 // If the compilation succeeded, we wouldn't be in here! |
| 1600 assert(exitCode != 0); | 1632 assert(exitCode != 0); |
| 1601 return Expectation.COMPILETIME_ERROR; | 1633 return Expectation.COMPILETIME_ERROR; |
| 1602 } | 1634 } |
| 1603 | 1635 |
| 1604 Expectation outcome = | 1636 Expectation outcome = |
| 1605 exitCode == 0 ? Expectation.PASS : Expectation.COMPILETIME_ERROR; | 1637 exitCode == 0 ? Expectation.PASS : Expectation.COMPILETIME_ERROR; |
| 1606 return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative); | 1638 return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative); |
| 1607 } | 1639 } |
| 1640 |
| 1641 String get json { |
| 1642 var map = { |
| 1643 'stdout': stdout, |
| 1644 'stderr': stderr, |
| 1645 'exitCode': exitCode, |
| 1646 'timedOut': timedOut, |
| 1647 }; |
| 1648 return JSON.encode(map); |
| 1649 } |
| 1650 |
| 1651 factory CompilationCommandOutputImpl.fromJson(Command command, |
| 1652 String json) { |
| 1653 var obj = JSON.decode(json); |
| 1654 for (var v in ['stdout', 'stderr', 'exitCode', 'timedOut']) { |
| 1655 assert(obj.containsKey(v)); |
| 1656 } |
| 1657 return new CompilationCommandOutputImpl(command, |
| 1658 obj['exitCode'], |
| 1659 obj['timedOut'], |
| 1660 obj['stdout'], |
| 1661 obj['stderr'], |
| 1662 const Duration(seconds: 0), |
| 1663 true); |
| 1664 |
| 1665 } |
| 1608 } | 1666 } |
| 1609 | 1667 |
| 1610 class JsCommandlineOutputImpl extends CommandOutputImpl | 1668 class JsCommandlineOutputImpl extends CommandOutputImpl |
| 1611 with UnittestSuiteMessagesMixin { | 1669 with UnittestSuiteMessagesMixin { |
| 1612 JsCommandlineOutputImpl(Command command, int exitCode, bool timedOut, | 1670 JsCommandlineOutputImpl(Command command, int exitCode, bool timedOut, |
| 1613 List<int> stdout, List<int> stderr, Duration time) | 1671 List<int> stdout, List<int> stderr, Duration time) |
| 1614 : super(command, exitCode, timedOut, stdout, stderr, time, false, 0); | 1672 : super(command, exitCode, timedOut, stdout, stderr, time, false, 0); |
| 1615 | 1673 |
| 1616 Expectation result(TestCase testCase) { | 1674 Expectation result(TestCase testCase) { |
| 1617 // Handle crashes and timeouts first | 1675 // Handle crashes and timeouts first |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1795 RunningProcess(this.command, this.timeout); | 1853 RunningProcess(this.command, this.timeout); |
| 1796 | 1854 |
| 1797 Future<CommandOutput> run() { | 1855 Future<CommandOutput> run() { |
| 1798 completer = new Completer<CommandOutput>(); | 1856 completer = new Completer<CommandOutput>(); |
| 1799 startTime = new DateTime.now(); | 1857 startTime = new DateTime.now(); |
| 1800 _runCommand(); | 1858 _runCommand(); |
| 1801 return completer.future; | 1859 return completer.future; |
| 1802 } | 1860 } |
| 1803 | 1861 |
| 1804 void _runCommand() { | 1862 void _runCommand() { |
| 1805 command.outputIsUpToDate.then((bool isUpToDate) { | 1863 command.outputIsUpToDate.then((isUpToDate) { |
| 1806 if (isUpToDate) { | 1864 if (isUpToDate) { |
| 1807 compilationSkipped = true; | 1865 compilationSkipped = true; |
| 1808 _commandComplete(0); | 1866 command.cachedOutput.then((cached) { |
| 1867 _commandComplete(cached.exitCode, cachedOutput: cached); |
| 1868 }); |
| 1809 } else { | 1869 } else { |
| 1810 var processEnvironment = _createProcessEnvironment(); | 1870 var processEnvironment = _createProcessEnvironment(); |
| 1811 Future processFuture = | 1871 Future processFuture = |
| 1812 io.Process.start(command.executable, | 1872 io.Process.start(command.executable, |
| 1813 command.arguments, | 1873 command.arguments, |
| 1814 environment: processEnvironment, | 1874 environment: processEnvironment, |
| 1815 workingDirectory: command.workingDirectory); | 1875 workingDirectory: command.workingDirectory); |
| 1816 processFuture.then((io.Process process) { | 1876 processFuture.then((io.Process process) { |
| 1817 StreamSubscription stdoutSubscription = | 1877 StreamSubscription stdoutSubscription = |
| 1818 _drainStream(process.stdout, stdout); | 1878 _drainStream(process.stdout, stdout); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1891 print("Process error:"); | 1951 print("Process error:"); |
| 1892 print(" Command: $command"); | 1952 print(" Command: $command"); |
| 1893 print(" Error: $e"); | 1953 print(" Error: $e"); |
| 1894 _commandComplete(-1); | 1954 _commandComplete(-1); |
| 1895 return true; | 1955 return true; |
| 1896 }); | 1956 }); |
| 1897 } | 1957 } |
| 1898 }); | 1958 }); |
| 1899 } | 1959 } |
| 1900 | 1960 |
| 1901 void _commandComplete(int exitCode) { | 1961 void _commandComplete(int exitCode, {cachedOutput: null}) { |
| 1902 if (timeoutTimer != null) { | 1962 if (timeoutTimer != null) { |
| 1903 timeoutTimer.cancel(); | 1963 timeoutTimer.cancel(); |
| 1904 } | 1964 } |
| 1905 var commandOutput = _createCommandOutput(command, exitCode); | 1965 if (cachedOutput != null) { |
| 1906 completer.complete(commandOutput); | 1966 completer.complete(cachedOutput); |
| 1967 } else { |
| 1968 var commandOutput = _createCommandOutput(command, exitCode); |
| 1969 command.writeCachedOutput(commandOutput); |
| 1970 completer.complete(commandOutput); |
| 1971 } |
| 1907 } | 1972 } |
| 1908 | 1973 |
| 1909 CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) { | 1974 CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) { |
| 1910 var commandOutput = createCommandOutput( | 1975 var commandOutput = createCommandOutput( |
| 1911 command, | 1976 command, |
| 1912 exitCode, | 1977 exitCode, |
| 1913 timedOut, | 1978 timedOut, |
| 1914 stdout.toList(), | 1979 stdout.toList(), |
| 1915 stderr.toList(), | 1980 stderr.toList(), |
| 1916 new DateTime.now().difference(startTime), | 1981 new DateTime.now().difference(startTime), |
| (...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2970 } | 3035 } |
| 2971 } | 3036 } |
| 2972 | 3037 |
| 2973 void eventAllTestsDone() { | 3038 void eventAllTestsDone() { |
| 2974 for (var listener in _eventListener) { | 3039 for (var listener in _eventListener) { |
| 2975 listener.allDone(); | 3040 listener.allDone(); |
| 2976 } | 3041 } |
| 2977 _allDone(); | 3042 _allDone(); |
| 2978 } | 3043 } |
| 2979 } | 3044 } |
| OLD | NEW |