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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 return false; | 150 return false; |
151 } | 151 } |
152 } | 152 } |
153 } | 153 } |
154 return true; | 154 return true; |
155 } | 155 } |
156 | 156 |
157 String toString() => commandLine; | 157 String toString() => commandLine; |
158 | 158 |
159 Future<bool> get outputIsUpToDate => new Future.value(false); | 159 Future<bool> get outputIsUpToDate => new Future.value(false); |
160 Path get expectedOutputFile => null; | |
161 bool get isPixelTest => false; | |
162 } | 160 } |
163 | 161 |
164 class CompilationCommand extends Command { | 162 class CompilationCommand extends Command { |
165 String _outputFile; | 163 String _outputFile; |
166 bool _neverSkipCompilation; | 164 bool _neverSkipCompilation; |
167 List<Uri> _bootstrapDependencies; | 165 List<Uri> _bootstrapDependencies; |
168 | 166 |
169 CompilationCommand._(String displayName, | 167 CompilationCommand._(String displayName, |
170 this._outputFile, | 168 this._outputFile, |
171 this._neverSkipCompilation, | 169 this._neverSkipCompilation, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 return false; | 236 return false; |
239 } | 237 } |
240 } | 238 } |
241 return true; | 239 return true; |
242 } | 240 } |
243 return false; | 241 return false; |
244 } | 242 } |
245 } | 243 } |
246 | 244 |
247 class ContentShellCommand extends Command { | 245 class ContentShellCommand extends Command { |
248 /** | |
249 * If [expectedOutputPath] is set, the output of content shell is compared | |
250 * with the content of [expectedOutputPath]. | |
251 * This is used for example for pixel tests, where [expectedOutputPath] points | |
252 * to a *png file. | |
253 */ | |
254 Path expectedOutputPath; | |
255 | |
256 ContentShellCommand._(String executable, | 246 ContentShellCommand._(String executable, |
257 String htmlFile, | 247 String htmlFile, |
258 List<String> options, | 248 List<String> options, |
259 List<String> dartFlags, | 249 List<String> dartFlags, |
260 Path this.expectedOutputPath, | |
261 String configurationDir) | 250 String configurationDir) |
262 : super._("content_shell", | 251 : super._("content_shell", |
263 executable, | 252 executable, |
264 _getArguments(options, htmlFile), | 253 _getArguments(options, htmlFile), |
265 configurationDir, | 254 configurationDir, |
266 _getEnvironment(dartFlags)); | 255 _getEnvironment(dartFlags)); |
267 | 256 |
268 static Map _getEnvironment(List<String> dartFlags) { | 257 static Map _getEnvironment(List<String> dartFlags) { |
269 var needDartFlags = dartFlags != null && dartFlags.length > 0; | 258 var needDartFlags = dartFlags != null && dartFlags.length > 0; |
270 | 259 |
271 var env = null; | 260 var env = null; |
272 if (needDartFlags) { | 261 if (needDartFlags) { |
273 env = new Map<String, String>(); | 262 env = new Map<String, String>(); |
274 env['DART_FLAGS'] = dartFlags.join(" "); | 263 env['DART_FLAGS'] = dartFlags.join(" "); |
275 env['DART_FORWARDING_PRINT'] = '1'; | 264 env['DART_FORWARDING_PRINT'] = '1'; |
276 } | 265 } |
277 | 266 |
278 return env; | 267 return env; |
279 } | 268 } |
280 | 269 |
281 static List<String> _getArguments(List<String> options, String htmlFile) { | 270 static List<String> _getArguments(List<String> options, String htmlFile) { |
282 var arguments = new List.from(options); | 271 var arguments = new List.from(options); |
283 arguments.add(htmlFile); | 272 arguments.add(htmlFile); |
284 return arguments; | 273 return arguments; |
285 } | 274 } |
286 | 275 |
287 Path get expectedOutputFile => expectedOutputPath; | |
288 bool get isPixelTest => (expectedOutputFile != null && | |
289 expectedOutputFile.filename.endsWith(".png")); | |
290 | |
291 void _buildHashCode(HashCodeBuilder builder) { | |
292 super._buildHashCode(builder); | |
293 builder.add(expectedOutputPath.toString()); | |
294 } | |
295 | |
296 bool _equal(Command other) { | 276 bool _equal(Command other) { |
297 return | 277 return other is ContentShellCommand && super._equal(other); |
298 other is ContentShellCommand && | |
299 super._equal(other) && | |
300 expectedOutputPath.toString() == other.expectedOutputPath.toString(); | |
301 } | 278 } |
302 | 279 |
303 int get maxNumRetries => 3; | 280 int get maxNumRetries => 3; |
304 } | 281 } |
305 | 282 |
306 class BrowserTestCommand extends Command { | 283 class BrowserTestCommand extends Command { |
307 final String browser; | 284 final String browser; |
308 final String url; | 285 final String url; |
309 | 286 |
310 BrowserTestCommand._(String _browser, | 287 BrowserTestCommand._(String _browser, |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 static final instance = new CommandBuilder._(); | 381 static final instance = new CommandBuilder._(); |
405 | 382 |
406 final _cachedCommands = new Map<Command, Command>(); | 383 final _cachedCommands = new Map<Command, Command>(); |
407 | 384 |
408 CommandBuilder._(); | 385 CommandBuilder._(); |
409 | 386 |
410 ContentShellCommand getContentShellCommand(String executable, | 387 ContentShellCommand getContentShellCommand(String executable, |
411 String htmlFile, | 388 String htmlFile, |
412 List<String> options, | 389 List<String> options, |
413 List<String> dartFlags, | 390 List<String> dartFlags, |
414 Path expectedOutputPath, | |
415 String configurationDir) { | 391 String configurationDir) { |
416 ContentShellCommand command = new ContentShellCommand._( | 392 ContentShellCommand command = new ContentShellCommand._( |
417 executable, htmlFile, options, dartFlags, expectedOutputPath, | 393 executable, htmlFile, options, dartFlags, configurationDir); |
418 configurationDir); | |
419 return _getUniqueCommand(command); | 394 return _getUniqueCommand(command); |
420 } | 395 } |
421 | 396 |
422 BrowserTestCommand getBrowserTestCommand(String browser, | 397 BrowserTestCommand getBrowserTestCommand(String browser, |
423 String url, | 398 String url, |
424 String executable, | 399 String executable, |
425 List<String> arguments, | 400 List<String> arguments, |
426 String configurationDir) { | 401 String configurationDir) { |
427 var command = new BrowserTestCommand._( | 402 var command = new BrowserTestCommand._( |
428 browser, url, executable, arguments, configurationDir); | 403 browser, url, executable, arguments, configurationDir); |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 | 794 |
820 bool get hasCrashed { | 795 bool get hasCrashed { |
821 return super.hasCrashed || _rendererCrashed; | 796 return super.hasCrashed || _rendererCrashed; |
822 } | 797 } |
823 | 798 |
824 Expectation _getOutcome() { | 799 Expectation _getOutcome() { |
825 if (_failedBecauseOfMissingXDisplay) { | 800 if (_failedBecauseOfMissingXDisplay) { |
826 return Expectation.FAIL; | 801 return Expectation.FAIL; |
827 } | 802 } |
828 | 803 |
829 if (command.expectedOutputFile != null) { | |
830 // We are either doing a pixel test or a layout test with content shell | |
831 if (_failedBecauseOfUnexpectedDRTOutput) { | |
832 return Expectation.FAIL; | |
833 } | |
834 } | |
835 if (_browserTestFailure) { | 804 if (_browserTestFailure) { |
836 return Expectation.RUNTIME_ERROR; | 805 return Expectation.RUNTIME_ERROR; |
837 } | 806 } |
838 return Expectation.PASS; | 807 return Expectation.PASS; |
839 } | 808 } |
840 | 809 |
841 bool _didFailBecauseOfMissingXDisplay() { | 810 bool _didFailBecauseOfMissingXDisplay() { |
842 // Browser case: | 811 // Browser case: |
843 // If the browser test failed, it may have been because content shell | 812 // If the browser test failed, it may have been because content shell |
844 // and the virtual framebuffer X server didn't hook up, or it crashed with | 813 // and the virtual framebuffer X server didn't hook up, or it crashed with |
845 // a core dump. Sometimes content shell crashes after it has set the stdout | 814 // a core dump. Sometimes content shell crashes after it has set the stdout |
846 // to PASS, so we have to do this check first. | 815 // to PASS, so we have to do this check first. |
847 var stderrLines = decodeUtf8(super.stderr).split("\n"); | 816 var stderrLines = decodeUtf8(super.stderr).split("\n"); |
848 for (String line in stderrLines) { | 817 for (String line in stderrLines) { |
849 // TODO(kustermann,ricow): Issue: 7564 | 818 // TODO(kustermann,ricow): Issue: 7564 |
850 // This seems to happen quite frequently, we need to figure out why. | 819 // This seems to happen quite frequently, we need to figure out why. |
851 if (line.contains(MESSAGE_CANNOT_OPEN_DISPLAY) || | 820 if (line.contains(MESSAGE_CANNOT_OPEN_DISPLAY) || |
852 line.contains(MESSAGE_FAILED_TO_RUN_COMMAND)) { | 821 line.contains(MESSAGE_FAILED_TO_RUN_COMMAND)) { |
853 return true; | 822 return true; |
854 } | 823 } |
855 } | 824 } |
856 return false; | 825 return false; |
857 } | 826 } |
858 | 827 |
859 bool get _rendererCrashed => | 828 bool get _rendererCrashed => |
860 decodeUtf8(super.stdout).contains("#CRASHED - rendere"); | 829 decodeUtf8(super.stdout).contains("#CRASHED - rendere"); |
861 | 830 |
862 bool get _failedBecauseOfUnexpectedDRTOutput { | |
863 /* | |
864 * The output of content shell is different for pixel tests than for | |
865 * layout tests. | |
866 * | |
867 * On a pixel test, the DRT output has the following format | |
868 * ...... | |
869 * ...... | |
870 * Content-Length: ...\n | |
871 * <*png data> | |
872 * #EOF\n | |
873 * So we need to get the byte-range of the png data first, before | |
874 * comparing it with the content of the expected output file. | |
875 * | |
876 * On a layout tests, the DRT output is directly compared with the | |
877 * content of the expected output. | |
878 */ | |
879 var file = new io.File(command.expectedOutputFile.toNativePath()); | |
880 if (file.existsSync()) { | |
881 var bytesContentLength = "Content-Length:".codeUnits; | |
882 var bytesNewLine = "\n".codeUnits; | |
883 var bytesEOF = "#EOF\n".codeUnits; | |
884 | |
885 var expectedContent = file.readAsBytesSync(); | |
886 if (command.isPixelTest) { | |
887 var startOfContentLength = findBytes(stdout, bytesContentLength); | |
888 if (startOfContentLength >= 0) { | |
889 var newLineAfterContentLength = findBytes(stdout, | |
890 bytesNewLine, | |
891 startOfContentLength); | |
892 if (newLineAfterContentLength > 0) { | |
893 var startPosition = newLineAfterContentLength + | |
894 bytesNewLine.length; | |
895 var endPosition = stdout.length - bytesEOF.length; | |
896 | |
897 return !areByteArraysEqual(expectedContent, | |
898 0, | |
899 stdout, | |
900 startPosition, | |
901 endPosition - startPosition); | |
902 } | |
903 } | |
904 return true; | |
905 } else { | |
906 return !areByteArraysEqual(expectedContent, 0, | |
907 stdout, 0, | |
908 stdout.length); | |
909 } | |
910 } | |
911 return true; | |
912 } | |
913 | |
914 bool get _browserTestFailure { | 831 bool get _browserTestFailure { |
915 // Browser tests fail unless stdout contains | 832 // Browser tests fail unless stdout contains |
916 // 'Content-Type: text/plain' followed by 'PASS'. | 833 // 'Content-Type: text/plain' followed by 'PASS'. |
917 bool hasContentType = false; | 834 bool hasContentType = false; |
918 var stdoutLines = decodeUtf8(super.stdout).split("\n"); | 835 var stdoutLines = decodeUtf8(super.stdout).split("\n"); |
919 var containsFail = false; | 836 var containsFail = false; |
920 var containsPass = false; | 837 var containsPass = false; |
921 for (String line in stdoutLines) { | 838 for (String line in stdoutLines) { |
922 switch (line) { | 839 switch (line) { |
923 case 'Content-Type: text/plain': | 840 case 'Content-Type: text/plain': |
(...skipping 1475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2399 } | 2316 } |
2400 } | 2317 } |
2401 | 2318 |
2402 void eventAllTestsDone() { | 2319 void eventAllTestsDone() { |
2403 for (var listener in _eventListener) { | 2320 for (var listener in _eventListener) { |
2404 listener.allDone(); | 2321 listener.allDone(); |
2405 } | 2322 } |
2406 _allDone(); | 2323 _allDone(); |
2407 } | 2324 } |
2408 } | 2325 } |
OLD | NEW |