| 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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 executable = executable.replaceAll('/', '\\'); | 116 executable = executable.replaceAll('/', '\\'); |
| 117 } | 117 } |
| 118 var quotedArguments = []; | 118 var quotedArguments = []; |
| 119 quotedArguments.add(escapeCommandLineArgument(executable)); | 119 quotedArguments.add(escapeCommandLineArgument(executable)); |
| 120 quotedArguments.addAll(arguments.map(escapeCommandLineArgument)); | 120 quotedArguments.addAll(arguments.map(escapeCommandLineArgument)); |
| 121 commandLine = quotedArguments.join(' '); | 121 commandLine = quotedArguments.join(' '); |
| 122 } | 122 } |
| 123 | 123 |
| 124 String toString() => commandLine; | 124 String toString() => commandLine; |
| 125 | 125 |
| 126 Future postProcessCommand() => new Future.immediate(null); | |
| 127 | |
| 128 Future<bool> get outputIsUpToDate => new Future.immediate(false); | 126 Future<bool> get outputIsUpToDate => new Future.immediate(false); |
| 129 io.Path get expectedOutputFile => null; | 127 io.Path get expectedOutputFile => null; |
| 130 bool get isPixelTest => false; | 128 bool get isPixelTest => false; |
| 131 } | 129 } |
| 132 | 130 |
| 133 class CompilationCommand extends Command { | 131 class CompilationCommand extends Command { |
| 134 String _outputFile; | 132 String _outputFile; |
| 135 String _shadowFile; | |
| 136 bool _neverSkipCompilation; | 133 bool _neverSkipCompilation; |
| 137 List<Uri> _bootstrapDependencies; | 134 List<Uri> _bootstrapDependencies; |
| 138 | 135 |
| 139 CompilationCommand(this._outputFile, | 136 CompilationCommand(this._outputFile, |
| 140 this._shadowFile, | |
| 141 this._neverSkipCompilation, | 137 this._neverSkipCompilation, |
| 142 this._bootstrapDependencies, | 138 this._bootstrapDependencies, |
| 143 String executable, | 139 String executable, |
| 144 List<String> arguments) | 140 List<String> arguments) |
| 145 : super(executable, arguments); | 141 : super(executable, arguments); |
| 146 | 142 |
| 147 Future<bool> get outputIsUpToDate { | 143 Future<bool> get outputIsUpToDate { |
| 148 if (_neverSkipCompilation) return new Future.immediate(false); | 144 if (_neverSkipCompilation) return new Future.immediate(false); |
| 149 | 145 |
| 150 Future<List<Uri>> readDepsFile(String path) { | 146 Future<List<Uri>> readDepsFile(String path) { |
| 151 var file = new io.File(new io.Path(path).toNativePath()); | 147 var file = new io.File(new io.Path(path).toNativePath()); |
| 152 if (!file.existsSync()) { | 148 if (!file.existsSync()) { |
| 153 return new Future.immediate(null); | 149 return new Future.immediate(null); |
| 154 } | 150 } |
| 155 return file.readAsLines().then((List<String> lines) { | 151 return file.readAsLines().then((List<String> lines) { |
| 156 var dependencies = new List<Uri>(); | 152 var dependencies = new List<Uri>(); |
| 157 for (var line in lines) { | 153 for (var line in lines) { |
| 158 line = line.trim(); | 154 line = line.trim(); |
| 159 if (line.length > 0) { | 155 if (line.length > 0) { |
| 160 dependencies.add(new Uri(line)); | 156 dependencies.add(new Uri(line)); |
| 161 } | 157 } |
| 162 } | 158 } |
| 163 return dependencies; | 159 return dependencies; |
| 164 }); | 160 }); |
| 165 } | 161 } |
| 166 | 162 |
| 167 return readDepsFile("${_shadowFile}.deps").then((dependencies) { | 163 return readDepsFile("$_outputFile.deps").then((dependencies) { |
| 168 if (dependencies != null) { | 164 if (dependencies != null) { |
| 169 dependencies.addAll(_bootstrapDependencies); | 165 dependencies.addAll(_bootstrapDependencies); |
| 170 var jsOutputLastModified = TestUtils.lastModifiedCache.getLastModified( | 166 var jsOutputLastModified = TestUtils.lastModifiedCache.getLastModified( |
| 171 new Uri.fromComponents(scheme: 'file', path: _shadowFile)); | 167 new Uri.fromComponents(scheme: 'file', path: _outputFile)); |
| 172 if (jsOutputLastModified != null) { | 168 if (jsOutputLastModified != null) { |
| 173 for (var dependency in dependencies) { | 169 for (var dependency in dependencies) { |
| 174 var dependencyLastModified = | 170 var dependencyLastModified = |
| 175 TestUtils.lastModifiedCache.getLastModified(dependency); | 171 TestUtils.lastModifiedCache.getLastModified(dependency); |
| 176 if (dependencyLastModified == null || | 172 if (dependencyLastModified == null || |
| 177 dependencyLastModified.isAfter(jsOutputLastModified)) { | 173 dependencyLastModified.isAfter(jsOutputLastModified)) { |
| 178 return false; | 174 return false; |
| 179 } | 175 } |
| 180 } | 176 } |
| 181 // Shadow files are up to date, so copy them. | |
| 182 _copyFilesSync(_shadowFile, _outputFile); | |
| 183 return true; | 177 return true; |
| 184 } | 178 } |
| 185 } | 179 } |
| 186 return false; | 180 return false; |
| 187 }); | 181 }); |
| 188 } | 182 } |
| 189 | |
| 190 Future postProcessCommand() { | |
| 191 // After the actual compile, we synchronously copy the compiled output files | |
| 192 // to shadow files. | |
| 193 _copyFilesSync(_outputFile, _shadowFile); | |
| 194 return new Future.immediate(null); | |
| 195 } | |
| 196 | |
| 197 _copyFilesSync(String from, String to) { | |
| 198 for (var ending in ['', '.deps', '.map']) { | |
| 199 var fromFile = new io.File("${from}${ending}"); | |
| 200 var toFile = new io.File("${to}${ending}"); | |
| 201 if (fromFile.existsSync()) { | |
| 202 // We copy the dart2js results synchronously to make it atomic. | |
| 203 // This ensures that the shadow files are always in a consistent state | |
| 204 // (no other code in the testing scripts will see a half-written shadow | |
| 205 // file). | |
| 206 toFile.writeAsBytesSync(fromFile.readAsBytesSync()); | |
| 207 } | |
| 208 } | |
| 209 } | |
| 210 } | 183 } |
| 211 | 184 |
| 212 class ContentShellCommand extends Command { | 185 class ContentShellCommand extends Command { |
| 213 /** | 186 /** |
| 214 * If [expectedOutputPath] is set, the output of content shell is compared | 187 * If [expectedOutputPath] is set, the output of content shell is compared |
| 215 * with the content of [expectedOutputPath]. | 188 * with the content of [expectedOutputPath]. |
| 216 * This is used for example for pixel tests, where [expectedOutputPath] points | 189 * This is used for example for pixel tests, where [expectedOutputPath] points |
| 217 * to a *png file. | 190 * to a *png file. |
| 218 */ | 191 */ |
| 219 io.Path expectedOutputPath; | 192 io.Path expectedOutputPath; |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 processOptions); | 1037 processOptions); |
| 1065 processFuture.then((io.Process process) { | 1038 processFuture.then((io.Process process) { |
| 1066 // Close stdin so that tests that try to block on input will fail. | 1039 // Close stdin so that tests that try to block on input will fail. |
| 1067 process.stdin.close(); | 1040 process.stdin.close(); |
| 1068 void timeoutHandler() { | 1041 void timeoutHandler() { |
| 1069 timedOut = true; | 1042 timedOut = true; |
| 1070 if (process != null) { | 1043 if (process != null) { |
| 1071 process.kill(); | 1044 process.kill(); |
| 1072 } | 1045 } |
| 1073 } | 1046 } |
| 1074 process.exitCode.then((exitCode) { | 1047 process.exitCode.then(_commandComplete); |
| 1075 if (exitCode == 0) { | |
| 1076 command.postProcessCommand().then((_) { | |
| 1077 _commandComplete(exitCode); | |
| 1078 }); | |
| 1079 } else { | |
| 1080 _commandComplete(exitCode); | |
| 1081 } | |
| 1082 }); | |
| 1083 _drainStream(process.stdout, stdout); | 1048 _drainStream(process.stdout, stdout); |
| 1084 _drainStream(process.stderr, stderr); | 1049 _drainStream(process.stderr, stderr); |
| 1085 timeoutTimer = new Timer(new Duration(seconds: testCase.timeout), | 1050 timeoutTimer = new Timer(new Duration(seconds: testCase.timeout), |
| 1086 timeoutHandler); | 1051 timeoutHandler); |
| 1087 }).catchError((e) { | 1052 }).catchError((e) { |
| 1088 // TODO(floitsch): should we try to report the stacktrace? | 1053 // TODO(floitsch): should we try to report the stacktrace? |
| 1089 print("Process error:"); | 1054 print("Process error:"); |
| 1090 print(" Command: $command"); | 1055 print(" Command: $command"); |
| 1091 print(" Error: $e"); | 1056 print(" Error: $e"); |
| 1092 _commandComplete(-1); | 1057 _commandComplete(-1); |
| (...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1946 } | 1911 } |
| 1947 } | 1912 } |
| 1948 | 1913 |
| 1949 void eventAllTestsDone() { | 1914 void eventAllTestsDone() { |
| 1950 for (var listener in _eventListener) { | 1915 for (var listener in _eventListener) { |
| 1951 listener.allDone(); | 1916 listener.allDone(); |
| 1952 } | 1917 } |
| 1953 } | 1918 } |
| 1954 } | 1919 } |
| 1955 | 1920 |
| OLD | NEW |