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 23 matching lines...) Expand all Loading... |
34 const int SLOW_TIMEOUT_MULTIPLIER = 4; | 34 const int SLOW_TIMEOUT_MULTIPLIER = 4; |
35 const int NON_UTF_FAKE_EXITCODE = 0xFFFD; | 35 const int NON_UTF_FAKE_EXITCODE = 0xFFFD; |
36 | 36 |
37 const MESSAGE_CANNOT_OPEN_DISPLAY = 'Gtk-WARNING **: cannot open display'; | 37 const MESSAGE_CANNOT_OPEN_DISPLAY = 'Gtk-WARNING **: cannot open display'; |
38 const MESSAGE_FAILED_TO_RUN_COMMAND = 'Failed to run command. return code=1'; | 38 const MESSAGE_FAILED_TO_RUN_COMMAND = 'Failed to run command. return code=1'; |
39 | 39 |
40 typedef void TestCaseEvent(TestCase testCase); | 40 typedef void TestCaseEvent(TestCase testCase); |
41 typedef void ExitCodeEvent(int exitCode); | 41 typedef void ExitCodeEvent(int exitCode); |
42 typedef void EnqueueMoreWork(ProcessQueue queue); | 42 typedef void EnqueueMoreWork(ProcessQueue queue); |
43 typedef void Action(); | 43 typedef void Action(); |
| 44 typedef Future<AdbCommandResult> StepFunction(); |
44 | 45 |
45 // Some IO tests use these variables and get confused if the host environment | 46 // Some IO tests use these variables and get confused if the host environment |
46 // variables are inherited so they are excluded. | 47 // variables are inherited so they are excluded. |
47 const EXCLUDED_ENVIRONMENT_VARIABLES = const [ | 48 const EXCLUDED_ENVIRONMENT_VARIABLES = const [ |
48 'http_proxy', | 49 'http_proxy', |
49 'https_proxy', | 50 'https_proxy', |
50 'no_proxy', | 51 'no_proxy', |
51 'HTTP_PROXY', | 52 'HTTP_PROXY', |
52 'HTTPS_PROXY', | 53 'HTTPS_PROXY', |
53 'NO_PROXY' | 54 'NO_PROXY' |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 String htmlFile, | 260 String htmlFile, |
260 List<String> options, | 261 List<String> options, |
261 List<String> dartFlags, | 262 List<String> dartFlags, |
262 Map<String, String> environmentOverrides) | 263 Map<String, String> environmentOverrides) |
263 : super._("content_shell", executable, _getArguments(options, htmlFile), | 264 : super._("content_shell", executable, _getArguments(options, htmlFile), |
264 _getEnvironment(environmentOverrides, dartFlags)); | 265 _getEnvironment(environmentOverrides, dartFlags)); |
265 | 266 |
266 // Cache the modified environments in a map from the old environment and | 267 // Cache the modified environments in a map from the old environment and |
267 // the string of Dart flags to the new environment. Avoid creating new | 268 // the string of Dart flags to the new environment. Avoid creating new |
268 // environment object for each command object. | 269 // environment object for each command object. |
269 static Map<AddFlagsKey, Map> environments = {}; | 270 static Map<AddFlagsKey, Map<String, String>> environments = {}; |
270 | 271 |
271 static Map<String, String> _getEnvironment( | 272 static Map<String, String> _getEnvironment( |
272 Map<String, String> env, List<String> dartFlags) { | 273 Map<String, String> env, List<String> dartFlags) { |
273 var needDartFlags = dartFlags != null && dartFlags.isNotEmpty; | 274 var needDartFlags = dartFlags != null && dartFlags.isNotEmpty; |
274 if (needDartFlags) { | 275 if (needDartFlags) { |
275 if (env == null) { | 276 if (env == null) { |
276 env = const <String, String>{}; | 277 env = const <String, String>{}; |
277 } | 278 } |
278 var flags = dartFlags.join(' '); | 279 var flags = dartFlags.join(' '); |
279 return environments.putIfAbsent( | 280 return environments.putIfAbsent( |
280 new AddFlagsKey(flags, env), | 281 new AddFlagsKey(flags, env), |
281 () => new Map.from(env) | 282 () => new Map<String, String>.from(env) |
282 ..addAll({'DART_FLAGS': flags, 'DART_FORWARDING_PRINT': '1'})); | 283 ..addAll({'DART_FLAGS': flags, 'DART_FORWARDING_PRINT': '1'})); |
283 } | 284 } |
284 return env; | 285 return env; |
285 } | 286 } |
286 | 287 |
287 static List<String> _getArguments(List<String> options, String htmlFile) { | 288 static List<String> _getArguments(List<String> options, String htmlFile) { |
288 var arguments = options.toList(); | 289 var arguments = options.toList(); |
289 arguments.add(htmlFile); | 290 arguments.add(htmlFile); |
290 return arguments; | 291 return arguments; |
291 } | 292 } |
292 | 293 |
293 int get maxNumRetries => 3; | 294 int get maxNumRetries => 3; |
294 } | 295 } |
295 | 296 |
296 class BrowserTestCommand extends Command { | 297 class BrowserTestCommand extends Command { |
297 final String browser; | 298 final String browser; |
298 final String url; | 299 final String url; |
299 final Map configuration; | 300 final Map<String, dynamic> configuration; |
300 final bool retry; | 301 final bool retry; |
301 | 302 |
302 BrowserTestCommand._( | 303 BrowserTestCommand._( |
303 String _browser, this.url, this.configuration, this.retry) | 304 String _browser, this.url, this.configuration, this.retry) |
304 : browser = _browser, | 305 : browser = _browser, |
305 super._(_browser); | 306 super._(_browser); |
306 | 307 |
307 void _buildHashCode(HashCodeBuilder builder) { | 308 void _buildHashCode(HashCodeBuilder builder) { |
308 super._buildHashCode(builder); | 309 super._buildHashCode(builder); |
309 builder.addJson(browser); | 310 builder.addJson(browser); |
(...skipping 17 matching lines...) Expand all Loading... |
327 url | 328 url |
328 ]; | 329 ]; |
329 return parts.map(escapeCommandLineArgument).join(' '); | 330 return parts.map(escapeCommandLineArgument).join(' '); |
330 } | 331 } |
331 | 332 |
332 int get maxNumRetries => 4; | 333 int get maxNumRetries => 4; |
333 } | 334 } |
334 | 335 |
335 class BrowserHtmlTestCommand extends BrowserTestCommand { | 336 class BrowserHtmlTestCommand extends BrowserTestCommand { |
336 List<String> expectedMessages; | 337 List<String> expectedMessages; |
337 BrowserHtmlTestCommand._(String browser, String url, Map configuration, | 338 BrowserHtmlTestCommand._(String browser, String url, |
338 this.expectedMessages, bool retry) | 339 Map<String, dynamic> configuration, this.expectedMessages, bool retry) |
339 : super._(browser, url, configuration, retry); | 340 : super._(browser, url, configuration, retry); |
340 | 341 |
341 void _buildHashCode(HashCodeBuilder builder) { | 342 void _buildHashCode(HashCodeBuilder builder) { |
342 super._buildHashCode(builder); | 343 super._buildHashCode(builder); |
343 builder.addJson(expectedMessages); | 344 builder.addJson(expectedMessages); |
344 } | 345 } |
345 | 346 |
346 bool _equal(BrowserHtmlTestCommand other) => | 347 bool _equal(BrowserHtmlTestCommand other) => |
347 super._equal(other) && | 348 super._equal(other) && |
348 identical(expectedMessages, other.expectedMessages); | 349 identical(expectedMessages, other.expectedMessages); |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 String executable, | 576 String executable, |
576 String htmlFile, | 577 String htmlFile, |
577 List<String> options, | 578 List<String> options, |
578 List<String> dartFlags, | 579 List<String> dartFlags, |
579 Map<String, String> environment) { | 580 Map<String, String> environment) { |
580 ContentShellCommand command = new ContentShellCommand._( | 581 ContentShellCommand command = new ContentShellCommand._( |
581 executable, htmlFile, options, dartFlags, environment); | 582 executable, htmlFile, options, dartFlags, environment); |
582 return _getUniqueCommand(command); | 583 return _getUniqueCommand(command); |
583 } | 584 } |
584 | 585 |
585 BrowserTestCommand getBrowserTestCommand( | 586 BrowserTestCommand getBrowserTestCommand(String browser, String url, |
586 String browser, String url, Map configuration, bool retry) { | 587 Map<String, dynamic> configuration, bool retry) { |
587 var command = new BrowserTestCommand._(browser, url, configuration, retry); | 588 var command = new BrowserTestCommand._(browser, url, configuration, retry); |
588 return _getUniqueCommand(command); | 589 return _getUniqueCommand(command); |
589 } | 590 } |
590 | 591 |
591 BrowserHtmlTestCommand getBrowserHtmlTestCommand(String browser, String url, | 592 BrowserHtmlTestCommand getBrowserHtmlTestCommand( |
592 Map configuration, List<String> expectedMessages, bool retry) { | 593 String browser, |
| 594 String url, |
| 595 Map<String, dynamic> configuration, |
| 596 List<String> expectedMessages, |
| 597 bool retry) { |
593 var command = new BrowserHtmlTestCommand._( | 598 var command = new BrowserHtmlTestCommand._( |
594 browser, url, configuration, expectedMessages, retry); | 599 browser, url, configuration, expectedMessages, retry); |
595 return _getUniqueCommand(command); | 600 return _getUniqueCommand(command); |
596 } | 601 } |
597 | 602 |
598 CompilationCommand getCompilationCommand( | 603 CompilationCommand getCompilationCommand( |
599 String displayName, | 604 String displayName, |
600 String outputFile, | 605 String outputFile, |
601 bool neverSkipCompilation, | 606 bool neverSkipCompilation, |
602 List<Uri> bootstrapDependencies, | 607 List<Uri> bootstrapDependencies, |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 // We don't want to keep the entire (large) TestInformation structure, | 783 // We don't want to keep the entire (large) TestInformation structure, |
779 // so we copy the needed bools into flags set in a single integer. | 784 // so we copy the needed bools into flags set in a single integer. |
780 if (info.hasRuntimeError) _expectations |= HAS_RUNTIME_ERROR; | 785 if (info.hasRuntimeError) _expectations |= HAS_RUNTIME_ERROR; |
781 if (info.hasStaticWarning) _expectations |= HAS_STATIC_WARNING; | 786 if (info.hasStaticWarning) _expectations |= HAS_STATIC_WARNING; |
782 if (info.isNegativeIfChecked) _expectations |= IS_NEGATIVE_IF_CHECKED; | 787 if (info.isNegativeIfChecked) _expectations |= IS_NEGATIVE_IF_CHECKED; |
783 if (info.hasCompileError) _expectations |= HAS_COMPILE_ERROR; | 788 if (info.hasCompileError) _expectations |= HAS_COMPILE_ERROR; |
784 if (info.hasCompileErrorIfChecked) { | 789 if (info.hasCompileErrorIfChecked) { |
785 _expectations |= HAS_COMPILE_ERROR_IF_CHECKED; | 790 _expectations |= HAS_COMPILE_ERROR_IF_CHECKED; |
786 } | 791 } |
787 if (info.hasCompileError || | 792 if (info.hasCompileError || |
788 (configuration['checked'] && info.hasCompileErrorIfChecked)) { | 793 ((configuration['checked'] as bool) && info.hasCompileErrorIfChecked)) { |
789 _expectations |= EXPECT_COMPILE_ERROR; | 794 _expectations |= EXPECT_COMPILE_ERROR; |
790 } | 795 } |
791 } | 796 } |
792 | 797 |
793 bool get isNegative => _expectations & IS_NEGATIVE != 0; | 798 bool get isNegative => _expectations & IS_NEGATIVE != 0; |
794 bool get hasRuntimeError => _expectations & HAS_RUNTIME_ERROR != 0; | 799 bool get hasRuntimeError => _expectations & HAS_RUNTIME_ERROR != 0; |
795 bool get hasStaticWarning => _expectations & HAS_STATIC_WARNING != 0; | 800 bool get hasStaticWarning => _expectations & HAS_STATIC_WARNING != 0; |
796 bool get isNegativeIfChecked => _expectations & IS_NEGATIVE_IF_CHECKED != 0; | 801 bool get isNegativeIfChecked => _expectations & IS_NEGATIVE_IF_CHECKED != 0; |
797 bool get hasCompileError => _expectations & HAS_COMPILE_ERROR != 0; | 802 bool get hasCompileError => _expectations & HAS_COMPILE_ERROR != 0; |
798 bool get hasCompileErrorIfChecked => | 803 bool get hasCompileErrorIfChecked => |
(...skipping 22 matching lines...) Expand all Loading... |
821 if (commandOutputs.length == 0) { | 826 if (commandOutputs.length == 0) { |
822 throw new Exception("CommandOutputs is empty, maybe no command was run? (" | 827 throw new Exception("CommandOutputs is empty, maybe no command was run? (" |
823 "displayName: '$displayName', " | 828 "displayName: '$displayName', " |
824 "configurationString: '$configurationString')"); | 829 "configurationString: '$configurationString')"); |
825 } | 830 } |
826 return commands[commandOutputs.length - 1]; | 831 return commands[commandOutputs.length - 1]; |
827 } | 832 } |
828 | 833 |
829 int get timeout { | 834 int get timeout { |
830 if (expectedOutcomes.contains(Expectation.slow)) { | 835 if (expectedOutcomes.contains(Expectation.slow)) { |
831 return configuration['timeout'] * SLOW_TIMEOUT_MULTIPLIER; | 836 return (configuration['timeout'] as int) * SLOW_TIMEOUT_MULTIPLIER; |
832 } else { | 837 } else { |
833 return configuration['timeout']; | 838 return configuration['timeout'] as int; |
834 } | 839 } |
835 } | 840 } |
836 | 841 |
837 String get configurationString { | 842 String get configurationString { |
838 final compiler = configuration['compiler']; | 843 var compiler = configuration['compiler'] as String; |
839 final runtime = configuration['runtime']; | 844 var runtime = configuration['runtime'] as String; |
840 final mode = configuration['mode']; | 845 var mode = configuration['mode'] as String; |
841 final arch = configuration['arch']; | 846 var arch = configuration['arch'] as String; |
842 final checked = configuration['checked'] ? '-checked' : ''; | 847 var checked = configuration['checked'] as bool ? '-checked' : ''; |
843 return "$compiler-$runtime$checked ${mode}_$arch"; | 848 return "$compiler-$runtime$checked ${mode}_$arch"; |
844 } | 849 } |
845 | 850 |
846 List<String> get batchTestArguments { | 851 List<String> get batchTestArguments { |
847 assert(commands.last is ProcessCommand); | 852 assert(commands.last is ProcessCommand); |
848 return (commands.last as ProcessCommand).arguments; | 853 return (commands.last as ProcessCommand).arguments; |
849 } | 854 } |
850 | 855 |
851 bool get isFlaky { | 856 bool get isFlaky { |
852 if (expectedOutcomes.contains(Expectation.skip) || | 857 if (expectedOutcomes.contains(Expectation.skip) || |
(...skipping 16 matching lines...) Expand all Loading... |
869 | 874 |
870 /** | 875 /** |
871 * BrowserTestCase has an extra compilation command that is run in a separate | 876 * BrowserTestCase has an extra compilation command that is run in a separate |
872 * process, before the regular test is run as in the base class [TestCase]. | 877 * process, before the regular test is run as in the base class [TestCase]. |
873 * If the compilation command fails, then the rest of the test is not run. | 878 * If the compilation command fails, then the rest of the test is not run. |
874 */ | 879 */ |
875 class BrowserTestCase extends TestCase { | 880 class BrowserTestCase extends TestCase { |
876 BrowserTestCase( | 881 BrowserTestCase( |
877 String displayName, | 882 String displayName, |
878 List<Command> commands, | 883 List<Command> commands, |
879 configuration, | 884 Map<String, dynamic> configuration, |
880 Set<Expectation> expectedOutcomes, | 885 Set<Expectation> expectedOutcomes, |
881 TestInformation info, | 886 TestInformation info, |
882 bool isNegative, | 887 bool isNegative, |
883 this._testingUrl) | 888 this._testingUrl) |
884 : super(displayName, commands, configuration, expectedOutcomes, | 889 : super(displayName, commands, configuration, expectedOutcomes, |
885 isNegative: isNegative, info: info); | 890 isNegative: isNegative, info: info); |
886 | 891 |
887 String _testingUrl; | 892 String _testingUrl; |
888 | 893 |
889 String get testingUrl => _testingUrl; | 894 String get testingUrl => _testingUrl; |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1233 'script_onerror', | 1238 'script_onerror', |
1234 'window_compilationerror', | 1239 'window_compilationerror', |
1235 'print', | 1240 'print', |
1236 'message_received', | 1241 'message_received', |
1237 'dom', | 1242 'dom', |
1238 'debug' | 1243 'debug' |
1239 ]; | 1244 ]; |
1240 | 1245 |
1241 final Expectation outcome; | 1246 final Expectation outcome; |
1242 final String htmlDom; | 1247 final String htmlDom; |
1243 final List events; | 1248 final List<dynamic> events; |
1244 | 1249 |
1245 BrowserTestJsonResult(this.outcome, this.htmlDom, this.events); | 1250 BrowserTestJsonResult(this.outcome, this.htmlDom, this.events); |
1246 | 1251 |
1247 static BrowserTestJsonResult parseFromString(String content) { | 1252 static BrowserTestJsonResult parseFromString(String content) { |
1248 void validate(String assertion, bool value) { | 1253 void validate(String assertion, bool value) { |
1249 if (!value) { | 1254 if (!value) { |
1250 throw "InvalidFormat sent from browser driving page: $assertion:\n\n" | 1255 throw "InvalidFormat sent from browser driving page: $assertion:\n\n" |
1251 "$content"; | 1256 "$content"; |
1252 } | 1257 } |
1253 } | 1258 } |
1254 | 1259 |
1255 try { | 1260 try { |
1256 var events = JSON.decode(content); | 1261 var events = JSON.decode(content); |
1257 if (events != null) { | 1262 if (events != null) { |
1258 validate("Message must be a List", events is List); | 1263 validate("Message must be a List", events is List); |
1259 | 1264 |
1260 Map<String, List<String>> messagesByType = {}; | 1265 var messagesByType = <String, List<String>>{}; |
1261 ALLOWED_TYPES.forEach((type) => messagesByType[type] = <String>[]); | 1266 ALLOWED_TYPES.forEach((type) => messagesByType[type] = <String>[]); |
1262 | 1267 |
1263 for (var entry in events) { | 1268 for (var entry in events) { |
1264 validate("An entry must be a Map", entry is Map); | 1269 validate("An entry must be a Map", entry is Map); |
1265 | 1270 |
1266 var type = entry['type']; | 1271 var type = entry['type']; |
1267 var value = entry['value']; | 1272 var value = entry['value'] as String; |
1268 var timestamp = entry['timestamp']; | 1273 var timestamp = entry['timestamp']; |
1269 | 1274 |
1270 validate("'type' of an entry must be a String", type is String); | 1275 validate("'type' of an entry must be a String", type is String); |
1271 validate("'type' has to be in $ALLOWED_TYPES.", | 1276 validate("'type' has to be in $ALLOWED_TYPES.", |
1272 ALLOWED_TYPES.contains(type)); | 1277 ALLOWED_TYPES.contains(type)); |
1273 validate( | 1278 validate( |
1274 "'timestamp' of an entry must be a number", timestamp is num); | 1279 "'timestamp' of an entry must be a number", timestamp is num); |
1275 | 1280 |
1276 messagesByType[type].add(value); | 1281 messagesByType[type].add(value); |
1277 } | 1282 } |
1278 validate("The message must have exactly one 'dom' entry.", | 1283 validate("The message must have exactly one 'dom' entry.", |
1279 messagesByType['dom'].length == 1); | 1284 messagesByType['dom'].length == 1); |
1280 | 1285 |
1281 var dom = messagesByType['dom'][0]; | 1286 var dom = messagesByType['dom'][0]; |
1282 if (dom.endsWith('\n')) { | 1287 if (dom.endsWith('\n')) { |
1283 dom = '$dom\n'; | 1288 dom = '$dom\n'; |
1284 } | 1289 } |
1285 | 1290 |
1286 return new BrowserTestJsonResult( | 1291 return new BrowserTestJsonResult( |
1287 _getOutcome(messagesByType), dom, events); | 1292 _getOutcome(messagesByType), dom, events as List<dynamic>); |
1288 } | 1293 } |
1289 } catch (error) { | 1294 } catch (error) { |
1290 // If something goes wrong, we know the content was not in the correct | 1295 // If something goes wrong, we know the content was not in the correct |
1291 // JSON format. So we can't parse it. | 1296 // JSON format. So we can't parse it. |
1292 // The caller is responsible for falling back to the old way of | 1297 // The caller is responsible for falling back to the old way of |
1293 // determining if a test failed. | 1298 // determining if a test failed. |
1294 } | 1299 } |
1295 | 1300 |
1296 return null; | 1301 return null; |
1297 } | 1302 } |
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1876 | 1881 |
1877 // Helper to get a list of all child pids for a parent process. | 1882 // Helper to get a list of all child pids for a parent process. |
1878 // The first element of the list is the parent pid. | 1883 // The first element of the list is the parent pid. |
1879 Future<List<int>> _getPidList(int pid, List<String> diagnostics) async { | 1884 Future<List<int>> _getPidList(int pid, List<String> diagnostics) async { |
1880 var pids = [pid]; | 1885 var pids = [pid]; |
1881 List<String> lines; | 1886 List<String> lines; |
1882 var startLine = 0; | 1887 var startLine = 0; |
1883 if (io.Platform.isLinux || io.Platform.isMacOS) { | 1888 if (io.Platform.isLinux || io.Platform.isMacOS) { |
1884 var result = | 1889 var result = |
1885 await io.Process.run("pgrep", ["-P", "${pids[0]}"], runInShell: true); | 1890 await io.Process.run("pgrep", ["-P", "${pids[0]}"], runInShell: true); |
1886 lines = result.stdout.split('\n'); | 1891 lines = (result.stdout as String).split('\n'); |
1887 } else if (io.Platform.isWindows) { | 1892 } else if (io.Platform.isWindows) { |
1888 var result = await io.Process.run( | 1893 var result = await io.Process.run( |
1889 "wmic", | 1894 "wmic", |
1890 [ | 1895 [ |
1891 "process", | 1896 "process", |
1892 "where", | 1897 "where", |
1893 "(ParentProcessId=${pids[0]})", | 1898 "(ParentProcessId=${pids[0]})", |
1894 "get", | 1899 "get", |
1895 "ProcessId" | 1900 "ProcessId" |
1896 ], | 1901 ], |
1897 runInShell: true); | 1902 runInShell: true); |
1898 lines = result.stdout.split('\n'); | 1903 lines = (result.stdout as String).split('\n'); |
1899 // Skip first line containing header "ProcessId". | 1904 // Skip first line containing header "ProcessId". |
1900 startLine = 1; | 1905 startLine = 1; |
1901 } else { | 1906 } else { |
1902 assert(false); | 1907 assert(false); |
1903 } | 1908 } |
1904 if (lines.length > startLine) { | 1909 if (lines.length > startLine) { |
1905 for (var i = startLine; i < lines.length; ++i) { | 1910 for (var i = startLine; i < lines.length; ++i) { |
1906 var pid = int.parse(lines[i], onError: (source) => null); | 1911 var pid = int.parse(lines[i], onError: (source) => null); |
1907 if (pid != null) pids.add(pid); | 1912 if (pid != null) pids.add(pid); |
1908 } | 1913 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2004 String executable; | 2009 String executable; |
2005 if (io.Platform.isLinux) { | 2010 if (io.Platform.isLinux) { |
2006 executable = 'eu-stack'; | 2011 executable = 'eu-stack'; |
2007 } else if (io.Platform.isMacOS) { | 2012 } else if (io.Platform.isMacOS) { |
2008 // Try to print stack traces of the timed out process. | 2013 // Try to print stack traces of the timed out process. |
2009 // `sample` is a sampling profiler but we ask it sample for 1 | 2014 // `sample` is a sampling profiler but we ask it sample for 1 |
2010 // second with a 4 second delay between samples so that we only | 2015 // second with a 4 second delay between samples so that we only |
2011 // sample the threads once. | 2016 // sample the threads once. |
2012 executable = '/usr/bin/sample'; | 2017 executable = '/usr/bin/sample'; |
2013 } else if (io.Platform.isWindows) { | 2018 } else if (io.Platform.isWindows) { |
2014 bool is_x64 = command.executable.contains("X64") || | 2019 var isX64 = command.executable.contains("X64") || |
2015 command.executable.contains("SIMARM64"); | 2020 command.executable.contains("SIMARM64"); |
2016 var winSdkPath = configuration['win_sdk_path']; | 2021 var winSdkPath = configuration['win_sdk_path'] as String; |
2017 if (winSdkPath != null) { | 2022 if (winSdkPath != null) { |
2018 executable = winSdkPath + | 2023 executable = winSdkPath + |
2019 "\\Debuggers\\" + | 2024 "\\Debuggers\\" + |
2020 (is_x64 ? "x64" : "x86") + | 2025 (isX64 ? "x64" : "x86") + |
2021 "\\cdb.exe"; | 2026 "\\cdb.exe"; |
2022 diagnostics.add("Using $executable to print stack traces"); | 2027 diagnostics.add("Using $executable to print stack traces"); |
2023 } else { | 2028 } else { |
2024 diagnostics.add("win_sdk path not found"); | 2029 diagnostics.add("win_sdk path not found"); |
2025 } | 2030 } |
2026 } else { | 2031 } else { |
2027 diagnostics.add("Capturing stack traces on" | 2032 diagnostics.add("Capturing stack traces on" |
2028 "${io.Platform.operatingSystem} not supported"); | 2033 "${io.Platform.operatingSystem} not supported"); |
2029 } | 2034 } |
2030 if (executable != null) { | 2035 if (executable != null) { |
2031 var pids = await _getPidList(process.pid, diagnostics); | 2036 var pids = await _getPidList(process.pid, diagnostics); |
2032 diagnostics.add("Process list including children: $pids"); | 2037 diagnostics.add("Process list including children: $pids"); |
2033 for (pid in pids) { | 2038 for (pid in pids) { |
2034 List<String> arguments; | 2039 List<String> arguments; |
2035 if (io.Platform.isLinux) { | 2040 if (io.Platform.isLinux) { |
2036 arguments = ['-p $pid']; | 2041 arguments = ['-p $pid']; |
2037 } else if (io.Platform.isMacOS) { | 2042 } else if (io.Platform.isMacOS) { |
2038 arguments = ['$pid', '1', '4000', '-mayDie']; | 2043 arguments = ['$pid', '1', '4000', '-mayDie']; |
2039 } else if (io.Platform.isWindows) { | 2044 } else if (io.Platform.isWindows) { |
2040 arguments = ['-p', '$pid', '-c', '!uniqstack;qd']; | 2045 arguments = ['-p', '$pid', '-c', '!uniqstack;qd']; |
2041 } else { | 2046 } else { |
2042 assert(false); | 2047 assert(false); |
2043 } | 2048 } |
2044 diagnostics.add("Trying to capture stack trace for pid $pid"); | 2049 diagnostics.add("Trying to capture stack trace for pid $pid"); |
2045 try { | 2050 try { |
2046 var result = await io.Process.run(executable, arguments); | 2051 var result = await io.Process.run(executable, arguments); |
2047 diagnostics.addAll(result.stdout.split('\n')); | 2052 diagnostics.addAll((result.stdout as String).split('\n')); |
2048 diagnostics.addAll(result.stderr.split('\n')); | 2053 diagnostics.addAll((result.stderr as String).split('\n')); |
2049 } catch (error) { | 2054 } catch (error) { |
2050 diagnostics.add("Unable to capture stack traces: $error"); | 2055 diagnostics.add("Unable to capture stack traces: $error"); |
2051 } | 2056 } |
2052 } | 2057 } |
2053 } | 2058 } |
2054 | 2059 |
2055 if (!process.kill()) { | 2060 if (!process.kill()) { |
2056 diagnostics.add("Unable to kill ${process.pid}"); | 2061 diagnostics.add("Unable to kill ${process.pid}"); |
2057 } | 2062 } |
2058 } | 2063 } |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2124 commandOutput.diagnostics.addAll(diagnostics); | 2129 commandOutput.diagnostics.addAll(diagnostics); |
2125 return commandOutput; | 2130 return commandOutput; |
2126 } | 2131 } |
2127 | 2132 |
2128 StreamSubscription _drainStream( | 2133 StreamSubscription _drainStream( |
2129 Stream<List<int>> source, OutputLog destination) { | 2134 Stream<List<int>> source, OutputLog destination) { |
2130 return source.listen(destination.add); | 2135 return source.listen(destination.add); |
2131 } | 2136 } |
2132 | 2137 |
2133 Map<String, String> _createProcessEnvironment() { | 2138 Map<String, String> _createProcessEnvironment() { |
2134 var environment = new Map.from(io.Platform.environment); | 2139 var environment = new Map<String, String>.from(io.Platform.environment); |
2135 | 2140 |
2136 if (command.environmentOverrides != null) { | 2141 if (command.environmentOverrides != null) { |
2137 for (var key in command.environmentOverrides.keys) { | 2142 for (var key in command.environmentOverrides.keys) { |
2138 environment[key] = command.environmentOverrides[key]; | 2143 environment[key] = command.environmentOverrides[key]; |
2139 } | 2144 } |
2140 } | 2145 } |
2141 for (var excludedEnvironmentVariable in EXCLUDED_ENVIRONMENT_VARIABLES) { | 2146 for (var excludedEnvironmentVariable in EXCLUDED_ENVIRONMENT_VARIABLES) { |
2142 environment.remove(excludedEnvironmentVariable); | 2147 environment.remove(excludedEnvironmentVariable); |
2143 } | 2148 } |
2144 | 2149 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2201 _stdoutSubscription.cancel(); | 2206 _stdoutSubscription.cancel(); |
2202 _stderrSubscription.cancel(); | 2207 _stderrSubscription.cancel(); |
2203 } else { | 2208 } else { |
2204 doStartTest(command, timeout); | 2209 doStartTest(command, timeout); |
2205 } | 2210 } |
2206 return _completer.future; | 2211 return _completer.future; |
2207 } | 2212 } |
2208 | 2213 |
2209 Future<bool> terminate() { | 2214 Future<bool> terminate() { |
2210 if (_process == null) return new Future.value(true); | 2215 if (_process == null) return new Future.value(true); |
2211 Completer terminateCompleter = new Completer<bool>(); | 2216 var terminateCompleter = new Completer<bool>(); |
2212 _processExitHandler = (_) { | 2217 _processExitHandler = (_) { |
2213 terminateCompleter.complete(true); | 2218 terminateCompleter.complete(true); |
2214 }; | 2219 }; |
2215 _process.kill(); | 2220 _process.kill(); |
2216 _stdoutSubscription.cancel(); | 2221 _stdoutSubscription.cancel(); |
2217 _stderrSubscription.cancel(); | 2222 _stderrSubscription.cancel(); |
2218 | 2223 |
2219 return terminateCompleter.future; | 2224 return terminateCompleter.future; |
2220 } | 2225 } |
2221 | 2226 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2282 void _timeoutHandler() { | 2287 void _timeoutHandler() { |
2283 _processExitHandler = makeExitHandler(">>> TEST TIMEOUT"); | 2288 _processExitHandler = makeExitHandler(">>> TEST TIMEOUT"); |
2284 _process.kill(); | 2289 _process.kill(); |
2285 } | 2290 } |
2286 | 2291 |
2287 void _startProcess(Action callback) { | 2292 void _startProcess(Action callback) { |
2288 assert(_command is ProcessCommand); | 2293 assert(_command is ProcessCommand); |
2289 var executable = _command.executable; | 2294 var executable = _command.executable; |
2290 var arguments = _command.batchArguments.toList(); | 2295 var arguments = _command.batchArguments.toList(); |
2291 arguments.add('--batch'); | 2296 arguments.add('--batch'); |
2292 var environment = new Map.from(io.Platform.environment); | 2297 var environment = new Map<String, String>.from(io.Platform.environment); |
2293 if (_processEnvironmentOverrides != null) { | 2298 if (_processEnvironmentOverrides != null) { |
2294 for (var key in _processEnvironmentOverrides.keys) { | 2299 for (var key in _processEnvironmentOverrides.keys) { |
2295 environment[key] = _processEnvironmentOverrides[key]; | 2300 environment[key] = _processEnvironmentOverrides[key]; |
2296 } | 2301 } |
2297 } | 2302 } |
2298 Future processFuture = | 2303 Future processFuture = |
2299 io.Process.start(executable, arguments, environment: environment); | 2304 io.Process.start(executable, arguments, environment: environment); |
2300 processFuture.then((io.Process p) { | 2305 processFuture.then((io.Process p) { |
2301 _process = p; | 2306 _process = p; |
2302 | 2307 |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2722 } else { | 2727 } else { |
2723 return new Future.value(output); | 2728 return new Future.value(output); |
2724 } | 2729 } |
2725 }); | 2730 }); |
2726 } | 2731 } |
2727 | 2732 |
2728 return runCommand(command.maxNumRetries); | 2733 return runCommand(command.maxNumRetries); |
2729 } | 2734 } |
2730 | 2735 |
2731 Future<CommandOutput> _runCommand(Command command, int timeout) { | 2736 Future<CommandOutput> _runCommand(Command command, int timeout) { |
2732 var batchMode = !globalConfiguration['noBatch']; | 2737 var batchMode = !(globalConfiguration['noBatch'] as bool); |
2733 var dart2jsBatchMode = globalConfiguration['dart2js_batch']; | 2738 var dart2jsBatchMode = globalConfiguration['dart2js_batch'] as bool; |
2734 | 2739 |
2735 if (command is BrowserTestCommand) { | 2740 if (command is BrowserTestCommand) { |
2736 return _startBrowserControllerTest(command, timeout); | 2741 return _startBrowserControllerTest(command, timeout); |
2737 } else if (command is KernelCompilationCommand) { | 2742 } else if (command is KernelCompilationCommand) { |
2738 // For now, we always run dartk in batch mode. | 2743 // For now, we always run dartk in batch mode. |
2739 var name = command.displayName; | 2744 var name = command.displayName; |
2740 assert(name == 'dartk'); | 2745 assert(name == 'dartk'); |
2741 return _getBatchRunner(name) | 2746 return _getBatchRunner(name) |
2742 .runCommand(name, command, timeout, command.arguments); | 2747 .runCommand(name, command, timeout, command.arguments); |
2743 } else if (command is CompilationCommand && dart2jsBatchMode) { | 2748 } else if (command is CompilationCommand && dart2jsBatchMode) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2781 // We copy all the files which the vm precompiler puts into the test | 2786 // We copy all the files which the vm precompiler puts into the test |
2782 // directory. | 2787 // directory. |
2783 List<String> files = new io.Directory(testdir) | 2788 List<String> files = new io.Directory(testdir) |
2784 .listSync() | 2789 .listSync() |
2785 .map((file) => file.path) | 2790 .map((file) => file.path) |
2786 .map((path) => path.substring(path.lastIndexOf('/') + 1)) | 2791 .map((path) => path.substring(path.lastIndexOf('/') + 1)) |
2787 .toList(); | 2792 .toList(); |
2788 | 2793 |
2789 var timeoutDuration = new Duration(seconds: timeout); | 2794 var timeoutDuration = new Duration(seconds: timeout); |
2790 | 2795 |
2791 // All closures are of type "Future<AdbCommandResult> run()" | 2796 var steps = <StepFunction>[]; |
2792 List<Function> steps = []; | |
2793 | 2797 |
2794 steps.add(() => device.runAdbShellCommand(['rm', '-Rf', deviceTestDir])); | 2798 steps.add(() => device.runAdbShellCommand(['rm', '-Rf', deviceTestDir])); |
2795 steps.add(() => device.runAdbShellCommand(['mkdir', '-p', deviceTestDir])); | 2799 steps.add(() => device.runAdbShellCommand(['mkdir', '-p', deviceTestDir])); |
2796 steps.add(() => | 2800 steps.add(() => |
2797 device.pushCachedData(runner, '$devicedir/dart_precompiled_runtime')); | 2801 device.pushCachedData(runner, '$devicedir/dart_precompiled_runtime')); |
2798 steps.add( | 2802 steps.add( |
2799 () => device.pushCachedData(processTest, '$devicedir/process_test')); | 2803 () => device.pushCachedData(processTest, '$devicedir/process_test')); |
2800 steps.add(() => device.runAdbShellCommand([ | 2804 steps.add(() => device.runAdbShellCommand([ |
2801 'chmod', | 2805 'chmod', |
2802 '777', | 2806 '777', |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2880 } | 2884 } |
2881 _getBrowserTestRunner(browserCommand.browser, browserCommand.configuration) | 2885 _getBrowserTestRunner(browserCommand.browser, browserCommand.configuration) |
2882 .then((testRunner) { | 2886 .then((testRunner) { |
2883 testRunner.enqueueTest(browserTest); | 2887 testRunner.enqueueTest(browserTest); |
2884 }); | 2888 }); |
2885 | 2889 |
2886 return completer.future; | 2890 return completer.future; |
2887 } | 2891 } |
2888 | 2892 |
2889 Future<BrowserTestRunner> _getBrowserTestRunner( | 2893 Future<BrowserTestRunner> _getBrowserTestRunner( |
2890 String browser, Map configuration) async { | 2894 String browser, Map<String, dynamic> configuration) async { |
2891 var localIp = globalConfiguration['local_ip']; | 2895 var localIp = globalConfiguration['local_ip'] as String; |
2892 if (_browserTestRunners[configuration] == null) { | 2896 if (_browserTestRunners[configuration] == null) { |
2893 var testRunner = new BrowserTestRunner( | 2897 var testRunner = new BrowserTestRunner( |
2894 configuration, localIp, browser, maxBrowserProcesses); | 2898 configuration, localIp, browser, maxBrowserProcesses); |
2895 if (globalConfiguration['verbose']) { | 2899 if (globalConfiguration['verbose'] as bool) { |
2896 testRunner.logger = DebugLogger.info; | 2900 testRunner.logger = DebugLogger.info; |
2897 } | 2901 } |
2898 _browserTestRunners[configuration] = testRunner; | 2902 _browserTestRunners[configuration] = testRunner; |
2899 await testRunner.start(); | 2903 await testRunner.start(); |
2900 } | 2904 } |
2901 return _browserTestRunners[configuration]; | 2905 return _browserTestRunners[configuration]; |
2902 } | 2906 } |
2903 } | 2907 } |
2904 | 2908 |
2905 class RecordingCommandExecutor implements CommandExecutor { | 2909 class RecordingCommandExecutor implements CommandExecutor { |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3215 _graph.events | 3219 _graph.events |
3216 .where((event) => event is dgraph.GraphSealedEvent) | 3220 .where((event) => event is dgraph.GraphSealedEvent) |
3217 .listen((event) { | 3221 .listen((event) { |
3218 eventAllTestsKnown(); | 3222 eventAllTestsKnown(); |
3219 }); | 3223 }); |
3220 | 3224 |
3221 // Queue commands as they become "runnable" | 3225 // Queue commands as they become "runnable" |
3222 new CommandEnqueuer(_graph); | 3226 new CommandEnqueuer(_graph); |
3223 | 3227 |
3224 // CommandExecutor will execute commands | 3228 // CommandExecutor will execute commands |
3225 var executor; | 3229 CommandExecutor executor; |
3226 if (recording) { | 3230 if (recording) { |
3227 executor = new RecordingCommandExecutor(new Path(recordingOutputFile)); | 3231 executor = new RecordingCommandExecutor(new Path(recordingOutputFile)); |
3228 } else if (replaying) { | 3232 } else if (replaying) { |
3229 executor = new ReplayingCommandExecutor(new Path(recordedInputFile)); | 3233 executor = new ReplayingCommandExecutor(new Path(recordedInputFile)); |
3230 } else { | 3234 } else { |
3231 executor = new CommandExecutorImpl( | 3235 executor = new CommandExecutorImpl( |
3232 _globalConfiguration, maxProcesses, maxBrowserProcesses, | 3236 _globalConfiguration, maxProcesses, maxBrowserProcesses, |
3233 adbDevicePool: adbDevicePool); | 3237 adbDevicePool: adbDevicePool); |
3234 } | 3238 } |
3235 | 3239 |
(...skipping 23 matching lines...) Expand all Loading... |
3259 | 3263 |
3260 resetDebugTimer(); | 3264 resetDebugTimer(); |
3261 } | 3265 } |
3262 | 3266 |
3263 // Build up the dependency graph | 3267 // Build up the dependency graph |
3264 testCaseEnqueuer = new TestCaseEnqueuer(_graph, (TestCase newTestCase) { | 3268 testCaseEnqueuer = new TestCaseEnqueuer(_graph, (TestCase newTestCase) { |
3265 eventTestAdded(newTestCase); | 3269 eventTestAdded(newTestCase); |
3266 }); | 3270 }); |
3267 | 3271 |
3268 // Either list or run the tests | 3272 // Either list or run the tests |
3269 if (_globalConfiguration['list']) { | 3273 if (_globalConfiguration['list'] as bool) { |
3270 setupForListing(testCaseEnqueuer); | 3274 setupForListing(testCaseEnqueuer); |
3271 } else { | 3275 } else { |
3272 setupForRunning(testCaseEnqueuer); | 3276 setupForRunning(testCaseEnqueuer); |
3273 } | 3277 } |
3274 | 3278 |
3275 // Start enqueing all TestCases | 3279 // Start enqueing all TestCases |
3276 testCaseEnqueuer.enqueueTestSuites(testSuites); | 3280 testCaseEnqueuer.enqueueTestSuites(testSuites); |
3277 } | 3281 } |
3278 | 3282 |
3279 void freeEnqueueingStructures() { | 3283 void freeEnqueueingStructures() { |
(...skipping 19 matching lines...) Expand all Loading... |
3299 } | 3303 } |
3300 } | 3304 } |
3301 | 3305 |
3302 void eventAllTestsDone() { | 3306 void eventAllTestsDone() { |
3303 for (var listener in _eventListener) { | 3307 for (var listener in _eventListener) { |
3304 listener.allDone(); | 3308 listener.allDone(); |
3305 } | 3309 } |
3306 _allDone(); | 3310 _allDone(); |
3307 } | 3311 } |
3308 } | 3312 } |
OLD | NEW |