Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: tools/testing/dart/test_runner.dart

Issue 256743009: Cache output of dart2js compilations that went wrong on disk. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 } 85 }
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<CachedState> get outputIsUpToDate =>
96 new Future.value(const CachedState(false, false));
kustermann 2014/04/29 21:20:44 It's not so nice that the Command class itself has
ricow1 2014/04/30 06:51:01 This is actually no different then the fact that i
97
98 Future<String> get cachedOutput => new Future.value(null);
99 Future writeCachedOutput(CommandOutput output) => new Future.value(null);
96 } 100 }
97 101
102 class CachedState {
103 const CachedState(this.upToDateCompilation,
104 this.upToDateCommandOutput);
105 final bool upToDateCompilation;
106 final bool upToDateCommandOutput;
107 }
108
109
98 class ProcessCommand extends Command { 110 class ProcessCommand extends Command {
99 /** Path to the executable of this command. */ 111 /** Path to the executable of this command. */
100 String executable; 112 String executable;
101 113
102 /** Command line arguments to the executable. */ 114 /** Command line arguments to the executable. */
103 List<String> arguments; 115 List<String> arguments;
104 116
105 /** Environment for the command */ 117 /** Environment for the command */
106 Map<String, String> environmentOverrides; 118 Map<String, String> environmentOverrides;
107 119
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 169
158 String get reproductionCommand { 170 String get reproductionCommand {
159 var command = ([executable]..addAll(arguments)) 171 var command = ([executable]..addAll(arguments))
160 .map(escapeCommandLineArgument).join(' '); 172 .map(escapeCommandLineArgument).join(' ');
161 if (workingDirectory != null) { 173 if (workingDirectory != null) {
162 command = "$command (working directory: $workingDirectory)"; 174 command = "$command (working directory: $workingDirectory)";
163 } 175 }
164 return command; 176 return command;
165 } 177 }
166 178
167 Future<bool> get outputIsUpToDate => new Future.value(false); 179 Future<CachedState> get outputIsUpToDate =>
180 new Future.value(const CachedState(false, false));
168 } 181 }
169 182
170 class CompilationCommand extends ProcessCommand { 183 class CompilationCommand extends ProcessCommand {
171 String _outputFile; 184 String _outputFile;
172 bool _neverSkipCompilation; 185 bool _neverSkipCompilation;
173 List<Uri> _bootstrapDependencies; 186 List<Uri> _bootstrapDependencies;
174 187
188 Future writeCachedOutput(CommandOutput output) {
189 var file = new io.File(TestUtils.cachedOutputFile(_outputFile));
190 return file.writeAsString(output.json);
191 }
192
193 Future<CommandOutput> get cachedOutput {
194 var file = new io.File(TestUtils.cachedOutputFile(_outputFile));
195 return file.exists().then((exists) {
196 if (exists) return file.readAsString().then((content) {
197 return new CompilationCommandOutputImpl.fromJson(this, content);
198 });;
199 });
200 }
201
175 CompilationCommand._(String displayName, 202 CompilationCommand._(String displayName,
176 this._outputFile, 203 this._outputFile,
177 this._neverSkipCompilation, 204 this._neverSkipCompilation,
178 List<Uri> bootstrapDependencies, 205 List<Uri> bootstrapDependencies,
179 String executable, 206 String executable,
180 List<String> arguments, 207 List<String> arguments,
181 Map<String, String> environmentOverrides) 208 Map<String, String> environmentOverrides)
182 : super._(displayName, executable, arguments, environmentOverrides) { 209 : super._(displayName, executable, arguments, environmentOverrides) {
183 // We sort here, so we can do a fast hashCode/operator== 210 // We sort here, so we can do a fast hashCode/operator==
184 _bootstrapDependencies = new List.from(bootstrapDependencies); 211 _bootstrapDependencies = new List.from(bootstrapDependencies);
185 _bootstrapDependencies.sort(); 212 _bootstrapDependencies.sort();
186 } 213 }
187 214
188 Future<bool> get outputIsUpToDate { 215 Future<CachedState> get outputIsUpToDate {
189 if (_neverSkipCompilation) return new Future.value(false); 216 if (_neverSkipCompilation) return new Future.value(false);
Bill Hesse 2014/04/29 17:51:55 Shouldn't these return CachedState objects?
kustermann 2014/04/29 21:20:44 BTW: I hope we did not disable '--checked' mode wh
ricow1 2014/04/30 06:51:01 We did not
ricow1 2014/04/30 06:51:01 Done.
190
191 Future<List<Uri>> readDepsFile(String path) { 217 Future<List<Uri>> readDepsFile(String path) {
192 var file = new io.File(new Path(path).toNativePath()); 218 var file = new io.File(new Path(path).toNativePath());
193 if (!file.existsSync()) { 219 if (!file.existsSync()) {
194 return new Future.value(null); 220 return new Future.value(null);
195 } 221 }
196 return file.readAsLines().then((List<String> lines) { 222 return file.readAsLines().then((List<String> lines) {
197 var dependencies = new List<Uri>(); 223 var dependencies = new List<Uri>();
198 for (var line in lines) { 224 for (var line in lines) {
199 line = line.trim(); 225 line = line.trim();
200 if (line.length > 0) { 226 if (line.length > 0) {
201 dependencies.add(Uri.parse(line)); 227 dependencies.add(Uri.parse(line));
202 } 228 }
203 } 229 }
204 return dependencies; 230 return dependencies;
205 }); 231 });
206 } 232 }
207 233
234 bool isUpToDate(lastModified, dependencies) {
235 if (lastModified == null) return false;
236 for (var dependency in dependencies) {
237 var dependencyLastModified =
238 TestUtils.lastModifiedCache.getLastModified(dependency);
239 if (dependencyLastModified == null ||
240 dependencyLastModified.isAfter(lastModified)) {
241 return false;
242 }
243 }
244 return true;
245 }
246
208 return readDepsFile("$_outputFile.deps").then((dependencies) { 247 return readDepsFile("$_outputFile.deps").then((dependencies) {
209 if (dependencies != null) { 248 if (dependencies != null) {
210 dependencies.addAll(_bootstrapDependencies); 249 dependencies.addAll(_bootstrapDependencies);
211 var jsOutputLastModified = TestUtils.lastModifiedCache.getLastModified( 250 var lastModified = TestUtils.lastModifiedCache.getLastModified(
212 new Uri(scheme: 'file', path: _outputFile)); 251 new Uri(scheme: 'file', path: _outputFile));
213 if (jsOutputLastModified != null) { 252 if (isUpToDate(lastModified, dependencies)) {
214 for (var dependency in dependencies) { 253 return const CachedState(true, false);
Bill Hesse 2014/04/29 17:51:55 Is CachedState(true, false) really meaning CachedS
ricow1 2014/04/30 06:51:01 Because it would not be true - if we have up to da
215 var dependencyLastModified = 254 } else {
216 TestUtils.lastModifiedCache.getLastModified(dependency); 255 // We did not have real output, check if we have stored the
217 if (dependencyLastModified == null || 256 // output of running the compiler on this test for a failed run.
218 dependencyLastModified.isAfter(jsOutputLastModified)) { 257 var cachedOutputFile = TestUtils.cachedOutputFile(_outputFile);
219 return false; 258 var cachedOutputUri = new Uri(scheme: 'file', path: cachedOutputFile);
220 } 259 var cachedOutputLastModified =
260 TestUtils.lastModifiedCache.getLastModified(cachedOutputUri);
261 if (isUpToDate(cachedOutputLastModified, dependencies)) {
262 return const CachedState(false, true);
221 } 263 }
222 return true;
223 } 264 }
224 } 265 }
225 return false; 266 return const CachedState(false, false);
226 }); 267 });
227 } 268 }
228 269
229 void _buildHashCode(HashCodeBuilder builder) { 270 void _buildHashCode(HashCodeBuilder builder) {
230 super._buildHashCode(builder); 271 super._buildHashCode(builder);
231 builder.add(_outputFile); 272 builder.add(_outputFile);
232 builder.add(_neverSkipCompilation); 273 builder.add(_neverSkipCompilation);
233 for (var uri in _bootstrapDependencies) builder.add(uri); 274 for (var uri in _bootstrapDependencies) builder.add(uri);
234 } 275 }
235 276
(...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 953
913 int get pid; 954 int get pid;
914 955
915 List<int> get stdout; 956 List<int> get stdout;
916 957
917 List<int> get stderr; 958 List<int> get stderr;
918 959
919 List<String> get diagnostics; 960 List<String> get diagnostics;
920 961
921 bool get compilationSkipped; 962 bool get compilationSkipped;
963
964 String get json;
922 } 965 }
923 966
924 class CommandOutputImpl extends UniqueObject implements CommandOutput { 967 class CommandOutputImpl extends UniqueObject implements CommandOutput {
925 Command command; 968 Command command;
926 int exitCode; 969 int exitCode;
927 970
928 bool timedOut; 971 bool timedOut;
929 List<int> stdout; 972 List<int> stdout;
930 List<int> stderr; 973 List<int> stderr;
931 Duration time; 974 Duration time;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1001 1044
1002 Expectation _negateOutcomeIfNegativeTest(Expectation outcome, 1045 Expectation _negateOutcomeIfNegativeTest(Expectation outcome,
1003 bool isNegative) { 1046 bool isNegative) {
1004 if (!isNegative) return outcome; 1047 if (!isNegative) return outcome;
1005 1048
1006 if (outcome.canBeOutcomeOf(Expectation.FAIL)) { 1049 if (outcome.canBeOutcomeOf(Expectation.FAIL)) {
1007 return Expectation.PASS; 1050 return Expectation.PASS;
1008 } 1051 }
1009 return Expectation.FAIL; 1052 return Expectation.FAIL;
1010 } 1053 }
1054
1055 String get json => null;
1056
1011 } 1057 }
1012 1058
1013 class BrowserCommandOutputImpl extends CommandOutputImpl { 1059 class BrowserCommandOutputImpl extends CommandOutputImpl {
1014 // Although tests are reported as passing, content shell sometimes exits with 1060 // Although tests are reported as passing, content shell sometimes exits with
1015 // a nonzero exitcode which makes our dartium builders extremely falky. 1061 // a nonzero exitcode which makes our dartium builders extremely falky.
1016 // See: http://dartbug.com/15139. 1062 // See: http://dartbug.com/15139.
1017 static int WHITELISTED_CONTENTSHELL_EXITCODE = -1073740022; 1063 static int WHITELISTED_CONTENTSHELL_EXITCODE = -1073740022;
1018 static bool isWindows = io.Platform.operatingSystem == 'windows'; 1064 static bool isWindows = io.Platform.operatingSystem == 'windows';
1019 1065
1020 bool _failedBecauseOfMissingXDisplay; 1066 bool _failedBecauseOfMissingXDisplay;
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after
1598 // We expected to run the test, but we got an compile time error. 1644 // We expected to run the test, but we got an compile time error.
1599 // If the compilation succeeded, we wouldn't be in here! 1645 // If the compilation succeeded, we wouldn't be in here!
1600 assert(exitCode != 0); 1646 assert(exitCode != 0);
1601 return Expectation.COMPILETIME_ERROR; 1647 return Expectation.COMPILETIME_ERROR;
1602 } 1648 }
1603 1649
1604 Expectation outcome = 1650 Expectation outcome =
1605 exitCode == 0 ? Expectation.PASS : Expectation.COMPILETIME_ERROR; 1651 exitCode == 0 ? Expectation.PASS : Expectation.COMPILETIME_ERROR;
1606 return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative); 1652 return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
1607 } 1653 }
1654
1655 String get json {
1656 var map = {
1657 'stdout': stdout,
1658 'stderr': stderr,
1659 'exitCode': exitCode,
1660 'timedOut': timedOut,
kustermann 2014/04/29 21:20:44 It may make sense to also add 'time' here, not sur
ricow1 2014/04/30 06:51:01 I did so at first, but removed it, since it would
1661 };
1662 return JSON.encode(map);
1663 }
1664
1665 factory CompilationCommandOutputImpl.fromJson(Command command,
1666 String json) {
1667 var obj = JSON.decode(json);
1668 for (var v in ['stdout', 'stderr', 'exitCode', 'timedOut']) {
1669 assert(obj.containsKey(v));
1670 }
1671 return new CompilationCommandOutputImpl(command,
1672 obj['exitCode'],
1673 obj['timedOut'],
1674 obj['stdout'],
1675 obj['stderr'],
1676 const Duration(seconds: 0),
1677 true);
1678
1679 }
1608 } 1680 }
1609 1681
1610 class JsCommandlineOutputImpl extends CommandOutputImpl 1682 class JsCommandlineOutputImpl extends CommandOutputImpl
1611 with UnittestSuiteMessagesMixin { 1683 with UnittestSuiteMessagesMixin {
1612 JsCommandlineOutputImpl(Command command, int exitCode, bool timedOut, 1684 JsCommandlineOutputImpl(Command command, int exitCode, bool timedOut,
1613 List<int> stdout, List<int> stderr, Duration time) 1685 List<int> stdout, List<int> stderr, Duration time)
1614 : super(command, exitCode, timedOut, stdout, stderr, time, false, 0); 1686 : super(command, exitCode, timedOut, stdout, stderr, time, false, 0);
1615 1687
1616 Expectation result(TestCase testCase) { 1688 Expectation result(TestCase testCase) {
1617 // Handle crashes and timeouts first 1689 // Handle crashes and timeouts first
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1795 RunningProcess(this.command, this.timeout); 1867 RunningProcess(this.command, this.timeout);
1796 1868
1797 Future<CommandOutput> run() { 1869 Future<CommandOutput> run() {
1798 completer = new Completer<CommandOutput>(); 1870 completer = new Completer<CommandOutput>();
1799 startTime = new DateTime.now(); 1871 startTime = new DateTime.now();
1800 _runCommand(); 1872 _runCommand();
1801 return completer.future; 1873 return completer.future;
1802 } 1874 }
1803 1875
1804 void _runCommand() { 1876 void _runCommand() {
1805 command.outputIsUpToDate.then((bool isUpToDate) { 1877 command.outputIsUpToDate.then((CachedState cachedState) {
1806 if (isUpToDate) { 1878 if (cachedState.upToDateCompilation) {
1807 compilationSkipped = true; 1879 compilationSkipped = true;
1808 _commandComplete(0); 1880 _commandComplete(0);
1881 } else if (cachedState.upToDateCommandOutput) {
1882 compilationSkipped = true;
1883 command.cachedOutput.then((cached) {
1884 _commandComplete(cached.exitCode, cachedOutput: cached);
1885 });
1809 } else { 1886 } else {
1810 var processEnvironment = _createProcessEnvironment(); 1887 var processEnvironment = _createProcessEnvironment();
1811 Future processFuture = 1888 Future processFuture =
1812 io.Process.start(command.executable, 1889 io.Process.start(command.executable,
1813 command.arguments, 1890 command.arguments,
1814 environment: processEnvironment, 1891 environment: processEnvironment,
1815 workingDirectory: command.workingDirectory); 1892 workingDirectory: command.workingDirectory);
1816 processFuture.then((io.Process process) { 1893 processFuture.then((io.Process process) {
1817 StreamSubscription stdoutSubscription = 1894 StreamSubscription stdoutSubscription =
1818 _drainStream(process.stdout, stdout); 1895 _drainStream(process.stdout, stdout);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1891 print("Process error:"); 1968 print("Process error:");
1892 print(" Command: $command"); 1969 print(" Command: $command");
1893 print(" Error: $e"); 1970 print(" Error: $e");
1894 _commandComplete(-1); 1971 _commandComplete(-1);
1895 return true; 1972 return true;
1896 }); 1973 });
1897 } 1974 }
1898 }); 1975 });
1899 } 1976 }
1900 1977
1901 void _commandComplete(int exitCode) { 1978 void _commandComplete(int exitCode, {cachedOutput: null}) {
1902 if (timeoutTimer != null) { 1979 if (timeoutTimer != null) {
1903 timeoutTimer.cancel(); 1980 timeoutTimer.cancel();
1904 } 1981 }
1905 var commandOutput = _createCommandOutput(command, exitCode); 1982 if (cachedOutput != null) {
1906 completer.complete(commandOutput); 1983 completer.complete(cachedOutput);
1984 } else {
1985 var commandOutput = _createCommandOutput(command, exitCode);
1986 if (exitCode != 0) {
1987 command.writeCachedOutput(commandOutput);
1988 }
Bill Hesse 2014/04/29 17:51:55 Should we put a try-catch around this? Or make wr
ricow1 2014/04/30 06:51:01 Changed writeCachedOutput to not ever throw
1989 completer.complete(commandOutput);
1990 }
1907 } 1991 }
1908 1992
1909 CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) { 1993 CommandOutput _createCommandOutput(ProcessCommand command, int exitCode) {
1910 var commandOutput = createCommandOutput( 1994 var commandOutput = createCommandOutput(
1911 command, 1995 command,
1912 exitCode, 1996 exitCode,
1913 timedOut, 1997 timedOut,
1914 stdout.toList(), 1998 stdout.toList(),
1915 stderr.toList(), 1999 stderr.toList(),
1916 new DateTime.now().difference(startTime), 2000 new DateTime.now().difference(startTime),
(...skipping 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after
2970 } 3054 }
2971 } 3055 }
2972 3056
2973 void eventAllTestsDone() { 3057 void eventAllTestsDone() {
2974 for (var listener in _eventListener) { 3058 for (var listener in _eventListener) {
2975 listener.allDone(); 3059 listener.allDone();
2976 } 3060 }
2977 _allDone(); 3061 _allDone();
2978 } 3062 }
2979 } 3063 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698