| 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 |