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