| 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. |
| 11 */ | 11 */ |
| 12 library test_runner; | 12 import 'dart:async'; |
| 13 | 13 import 'dart:collection'; |
| 14 import "dart:async"; | 14 import 'dart:convert'; |
| 15 import "dart:collection" show Queue; | |
| 16 import "dart:convert" show LineSplitter, UTF8, JSON; | |
| 17 // We need to use the 'io' prefix here, otherwise io.exitCode will shadow | 15 // We need to use the 'io' prefix here, otherwise io.exitCode will shadow |
| 18 // CommandOutput.exitCode in subclasses of CommandOutput. | 16 // CommandOutput.exitCode in subclasses of CommandOutput. |
| 19 import "dart:io" as io; | 17 import 'dart:io' as io; |
| 20 import "dart:math" as math; | 18 import 'dart:math' as math; |
| 21 | 19 |
| 22 import 'android.dart'; | 20 import 'android.dart'; |
| 23 import "browser_controller.dart"; | 21 import 'browser_controller.dart'; |
| 22 import 'configuration.dart'; |
| 24 import 'dependency_graph.dart' as dgraph; | 23 import 'dependency_graph.dart' as dgraph; |
| 25 import "expectation.dart"; | 24 import 'expectation.dart'; |
| 26 import "path.dart"; | 25 import 'path.dart'; |
| 27 import 'record_and_replay.dart'; | 26 import 'record_and_replay.dart'; |
| 28 import "runtime_configuration.dart"; | 27 import 'runtime_configuration.dart'; |
| 29 import "test_progress.dart"; | 28 import 'test_progress.dart'; |
| 30 import "test_suite.dart"; | 29 import 'test_suite.dart'; |
| 31 import "utils.dart"; | 30 import 'utils.dart'; |
| 32 | 31 |
| 33 const int CRASHING_BROWSER_EXITCODE = -10; | 32 const int CRASHING_BROWSER_EXITCODE = -10; |
| 34 const int SLOW_TIMEOUT_MULTIPLIER = 4; | 33 const int SLOW_TIMEOUT_MULTIPLIER = 4; |
| 35 const int NON_UTF_FAKE_EXITCODE = 0xFFFD; | 34 const int NON_UTF_FAKE_EXITCODE = 0xFFFD; |
| 36 | 35 |
| 37 const MESSAGE_CANNOT_OPEN_DISPLAY = 'Gtk-WARNING **: cannot open display'; | 36 const MESSAGE_CANNOT_OPEN_DISPLAY = 'Gtk-WARNING **: cannot open display'; |
| 38 const MESSAGE_FAILED_TO_RUN_COMMAND = 'Failed to run command. return code=1'; | 37 const MESSAGE_FAILED_TO_RUN_COMMAND = 'Failed to run command. return code=1'; |
| 39 | 38 |
| 40 typedef void TestCaseEvent(TestCase testCase); | 39 typedef void TestCaseEvent(TestCase testCase); |
| 41 typedef void ExitCodeEvent(int exitCode); | 40 typedef void ExitCodeEvent(int exitCode); |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 static List<String> _getArguments(List<String> options, String htmlFile) { | 287 static List<String> _getArguments(List<String> options, String htmlFile) { |
| 289 var arguments = options.toList(); | 288 var arguments = options.toList(); |
| 290 arguments.add(htmlFile); | 289 arguments.add(htmlFile); |
| 291 return arguments; | 290 return arguments; |
| 292 } | 291 } |
| 293 | 292 |
| 294 int get maxNumRetries => 3; | 293 int get maxNumRetries => 3; |
| 295 } | 294 } |
| 296 | 295 |
| 297 class BrowserTestCommand extends Command { | 296 class BrowserTestCommand extends Command { |
| 298 final String browser; | 297 Runtime get browser => configuration.runtime; |
| 299 final String url; | 298 final String url; |
| 300 final Map<String, dynamic> configuration; | 299 final Configuration configuration; |
| 301 final bool retry; | 300 final bool retry; |
| 302 | 301 |
| 303 BrowserTestCommand._( | 302 BrowserTestCommand._(this.url, this.configuration, this.retry) |
| 304 String _browser, this.url, this.configuration, this.retry) | 303 : super._(configuration.runtime.name); |
| 305 : browser = _browser, | |
| 306 super._(_browser); | |
| 307 | 304 |
| 308 void _buildHashCode(HashCodeBuilder builder) { | 305 void _buildHashCode(HashCodeBuilder builder) { |
| 309 super._buildHashCode(builder); | 306 super._buildHashCode(builder); |
| 310 builder.addJson(browser); | 307 builder.addJson(browser.name); |
| 311 builder.addJson(url); | 308 builder.addJson(url); |
| 312 builder.add(configuration); | 309 builder.add(configuration); |
| 313 builder.add(retry); | 310 builder.add(retry); |
| 314 } | 311 } |
| 315 | 312 |
| 316 bool _equal(BrowserTestCommand other) => | 313 bool _equal(BrowserTestCommand other) => |
| 317 super._equal(other) && | 314 super._equal(other) && |
| 318 browser == other.browser && | 315 browser == other.browser && |
| 319 url == other.url && | 316 url == other.url && |
| 320 identical(configuration, other.configuration) && | 317 identical(configuration, other.configuration) && |
| 321 retry == other.retry; | 318 retry == other.retry; |
| 322 | 319 |
| 323 String get reproductionCommand { | 320 String get reproductionCommand { |
| 324 var parts = [ | 321 var parts = [ |
| 325 io.Platform.resolvedExecutable, | 322 io.Platform.resolvedExecutable, |
| 326 'tools/testing/dart/launch_browser.dart', | 323 'tools/testing/dart/launch_browser.dart', |
| 327 browser, | 324 browser.name, |
| 328 url | 325 url |
| 329 ]; | 326 ]; |
| 330 return parts.map(escapeCommandLineArgument).join(' '); | 327 return parts.map(escapeCommandLineArgument).join(' '); |
| 331 } | 328 } |
| 332 | 329 |
| 333 int get maxNumRetries => 4; | 330 int get maxNumRetries => 4; |
| 334 } | 331 } |
| 335 | 332 |
| 336 class BrowserHtmlTestCommand extends BrowserTestCommand { | 333 class BrowserHtmlTestCommand extends BrowserTestCommand { |
| 337 List<String> expectedMessages; | 334 List<String> expectedMessages; |
| 338 BrowserHtmlTestCommand._(String browser, String url, | 335 BrowserHtmlTestCommand._(String url, Configuration configuration, |
| 339 Map<String, dynamic> configuration, this.expectedMessages, bool retry) | 336 this.expectedMessages, bool retry) |
| 340 : super._(browser, url, configuration, retry); | 337 : super._(url, configuration, retry); |
| 341 | 338 |
| 342 void _buildHashCode(HashCodeBuilder builder) { | 339 void _buildHashCode(HashCodeBuilder builder) { |
| 343 super._buildHashCode(builder); | 340 super._buildHashCode(builder); |
| 344 builder.addJson(expectedMessages); | 341 builder.addJson(expectedMessages); |
| 345 } | 342 } |
| 346 | 343 |
| 347 bool _equal(BrowserHtmlTestCommand other) => | 344 bool _equal(BrowserHtmlTestCommand other) => |
| 348 super._equal(other) && | 345 super._equal(other) && |
| 349 identical(expectedMessages, other.expectedMessages); | 346 identical(expectedMessages, other.expectedMessages); |
| 350 } | 347 } |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 String executable, | 573 String executable, |
| 577 String htmlFile, | 574 String htmlFile, |
| 578 List<String> options, | 575 List<String> options, |
| 579 List<String> dartFlags, | 576 List<String> dartFlags, |
| 580 Map<String, String> environment) { | 577 Map<String, String> environment) { |
| 581 ContentShellCommand command = new ContentShellCommand._( | 578 ContentShellCommand command = new ContentShellCommand._( |
| 582 executable, htmlFile, options, dartFlags, environment); | 579 executable, htmlFile, options, dartFlags, environment); |
| 583 return _getUniqueCommand(command); | 580 return _getUniqueCommand(command); |
| 584 } | 581 } |
| 585 | 582 |
| 586 BrowserTestCommand getBrowserTestCommand(String browser, String url, | 583 BrowserTestCommand getBrowserTestCommand( |
| 587 Map<String, dynamic> configuration, bool retry) { | 584 String url, Configuration configuration, bool retry) { |
| 588 var command = new BrowserTestCommand._(browser, url, configuration, retry); | 585 var command = new BrowserTestCommand._(url, configuration, retry); |
| 589 return _getUniqueCommand(command); | 586 return _getUniqueCommand(command); |
| 590 } | 587 } |
| 591 | 588 |
| 592 BrowserHtmlTestCommand getBrowserHtmlTestCommand( | 589 BrowserHtmlTestCommand getBrowserHtmlTestCommand(String url, |
| 593 String browser, | 590 Configuration configuration, List<String> expectedMessages, bool retry) { |
| 594 String url, | |
| 595 Map<String, dynamic> configuration, | |
| 596 List<String> expectedMessages, | |
| 597 bool retry) { | |
| 598 var command = new BrowserHtmlTestCommand._( | 591 var command = new BrowserHtmlTestCommand._( |
| 599 browser, url, configuration, expectedMessages, retry); | 592 url, configuration, expectedMessages, retry); |
| 600 return _getUniqueCommand(command); | 593 return _getUniqueCommand(command); |
| 601 } | 594 } |
| 602 | 595 |
| 603 CompilationCommand getCompilationCommand( | 596 CompilationCommand getCompilationCommand( |
| 604 String displayName, | 597 String displayName, |
| 605 String outputFile, | 598 String outputFile, |
| 606 bool neverSkipCompilation, | 599 bool neverSkipCompilation, |
| 607 List<Uri> bootstrapDependencies, | 600 List<Uri> bootstrapDependencies, |
| 608 String executable, | 601 String executable, |
| 609 List<String> arguments, | 602 List<String> arguments, |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 /** | 746 /** |
| 754 * A list of commands to execute. Most test cases have a single command. | 747 * A list of commands to execute. Most test cases have a single command. |
| 755 * Dart2js tests have two commands, one to compile the source and another | 748 * Dart2js tests have two commands, one to compile the source and another |
| 756 * to execute it. Some isolate tests might even have three, if they require | 749 * to execute it. Some isolate tests might even have three, if they require |
| 757 * compiling multiple sources that are run in isolation. | 750 * compiling multiple sources that are run in isolation. |
| 758 */ | 751 */ |
| 759 List<Command> commands; | 752 List<Command> commands; |
| 760 Map<Command, CommandOutput> commandOutputs = | 753 Map<Command, CommandOutput> commandOutputs = |
| 761 new Map<Command, CommandOutput>(); | 754 new Map<Command, CommandOutput>(); |
| 762 | 755 |
| 763 Map configuration; | 756 Configuration configuration; |
| 764 String displayName; | 757 String displayName; |
| 765 int _expectations = 0; | 758 int _expectations = 0; |
| 766 int hash = 0; | 759 int hash = 0; |
| 767 Set<Expectation> expectedOutcomes; | 760 Set<Expectation> expectedOutcomes; |
| 768 | 761 |
| 769 TestCase(this.displayName, this.commands, this.configuration, | 762 TestCase(this.displayName, this.commands, this.configuration, |
| 770 this.expectedOutcomes, | 763 this.expectedOutcomes, |
| 771 {bool isNegative: false, TestInformation info}) { | 764 {bool isNegative: false, TestInformation info}) { |
| 772 if (isNegative || displayName.contains("negative_test")) { | 765 if (isNegative || displayName.contains("negative_test")) { |
| 773 _expectations |= IS_NEGATIVE; | 766 _expectations |= IS_NEGATIVE; |
| 774 } | 767 } |
| 775 if (info != null) { | 768 if (info != null) { |
| 776 _setExpectations(info); | 769 _setExpectations(info); |
| 777 hash = | 770 hash = |
| 778 info.originTestPath.relativeTo(TestUtils.dartDir).toString().hashCode; | 771 info.originTestPath.relativeTo(TestUtils.dartDir).toString().hashCode; |
| 779 } | 772 } |
| 780 } | 773 } |
| 781 | 774 |
| 782 void _setExpectations(TestInformation info) { | 775 void _setExpectations(TestInformation info) { |
| 783 // We don't want to keep the entire (large) TestInformation structure, | 776 // We don't want to keep the entire (large) TestInformation structure, |
| 784 // so we copy the needed bools into flags set in a single integer. | 777 // so we copy the needed bools into flags set in a single integer. |
| 785 if (info.hasRuntimeError) _expectations |= HAS_RUNTIME_ERROR; | 778 if (info.hasRuntimeError) _expectations |= HAS_RUNTIME_ERROR; |
| 786 if (info.hasStaticWarning) _expectations |= HAS_STATIC_WARNING; | 779 if (info.hasStaticWarning) _expectations |= HAS_STATIC_WARNING; |
| 787 if (info.isNegativeIfChecked) _expectations |= IS_NEGATIVE_IF_CHECKED; | 780 if (info.isNegativeIfChecked) _expectations |= IS_NEGATIVE_IF_CHECKED; |
| 788 if (info.hasCompileError) _expectations |= HAS_COMPILE_ERROR; | 781 if (info.hasCompileError) _expectations |= HAS_COMPILE_ERROR; |
| 789 if (info.hasCompileErrorIfChecked) { | 782 if (info.hasCompileErrorIfChecked) { |
| 790 _expectations |= HAS_COMPILE_ERROR_IF_CHECKED; | 783 _expectations |= HAS_COMPILE_ERROR_IF_CHECKED; |
| 791 } | 784 } |
| 792 if (info.hasCompileError || | 785 if (info.hasCompileError || |
| 793 ((configuration['checked'] as bool) && info.hasCompileErrorIfChecked)) { | 786 (configuration.isChecked && info.hasCompileErrorIfChecked)) { |
| 794 _expectations |= EXPECT_COMPILE_ERROR; | 787 _expectations |= EXPECT_COMPILE_ERROR; |
| 795 } | 788 } |
| 796 } | 789 } |
| 797 | 790 |
| 798 bool get isNegative => _expectations & IS_NEGATIVE != 0; | 791 bool get isNegative => _expectations & IS_NEGATIVE != 0; |
| 799 bool get hasRuntimeError => _expectations & HAS_RUNTIME_ERROR != 0; | 792 bool get hasRuntimeError => _expectations & HAS_RUNTIME_ERROR != 0; |
| 800 bool get hasStaticWarning => _expectations & HAS_STATIC_WARNING != 0; | 793 bool get hasStaticWarning => _expectations & HAS_STATIC_WARNING != 0; |
| 801 bool get isNegativeIfChecked => _expectations & IS_NEGATIVE_IF_CHECKED != 0; | 794 bool get isNegativeIfChecked => _expectations & IS_NEGATIVE_IF_CHECKED != 0; |
| 802 bool get hasCompileError => _expectations & HAS_COMPILE_ERROR != 0; | 795 bool get hasCompileError => _expectations & HAS_COMPILE_ERROR != 0; |
| 803 bool get hasCompileErrorIfChecked => | 796 bool get hasCompileErrorIfChecked => |
| (...skipping 21 matching lines...) Expand all Loading... |
| 825 Command get lastCommandExecuted { | 818 Command get lastCommandExecuted { |
| 826 if (commandOutputs.length == 0) { | 819 if (commandOutputs.length == 0) { |
| 827 throw new Exception("CommandOutputs is empty, maybe no command was run? (" | 820 throw new Exception("CommandOutputs is empty, maybe no command was run? (" |
| 828 "displayName: '$displayName', " | 821 "displayName: '$displayName', " |
| 829 "configurationString: '$configurationString')"); | 822 "configurationString: '$configurationString')"); |
| 830 } | 823 } |
| 831 return commands[commandOutputs.length - 1]; | 824 return commands[commandOutputs.length - 1]; |
| 832 } | 825 } |
| 833 | 826 |
| 834 int get timeout { | 827 int get timeout { |
| 828 var result = configuration.timeout; |
| 835 if (expectedOutcomes.contains(Expectation.slow)) { | 829 if (expectedOutcomes.contains(Expectation.slow)) { |
| 836 return (configuration['timeout'] as int) * SLOW_TIMEOUT_MULTIPLIER; | 830 result *= SLOW_TIMEOUT_MULTIPLIER; |
| 837 } else { | |
| 838 return configuration['timeout'] as int; | |
| 839 } | 831 } |
| 832 return result; |
| 840 } | 833 } |
| 841 | 834 |
| 842 String get configurationString { | 835 String get configurationString { |
| 843 var compiler = configuration['compiler'] as String; | 836 var compiler = configuration.compiler.name; |
| 844 var runtime = configuration['runtime'] as String; | 837 var runtime = configuration.runtime.name; |
| 845 var mode = configuration['mode'] as String; | 838 var mode = configuration.mode.name; |
| 846 var arch = configuration['arch'] as String; | 839 var arch = configuration.architecture.name; |
| 847 var checked = configuration['checked'] as bool ? '-checked' : ''; | 840 var checked = configuration.isChecked ? '-checked' : ''; |
| 848 return "$compiler-$runtime$checked ${mode}_$arch"; | 841 return "$compiler-$runtime$checked ${mode}_$arch"; |
| 849 } | 842 } |
| 850 | 843 |
| 851 List<String> get batchTestArguments { | 844 List<String> get batchTestArguments { |
| 852 assert(commands.last is ProcessCommand); | 845 assert(commands.last is ProcessCommand); |
| 853 return (commands.last as ProcessCommand).arguments; | 846 return (commands.last as ProcessCommand).arguments; |
| 854 } | 847 } |
| 855 | 848 |
| 856 bool get isFlaky { | 849 bool get isFlaky { |
| 857 if (expectedOutcomes.contains(Expectation.skip) || | 850 if (expectedOutcomes.contains(Expectation.skip) || |
| (...skipping 16 matching lines...) Expand all Loading... |
| 874 | 867 |
| 875 /** | 868 /** |
| 876 * BrowserTestCase has an extra compilation command that is run in a separate | 869 * BrowserTestCase has an extra compilation command that is run in a separate |
| 877 * process, before the regular test is run as in the base class [TestCase]. | 870 * process, before the regular test is run as in the base class [TestCase]. |
| 878 * If the compilation command fails, then the rest of the test is not run. | 871 * If the compilation command fails, then the rest of the test is not run. |
| 879 */ | 872 */ |
| 880 class BrowserTestCase extends TestCase { | 873 class BrowserTestCase extends TestCase { |
| 881 BrowserTestCase( | 874 BrowserTestCase( |
| 882 String displayName, | 875 String displayName, |
| 883 List<Command> commands, | 876 List<Command> commands, |
| 884 Map<String, dynamic> configuration, | 877 Configuration configuration, |
| 885 Set<Expectation> expectedOutcomes, | 878 Set<Expectation> expectedOutcomes, |
| 886 TestInformation info, | 879 TestInformation info, |
| 887 bool isNegative, | 880 bool isNegative, |
| 888 this._testingUrl) | 881 this._testingUrl) |
| 889 : super(displayName, commands, configuration, expectedOutcomes, | 882 : super(displayName, commands, configuration, expectedOutcomes, |
| 890 isNegative: isNegative, info: info); | 883 isNegative: isNegative, info: info); |
| 891 | 884 |
| 892 String _testingUrl; | 885 String _testingUrl; |
| 893 | 886 |
| 894 String get testingUrl => _testingUrl; | 887 String get testingUrl => _testingUrl; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1078 } | 1071 } |
| 1079 // TODO(26739): See http://dartbug.com/26739 | 1072 // TODO(26739): See http://dartbug.com/26739 |
| 1080 if (zygoteCrash.hasMatch(stderr)) { | 1073 if (zygoteCrash.hasMatch(stderr)) { |
| 1081 DebugLogger.warning("Warning: Failure because of content_shell " | 1074 DebugLogger.warning("Warning: Failure because of content_shell " |
| 1082 "zygote crash. Test ignored"); | 1075 "zygote crash. Test ignored"); |
| 1083 return true; | 1076 return true; |
| 1084 } | 1077 } |
| 1085 // TODO(28955): See http://dartbug.com/28955 | 1078 // TODO(28955): See http://dartbug.com/28955 |
| 1086 if (timedOut && | 1079 if (timedOut && |
| 1087 command is BrowserTestCommand && | 1080 command is BrowserTestCommand && |
| 1088 command.browser == "ie11") { | 1081 command.browser == Runtime.ie11) { |
| 1089 DebugLogger.warning("Timeout of ie11 on test page ${command.url}"); | 1082 DebugLogger.warning("Timeout of ie11 on test page ${command.url}"); |
| 1090 return true; | 1083 return true; |
| 1091 } | 1084 } |
| 1092 return false; | 1085 return false; |
| 1093 } | 1086 } |
| 1094 | 1087 |
| 1095 bool _infraFailure; | 1088 bool _infraFailure; |
| 1096 | 1089 |
| 1097 BrowserCommandOutputImpl( | 1090 BrowserCommandOutputImpl( |
| 1098 Command command, | 1091 Command command, |
| (...skipping 834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1933 int timeout; | 1926 int timeout; |
| 1934 bool timedOut = false; | 1927 bool timedOut = false; |
| 1935 DateTime startTime; | 1928 DateTime startTime; |
| 1936 Timer timeoutTimer; | 1929 Timer timeoutTimer; |
| 1937 int pid; | 1930 int pid; |
| 1938 OutputLog stdout = new OutputLog(); | 1931 OutputLog stdout = new OutputLog(); |
| 1939 OutputLog stderr = new OutputLog(); | 1932 OutputLog stderr = new OutputLog(); |
| 1940 List<String> diagnostics = <String>[]; | 1933 List<String> diagnostics = <String>[]; |
| 1941 bool compilationSkipped = false; | 1934 bool compilationSkipped = false; |
| 1942 Completer<CommandOutput> completer; | 1935 Completer<CommandOutput> completer; |
| 1943 Map configuration; | 1936 Configuration configuration; |
| 1944 | 1937 |
| 1945 RunningProcess(this.command, this.timeout, {this.configuration}); | 1938 RunningProcess(this.command, this.timeout, {this.configuration}); |
| 1946 | 1939 |
| 1947 Future<CommandOutput> run() { | 1940 Future<CommandOutput> run() { |
| 1948 completer = new Completer<CommandOutput>(); | 1941 completer = new Completer<CommandOutput>(); |
| 1949 startTime = new DateTime.now(); | 1942 startTime = new DateTime.now(); |
| 1950 _runCommand(); | 1943 _runCommand(); |
| 1951 return completer.future; | 1944 return completer.future; |
| 1952 } | 1945 } |
| 1953 | 1946 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2011 executable = 'eu-stack'; | 2004 executable = 'eu-stack'; |
| 2012 } else if (io.Platform.isMacOS) { | 2005 } else if (io.Platform.isMacOS) { |
| 2013 // Try to print stack traces of the timed out process. | 2006 // Try to print stack traces of the timed out process. |
| 2014 // `sample` is a sampling profiler but we ask it sample for 1 | 2007 // `sample` is a sampling profiler but we ask it sample for 1 |
| 2015 // second with a 4 second delay between samples so that we only | 2008 // second with a 4 second delay between samples so that we only |
| 2016 // sample the threads once. | 2009 // sample the threads once. |
| 2017 executable = '/usr/bin/sample'; | 2010 executable = '/usr/bin/sample'; |
| 2018 } else if (io.Platform.isWindows) { | 2011 } else if (io.Platform.isWindows) { |
| 2019 var isX64 = command.executable.contains("X64") || | 2012 var isX64 = command.executable.contains("X64") || |
| 2020 command.executable.contains("SIMARM64"); | 2013 command.executable.contains("SIMARM64"); |
| 2021 var winSdkPath = configuration['win_sdk_path'] as String; | 2014 if (configuration.windowsSdkPath != null) { |
| 2022 if (winSdkPath != null) { | 2015 executable = configuration.windowsSdkPath + |
| 2023 executable = winSdkPath + | 2016 "\\Debuggers\\${isX64 ? 'x64' : 'x86'}\\cdb.exe"; |
| 2024 "\\Debuggers\\" + | |
| 2025 (isX64 ? "x64" : "x86") + | |
| 2026 "\\cdb.exe"; | |
| 2027 diagnostics.add("Using $executable to print stack traces"); | 2017 diagnostics.add("Using $executable to print stack traces"); |
| 2028 } else { | 2018 } else { |
| 2029 diagnostics.add("win_sdk path not found"); | 2019 diagnostics.add("win_sdk_path not found"); |
| 2030 } | 2020 } |
| 2031 } else { | 2021 } else { |
| 2032 diagnostics.add("Capturing stack traces on" | 2022 diagnostics.add("Capturing stack traces on" |
| 2033 "${io.Platform.operatingSystem} not supported"); | 2023 "${io.Platform.operatingSystem} not supported"); |
| 2034 } | 2024 } |
| 2035 if (executable != null) { | 2025 if (executable != null) { |
| 2036 var pids = await _getPidList(process.pid, diagnostics); | 2026 var pids = await _getPidList(process.pid, diagnostics); |
| 2037 diagnostics.add("Process list including children: $pids"); | 2027 diagnostics.add("Process list including children: $pids"); |
| 2038 for (pid in pids) { | 2028 for (pid in pids) { |
| 2039 List<String> arguments; | 2029 List<String> arguments; |
| (...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2667 * It provides a [cleanup] method to free all the allocated resources. | 2657 * It provides a [cleanup] method to free all the allocated resources. |
| 2668 */ | 2658 */ |
| 2669 abstract class CommandExecutor { | 2659 abstract class CommandExecutor { |
| 2670 Future cleanup(); | 2660 Future cleanup(); |
| 2671 // TODO(kustermann): The [timeout] parameter should be a property of Command | 2661 // TODO(kustermann): The [timeout] parameter should be a property of Command |
| 2672 Future<CommandOutput> runCommand( | 2662 Future<CommandOutput> runCommand( |
| 2673 dgraph.Node node, covariant Command command, int timeout); | 2663 dgraph.Node node, covariant Command command, int timeout); |
| 2674 } | 2664 } |
| 2675 | 2665 |
| 2676 class CommandExecutorImpl implements CommandExecutor { | 2666 class CommandExecutorImpl implements CommandExecutor { |
| 2677 final Map globalConfiguration; | 2667 final Configuration globalConfiguration; |
| 2678 final int maxProcesses; | 2668 final int maxProcesses; |
| 2679 final int maxBrowserProcesses; | 2669 final int maxBrowserProcesses; |
| 2680 AdbDevicePool adbDevicePool; | 2670 AdbDevicePool adbDevicePool; |
| 2681 | 2671 |
| 2682 // For dart2js and analyzer batch processing, | 2672 // For dart2js and analyzer batch processing, |
| 2683 // we keep a list of batch processes. | 2673 // we keep a list of batch processes. |
| 2684 final _batchProcesses = new Map<String, List<BatchRunnerProcess>>(); | 2674 final _batchProcesses = new Map<String, List<BatchRunnerProcess>>(); |
| 2685 // We keep a BrowserTestRunner for every configuration. | 2675 // We keep a BrowserTestRunner for every configuration. |
| 2686 final _browserTestRunners = new Map<Map, BrowserTestRunner>(); | 2676 final _browserTestRunners = new Map<Configuration, BrowserTestRunner>(); |
| 2687 | 2677 |
| 2688 bool _finishing = false; | 2678 bool _finishing = false; |
| 2689 | 2679 |
| 2690 CommandExecutorImpl( | 2680 CommandExecutorImpl( |
| 2691 this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses, | 2681 this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses, |
| 2692 {this.adbDevicePool}); | 2682 {this.adbDevicePool}); |
| 2693 | 2683 |
| 2694 Future cleanup() { | 2684 Future cleanup() { |
| 2695 assert(!_finishing); | 2685 assert(!_finishing); |
| 2696 _finishing = true; | 2686 _finishing = true; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2727 } else { | 2717 } else { |
| 2728 return new Future.value(output); | 2718 return new Future.value(output); |
| 2729 } | 2719 } |
| 2730 }); | 2720 }); |
| 2731 } | 2721 } |
| 2732 | 2722 |
| 2733 return runCommand(command.maxNumRetries); | 2723 return runCommand(command.maxNumRetries); |
| 2734 } | 2724 } |
| 2735 | 2725 |
| 2736 Future<CommandOutput> _runCommand(Command command, int timeout) { | 2726 Future<CommandOutput> _runCommand(Command command, int timeout) { |
| 2737 var batchMode = !(globalConfiguration['noBatch'] as bool); | |
| 2738 var dart2jsBatchMode = globalConfiguration['dart2js_batch'] as bool; | |
| 2739 | |
| 2740 if (command is BrowserTestCommand) { | 2727 if (command is BrowserTestCommand) { |
| 2741 return _startBrowserControllerTest(command, timeout); | 2728 return _startBrowserControllerTest(command, timeout); |
| 2742 } else if (command is KernelCompilationCommand) { | 2729 } else if (command is KernelCompilationCommand) { |
| 2743 // For now, we always run dartk in batch mode. | 2730 // For now, we always run dartk in batch mode. |
| 2744 var name = command.displayName; | 2731 var name = command.displayName; |
| 2745 assert(name == 'dartk'); | 2732 assert(name == 'dartk'); |
| 2746 return _getBatchRunner(name) | 2733 return _getBatchRunner(name) |
| 2747 .runCommand(name, command, timeout, command.arguments); | 2734 .runCommand(name, command, timeout, command.arguments); |
| 2748 } else if (command is CompilationCommand && dart2jsBatchMode) { | 2735 } else if (command is CompilationCommand && |
| 2736 globalConfiguration.batchDart2JS) { |
| 2749 return _getBatchRunner("dart2js") | 2737 return _getBatchRunner("dart2js") |
| 2750 .runCommand("dart2js", command, timeout, command.arguments); | 2738 .runCommand("dart2js", command, timeout, command.arguments); |
| 2751 } else if (command is AnalysisCommand && batchMode) { | 2739 } else if (command is AnalysisCommand && globalConfiguration.batch) { |
| 2752 return _getBatchRunner(command.flavor) | 2740 return _getBatchRunner(command.flavor) |
| 2753 .runCommand(command.flavor, command, timeout, command.arguments); | 2741 .runCommand(command.flavor, command, timeout, command.arguments); |
| 2754 } else if (command is ScriptCommand) { | 2742 } else if (command is ScriptCommand) { |
| 2755 return command.run(); | 2743 return command.run(); |
| 2756 } else if (command is AdbPrecompilationCommand) { | 2744 } else if (command is AdbPrecompilationCommand) { |
| 2757 assert(adbDevicePool != null); | 2745 assert(adbDevicePool != null); |
| 2758 return adbDevicePool.acquireDevice().then((AdbDevice device) { | 2746 return adbDevicePool.acquireDevice().then((AdbDevice device) { |
| 2759 return _runAdbPrecompilationCommand(device, command, timeout) | 2747 return _runAdbPrecompilationCommand(device, command, timeout) |
| 2760 .whenComplete(() { | 2748 .whenComplete(() { |
| 2761 adbDevicePool.releaseDevice(device); | 2749 adbDevicePool.releaseDevice(device); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2875 .complete(new BrowserControllerTestOutcome(browserCommand, output)); | 2863 .complete(new BrowserControllerTestOutcome(browserCommand, output)); |
| 2876 }; | 2864 }; |
| 2877 | 2865 |
| 2878 BrowserTest browserTest; | 2866 BrowserTest browserTest; |
| 2879 if (browserCommand is BrowserHtmlTestCommand) { | 2867 if (browserCommand is BrowserHtmlTestCommand) { |
| 2880 browserTest = new HtmlTest(browserCommand.url, callback, timeout, | 2868 browserTest = new HtmlTest(browserCommand.url, callback, timeout, |
| 2881 browserCommand.expectedMessages); | 2869 browserCommand.expectedMessages); |
| 2882 } else { | 2870 } else { |
| 2883 browserTest = new BrowserTest(browserCommand.url, callback, timeout); | 2871 browserTest = new BrowserTest(browserCommand.url, callback, timeout); |
| 2884 } | 2872 } |
| 2885 _getBrowserTestRunner(browserCommand.browser, browserCommand.configuration) | 2873 _getBrowserTestRunner(browserCommand.configuration).then((testRunner) { |
| 2886 .then((testRunner) { | |
| 2887 testRunner.enqueueTest(browserTest); | 2874 testRunner.enqueueTest(browserTest); |
| 2888 }); | 2875 }); |
| 2889 | 2876 |
| 2890 return completer.future; | 2877 return completer.future; |
| 2891 } | 2878 } |
| 2892 | 2879 |
| 2893 Future<BrowserTestRunner> _getBrowserTestRunner( | 2880 Future<BrowserTestRunner> _getBrowserTestRunner( |
| 2894 String browser, Map<String, dynamic> configuration) async { | 2881 Configuration configuration) async { |
| 2895 var localIp = globalConfiguration['local_ip'] as String; | |
| 2896 if (_browserTestRunners[configuration] == null) { | 2882 if (_browserTestRunners[configuration] == null) { |
| 2897 var testRunner = new BrowserTestRunner( | 2883 var testRunner = new BrowserTestRunner( |
| 2898 configuration, localIp, browser, maxBrowserProcesses); | 2884 configuration, globalConfiguration.localIP, maxBrowserProcesses); |
| 2899 if (globalConfiguration['verbose'] as bool) { | 2885 if (globalConfiguration.isVerbose) { |
| 2900 testRunner.logger = DebugLogger.info; | 2886 testRunner.logger = DebugLogger.info; |
| 2901 } | 2887 } |
| 2902 _browserTestRunners[configuration] = testRunner; | 2888 _browserTestRunners[configuration] = testRunner; |
| 2903 await testRunner.start(); | 2889 await testRunner.start(); |
| 2904 } | 2890 } |
| 2905 return _browserTestRunners[configuration]; | 2891 return _browserTestRunners[configuration]; |
| 2906 } | 2892 } |
| 2907 } | 2893 } |
| 2908 | 2894 |
| 2909 class RecordingCommandExecutor implements CommandExecutor { | 2895 class RecordingCommandExecutor implements CommandExecutor { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2975 if (stdout.any(containsOutOfMemoryMessage) || | 2961 if (stdout.any(containsOutOfMemoryMessage) || |
| 2976 stderr.any(containsOutOfMemoryMessage)) { | 2962 stderr.any(containsOutOfMemoryMessage)) { |
| 2977 return true; | 2963 return true; |
| 2978 } | 2964 } |
| 2979 } | 2965 } |
| 2980 } | 2966 } |
| 2981 | 2967 |
| 2982 // We currently rerun dartium tests, see issue 14074. | 2968 // We currently rerun dartium tests, see issue 14074. |
| 2983 if (command is BrowserTestCommand && | 2969 if (command is BrowserTestCommand && |
| 2984 command.retry && | 2970 command.retry && |
| 2985 command.browser == 'dartium') { | 2971 command.browser == Runtime.dartium) { |
| 2986 return true; | 2972 return true; |
| 2987 } | 2973 } |
| 2988 | 2974 |
| 2989 // As long as we use a legacy version of our custom content_shell (which | 2975 // As long as we use a legacy version of our custom content_shell (which |
| 2990 // became quite flaky after chrome-50 roll) we'll re-run tests on it. | 2976 // became quite flaky after chrome-50 roll) we'll re-run tests on it. |
| 2991 // The plan is to use chrome's content_shell instead of our own. | 2977 // The plan is to use chrome's content_shell instead of our own. |
| 2992 // See http://dartbug.com/29655 . | 2978 // See http://dartbug.com/29655 . |
| 2993 if (command is ContentShellCommand) { | 2979 if (command is ContentShellCommand) { |
| 2994 return true; | 2980 return true; |
| 2995 } | 2981 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3108 // [TestCase.isFinished] will return true if all commands were executed | 3094 // [TestCase.isFinished] will return true if all commands were executed |
| 3109 // or if a previous one failed. | 3095 // or if a previous one failed. |
| 3110 if (testCase.isFinished) { | 3096 if (testCase.isFinished) { |
| 3111 completeTestCase(testCase); | 3097 completeTestCase(testCase); |
| 3112 } | 3098 } |
| 3113 } | 3099 } |
| 3114 } | 3100 } |
| 3115 } | 3101 } |
| 3116 | 3102 |
| 3117 class ProcessQueue { | 3103 class ProcessQueue { |
| 3118 Map _globalConfiguration; | 3104 Configuration _globalConfiguration; |
| 3119 | 3105 |
| 3120 Function _allDone; | 3106 Function _allDone; |
| 3121 final dgraph.Graph _graph = new dgraph.Graph(); | 3107 final dgraph.Graph _graph = new dgraph.Graph(); |
| 3122 List<EventListener> _eventListener; | 3108 List<EventListener> _eventListener; |
| 3123 | 3109 |
| 3124 ProcessQueue( | 3110 ProcessQueue( |
| 3125 this._globalConfiguration, | 3111 this._globalConfiguration, |
| 3126 int maxProcesses, | 3112 int maxProcesses, |
| 3127 int maxBrowserProcesses, | 3113 int maxBrowserProcesses, |
| 3128 DateTime startTime, | 3114 DateTime startTime, |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3263 | 3249 |
| 3264 resetDebugTimer(); | 3250 resetDebugTimer(); |
| 3265 } | 3251 } |
| 3266 | 3252 |
| 3267 // Build up the dependency graph | 3253 // Build up the dependency graph |
| 3268 testCaseEnqueuer = new TestCaseEnqueuer(_graph, (TestCase newTestCase) { | 3254 testCaseEnqueuer = new TestCaseEnqueuer(_graph, (TestCase newTestCase) { |
| 3269 eventTestAdded(newTestCase); | 3255 eventTestAdded(newTestCase); |
| 3270 }); | 3256 }); |
| 3271 | 3257 |
| 3272 // Either list or run the tests | 3258 // Either list or run the tests |
| 3273 if (_globalConfiguration['list'] as bool) { | 3259 if (_globalConfiguration.listTests) { |
| 3274 setupForListing(testCaseEnqueuer); | 3260 setupForListing(testCaseEnqueuer); |
| 3275 } else { | 3261 } else { |
| 3276 setupForRunning(testCaseEnqueuer); | 3262 setupForRunning(testCaseEnqueuer); |
| 3277 } | 3263 } |
| 3278 | 3264 |
| 3279 // Start enqueing all TestCases | 3265 // Start enqueing all TestCases |
| 3280 testCaseEnqueuer.enqueueTestSuites(testSuites); | 3266 testCaseEnqueuer.enqueueTestSuites(testSuites); |
| 3281 } | 3267 } |
| 3282 | 3268 |
| 3283 void freeEnqueueingStructures() { | 3269 void freeEnqueueingStructures() { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3303 } | 3289 } |
| 3304 } | 3290 } |
| 3305 | 3291 |
| 3306 void eventAllTestsDone() { | 3292 void eventAllTestsDone() { |
| 3307 for (var listener in _eventListener) { | 3293 for (var listener in _eventListener) { |
| 3308 listener.allDone(); | 3294 listener.allDone(); |
| 3309 } | 3295 } |
| 3310 _allDone(); | 3296 _allDone(); |
| 3311 } | 3297 } |
| 3312 } | 3298 } |
| OLD | NEW |