| 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 22 matching lines...) Expand all Loading... |
| 33 const int CRASHING_BROWSER_EXITCODE = -10; | 33 const int CRASHING_BROWSER_EXITCODE = -10; |
| 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 | 44 |
| 44 // Some IO tests use these variables and get confused if the host environment | 45 // Some IO tests use these variables and get confused if the host environment |
| 45 // variables are inherited so they are excluded. | 46 // variables are inherited so they are excluded. |
| 46 const List<String> EXCLUDED_ENVIRONMENT_VARIABLES = const [ | 47 const EXCLUDED_ENVIRONMENT_VARIABLES = const [ |
| 47 'http_proxy', | 48 'http_proxy', |
| 48 'https_proxy', | 49 'https_proxy', |
| 49 'no_proxy', | 50 'no_proxy', |
| 50 'HTTP_PROXY', | 51 'HTTP_PROXY', |
| 51 'HTTPS_PROXY', | 52 'HTTPS_PROXY', |
| 52 'NO_PROXY' | 53 'NO_PROXY' |
| 53 ]; | 54 ]; |
| 54 | 55 |
| 55 /** A command executed as a step in a test case. */ | 56 /** A command executed as a step in a test case. */ |
| 56 class Command { | 57 class Command { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 71 | 72 |
| 72 int get hashCode { | 73 int get hashCode { |
| 73 if (_cachedHashCode == null) { | 74 if (_cachedHashCode == null) { |
| 74 var builder = new HashCodeBuilder(); | 75 var builder = new HashCodeBuilder(); |
| 75 _buildHashCode(builder); | 76 _buildHashCode(builder); |
| 76 _cachedHashCode = builder.value; | 77 _cachedHashCode = builder.value; |
| 77 } | 78 } |
| 78 return _cachedHashCode; | 79 return _cachedHashCode; |
| 79 } | 80 } |
| 80 | 81 |
| 81 operator ==(other) => | 82 operator ==(Object other) => |
| 82 identical(this, other) || | 83 identical(this, other) || |
| 83 (runtimeType == other.runtimeType && _equal(other)); | 84 (runtimeType == other.runtimeType && _equal(other as Command)); |
| 84 | 85 |
| 85 void _buildHashCode(HashCodeBuilder builder) { | 86 void _buildHashCode(HashCodeBuilder builder) { |
| 86 builder.addJson(displayName); | 87 builder.addJson(displayName); |
| 87 } | 88 } |
| 88 | 89 |
| 89 bool _equal(covariant Command other) => | 90 bool _equal(covariant Command other) => |
| 90 hashCode == other.hashCode && displayName == other.displayName; | 91 hashCode == other.hashCode && displayName == other.displayName; |
| 91 | 92 |
| 92 String toString() => reproductionCommand; | 93 String toString() => reproductionCommand; |
| 93 | 94 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 | 241 |
| 241 int get maxNumRetries => 1; | 242 int get maxNumRetries => 1; |
| 242 } | 243 } |
| 243 | 244 |
| 244 /// This is just a Pair(String, Map) class with hashCode and operator == | 245 /// This is just a Pair(String, Map) class with hashCode and operator == |
| 245 class AddFlagsKey { | 246 class AddFlagsKey { |
| 246 final String flags; | 247 final String flags; |
| 247 final Map env; | 248 final Map env; |
| 248 AddFlagsKey(this.flags, this.env); | 249 AddFlagsKey(this.flags, this.env); |
| 249 // Just use object identity for environment map | 250 // Just use object identity for environment map |
| 250 bool operator ==(other) => | 251 bool operator ==(Object other) => |
| 251 other is AddFlagsKey && flags == other.flags && env == other.env; | 252 other is AddFlagsKey && flags == other.flags && env == other.env; |
| 252 int get hashCode => flags.hashCode ^ env.hashCode; | 253 int get hashCode => flags.hashCode ^ env.hashCode; |
| 253 } | 254 } |
| 254 | 255 |
| 255 class ContentShellCommand extends ProcessCommand { | 256 class ContentShellCommand extends ProcessCommand { |
| 256 ContentShellCommand._( | 257 ContentShellCommand._( |
| 257 String executable, | 258 String executable, |
| 258 String htmlFile, | 259 String htmlFile, |
| 259 List<String> options, | 260 List<String> options, |
| 260 List<String> dartFlags, | 261 List<String> dartFlags, |
| 261 Map<String, String> environmentOverrides) | 262 Map<String, String> environmentOverrides) |
| 262 : super._("content_shell", executable, _getArguments(options, htmlFile), | 263 : super._("content_shell", executable, _getArguments(options, htmlFile), |
| 263 _getEnvironment(environmentOverrides, dartFlags)); | 264 _getEnvironment(environmentOverrides, dartFlags)); |
| 264 | 265 |
| 265 // Cache the modified environments in a map from the old environment and | 266 // Cache the modified environments in a map from the old environment and |
| 266 // the string of Dart flags to the new environment. Avoid creating new | 267 // the string of Dart flags to the new environment. Avoid creating new |
| 267 // environment object for each command object. | 268 // environment object for each command object. |
| 268 static Map<AddFlagsKey, Map> environments = <AddFlagsKey, Map>{}; | 269 static Map<AddFlagsKey, Map> environments = {}; |
| 269 | 270 |
| 270 static Map<String, String> _getEnvironment( | 271 static Map<String, String> _getEnvironment( |
| 271 Map<String, String> env, List<String> dartFlags) { | 272 Map<String, String> env, List<String> dartFlags) { |
| 272 var needDartFlags = dartFlags != null && dartFlags.length > 0; | 273 var needDartFlags = dartFlags != null && dartFlags.isNotEmpty; |
| 273 if (needDartFlags) { | 274 if (needDartFlags) { |
| 274 if (env == null) { | 275 if (env == null) { |
| 275 env = const <String, String>{}; | 276 env = const <String, String>{}; |
| 276 } | 277 } |
| 277 var flags = dartFlags.join(' '); | 278 var flags = dartFlags.join(' '); |
| 278 return environments.putIfAbsent( | 279 return environments.putIfAbsent( |
| 279 new AddFlagsKey(flags, env), | 280 new AddFlagsKey(flags, env), |
| 280 () => new Map.from(env) | 281 () => new Map.from(env) |
| 281 ..addAll({'DART_FLAGS': flags, 'DART_FORWARDING_PRINT': '1'})); | 282 ..addAll({'DART_FLAGS': flags, 'DART_FORWARDING_PRINT': '1'})); |
| 282 } | 283 } |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 | 478 |
| 478 String get reproductionCommand => | 479 String get reproductionCommand => |
| 479 "Copying '$_sourceDirectory' to '$_destinationDirectory'."; | 480 "Copying '$_sourceDirectory' to '$_destinationDirectory'."; |
| 480 | 481 |
| 481 Future<ScriptCommandOutputImpl> run() { | 482 Future<ScriptCommandOutputImpl> run() { |
| 482 var watch = new Stopwatch()..start(); | 483 var watch = new Stopwatch()..start(); |
| 483 | 484 |
| 484 var destination = new io.Directory(_destinationDirectory); | 485 var destination = new io.Directory(_destinationDirectory); |
| 485 | 486 |
| 486 return destination.exists().then((bool exists) { | 487 return destination.exists().then((bool exists) { |
| 487 var cleanDirectoryFuture; | 488 Future cleanDirectoryFuture; |
| 488 if (exists) { | 489 if (exists) { |
| 489 cleanDirectoryFuture = TestUtils.deleteDirectory(_destinationDirectory); | 490 cleanDirectoryFuture = TestUtils.deleteDirectory(_destinationDirectory); |
| 490 } else { | 491 } else { |
| 491 cleanDirectoryFuture = new Future.value(null); | 492 cleanDirectoryFuture = new Future.value(null); |
| 492 } | 493 } |
| 493 return cleanDirectoryFuture.then((_) { | 494 return cleanDirectoryFuture.then((_) { |
| 494 return TestUtils.copyDirectory(_sourceDirectory, _destinationDirectory); | 495 return TestUtils.copyDirectory(_sourceDirectory, _destinationDirectory); |
| 495 }); | 496 }); |
| 496 }).then((_) { | 497 }).then((_) { |
| 497 return new ScriptCommandOutputImpl( | 498 return new ScriptCommandOutputImpl( |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 | 590 |
| 590 BrowserHtmlTestCommand getBrowserHtmlTestCommand(String browser, String url, | 591 BrowserHtmlTestCommand getBrowserHtmlTestCommand(String browser, String url, |
| 591 Map configuration, List<String> expectedMessages, bool retry) { | 592 Map configuration, List<String> expectedMessages, bool retry) { |
| 592 var command = new BrowserHtmlTestCommand._( | 593 var command = new BrowserHtmlTestCommand._( |
| 593 browser, url, configuration, expectedMessages, retry); | 594 browser, url, configuration, expectedMessages, retry); |
| 594 return _getUniqueCommand(command); | 595 return _getUniqueCommand(command); |
| 595 } | 596 } |
| 596 | 597 |
| 597 CompilationCommand getCompilationCommand( | 598 CompilationCommand getCompilationCommand( |
| 598 String displayName, | 599 String displayName, |
| 599 outputFile, | 600 String outputFile, |
| 600 neverSkipCompilation, | 601 bool neverSkipCompilation, |
| 601 List<Uri> bootstrapDependencies, | 602 List<Uri> bootstrapDependencies, |
| 602 String executable, | 603 String executable, |
| 603 List<String> arguments, | 604 List<String> arguments, |
| 604 Map<String, String> environment) { | 605 Map<String, String> environment) { |
| 605 var command = new CompilationCommand._( | 606 var command = new CompilationCommand._( |
| 606 displayName, | 607 displayName, |
| 607 outputFile, | 608 outputFile, |
| 608 neverSkipCompilation, | 609 neverSkipCompilation, |
| 609 bootstrapDependencies, | 610 bootstrapDependencies, |
| 610 executable, | 611 executable, |
| 611 arguments, | 612 arguments, |
| 612 environment); | 613 environment); |
| 613 return _getUniqueCommand(command); | 614 return _getUniqueCommand(command); |
| 614 } | 615 } |
| 615 | 616 |
| 616 CompilationCommand getKernelCompilationCommand( | 617 CompilationCommand getKernelCompilationCommand( |
| 617 String displayName, | 618 String displayName, |
| 618 outputFile, | 619 String outputFile, |
| 619 neverSkipCompilation, | 620 bool neverSkipCompilation, |
| 620 List<Uri> bootstrapDependencies, | 621 List<Uri> bootstrapDependencies, |
| 621 String executable, | 622 String executable, |
| 622 List<String> arguments, | 623 List<String> arguments, |
| 623 Map<String, String> environment) { | 624 Map<String, String> environment) { |
| 624 var command = new KernelCompilationCommand._( | 625 var command = new KernelCompilationCommand._( |
| 625 displayName, | 626 displayName, |
| 626 outputFile, | 627 outputFile, |
| 627 neverSkipCompilation, | 628 neverSkipCompilation, |
| 628 bootstrapDependencies, | 629 bootstrapDependencies, |
| 629 executable, | 630 executable, |
| 630 arguments, | 631 arguments, |
| 631 environment); | 632 environment); |
| 632 return _getUniqueCommand(command); | 633 return _getUniqueCommand(command); |
| 633 } | 634 } |
| 634 | 635 |
| 635 AnalysisCommand getAnalysisCommand( | 636 AnalysisCommand getAnalysisCommand(String displayName, String executable, |
| 636 String displayName, executable, arguments, environmentOverrides, | 637 List<String> arguments, Map<String, String> environmentOverrides, |
| 637 {String flavor: 'dart2analyzer'}) { | 638 {String flavor: 'dart2analyzer'}) { |
| 638 var command = new AnalysisCommand._( | 639 var command = new AnalysisCommand._( |
| 639 flavor, displayName, executable, arguments, environmentOverrides); | 640 flavor, displayName, executable, arguments, environmentOverrides); |
| 640 return _getUniqueCommand(command); | 641 return _getUniqueCommand(command); |
| 641 } | 642 } |
| 642 | 643 |
| 643 VmCommand getVmCommand(String executable, List<String> arguments, | 644 VmCommand getVmCommand(String executable, List<String> arguments, |
| 644 Map<String, String> environmentOverrides) { | 645 Map<String, String> environmentOverrides) { |
| 645 var command = new VmCommand._(executable, arguments, environmentOverrides); | 646 var command = new VmCommand._(executable, arguments, environmentOverrides); |
| 646 return _getUniqueCommand(command); | 647 return _getUniqueCommand(command); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 659 String precompiledRunner, | 660 String precompiledRunner, |
| 660 String processTest, | 661 String processTest, |
| 661 String testDirectory, | 662 String testDirectory, |
| 662 List<String> arguments, | 663 List<String> arguments, |
| 663 bool useBlobs) { | 664 bool useBlobs) { |
| 664 var command = new AdbPrecompilationCommand._( | 665 var command = new AdbPrecompilationCommand._( |
| 665 precompiledRunner, processTest, testDirectory, arguments, useBlobs); | 666 precompiledRunner, processTest, testDirectory, arguments, useBlobs); |
| 666 return _getUniqueCommand(command); | 667 return _getUniqueCommand(command); |
| 667 } | 668 } |
| 668 | 669 |
| 669 Command getJSCommandlineCommand(String displayName, executable, arguments, | 670 Command getJSCommandlineCommand( |
| 670 [environment = null]) { | 671 String displayName, String executable, List<String> arguments, |
| 672 [Map<String, String> environment]) { |
| 671 var command = new JSCommandlineCommand._( | 673 var command = new JSCommandlineCommand._( |
| 672 displayName, executable, arguments, environment); | 674 displayName, executable, arguments, environment); |
| 673 return _getUniqueCommand(command); | 675 return _getUniqueCommand(command); |
| 674 } | 676 } |
| 675 | 677 |
| 676 Command getProcessCommand(String displayName, executable, arguments, | 678 Command getProcessCommand( |
| 677 [environment = null, workingDirectory = null]) { | 679 String displayName, String executable, List<String> arguments, |
| 680 [Map<String, String> environment, String workingDirectory]) { |
| 678 var command = new ProcessCommand._( | 681 var command = new ProcessCommand._( |
| 679 displayName, executable, arguments, environment, workingDirectory); | 682 displayName, executable, arguments, environment, workingDirectory); |
| 680 return _getUniqueCommand(command); | 683 return _getUniqueCommand(command); |
| 681 } | 684 } |
| 682 | 685 |
| 683 Command getCopyCommand(String sourceDirectory, String destinationDirectory) { | 686 Command getCopyCommand(String sourceDirectory, String destinationDirectory) { |
| 684 var command = | 687 var command = |
| 685 new CleanDirectoryCopyCommand._(sourceDirectory, destinationDirectory); | 688 new CleanDirectoryCopyCommand._(sourceDirectory, destinationDirectory); |
| 686 return _getUniqueCommand(command); | 689 return _getUniqueCommand(command); |
| 687 } | 690 } |
| 688 | 691 |
| 689 Command getPubCommand(String pubCommand, String pubExecutable, | 692 Command getPubCommand(String pubCommand, String pubExecutable, |
| 690 String pubspecYamlDirectory, String pubCacheDirectory, | 693 String pubspecYamlDirectory, String pubCacheDirectory, |
| 691 {List<String> arguments: const <String>[]}) { | 694 {List<String> arguments: const <String>[]}) { |
| 692 var command = new PubCommand._(pubCommand, pubExecutable, | 695 var command = new PubCommand._(pubCommand, pubExecutable, |
| 693 pubspecYamlDirectory, pubCacheDirectory, arguments); | 696 pubspecYamlDirectory, pubCacheDirectory, arguments); |
| 694 return _getUniqueCommand(command); | 697 return _getUniqueCommand(command); |
| 695 } | 698 } |
| 696 | 699 |
| 697 Command getMakeSymlinkCommand(String link, String target) { | 700 Command getMakeSymlinkCommand(String link, String target) { |
| 698 return _getUniqueCommand(new MakeSymlinkCommand._(link, target)); | 701 return _getUniqueCommand(new MakeSymlinkCommand._(link, target)); |
| 699 } | 702 } |
| 700 | 703 |
| 701 Command _getUniqueCommand(Command command) { | 704 T _getUniqueCommand<T extends Command>(T command) { |
| 702 // All Command classes implement hashCode and operator==. | 705 // All Command classes implement hashCode and operator==. |
| 703 // We check if this command has already been built. | 706 // We check if this command has already been built. |
| 704 // If so, we return the cached one. Otherwise we | 707 // If so, we return the cached one. Otherwise we |
| 705 // store the one given as [command] argument. | 708 // store the one given as [command] argument. |
| 706 if (_cleared) { | 709 if (_cleared) { |
| 707 throw new Exception( | 710 throw new Exception( |
| 708 "CommandBuilder.get[type]Command called after cache cleared"); | 711 "CommandBuilder.get[type]Command called after cache cleared"); |
| 709 } | 712 } |
| 710 var cachedCommand = _cachedCommands[command]; | 713 var cachedCommand = _cachedCommands[command]; |
| 711 if (cachedCommand != null) { | 714 if (cachedCommand != null) { |
| 712 return cachedCommand; | 715 return cachedCommand as T; |
| 713 } | 716 } |
| 714 _cachedCommands[command] = command; | 717 _cachedCommands[command] = command; |
| 715 return command; | 718 return command; |
| 716 } | 719 } |
| 717 } | 720 } |
| 718 | 721 |
| 719 /** | 722 /** |
| 720 * TestCase contains all the information needed to run a test and evaluate | 723 * TestCase contains all the information needed to run a test and evaluate |
| 721 * its output. Running a test involves starting a separate process, with | 724 * its output. Running a test involves starting a separate process, with |
| 722 * the executable and arguments given by the TestCase, and recording its | 725 * the executable and arguments given by the TestCase, and recording its |
| (...skipping 30 matching lines...) Expand all Loading... |
| 753 new Map<Command, CommandOutput>(); | 756 new Map<Command, CommandOutput>(); |
| 754 | 757 |
| 755 Map configuration; | 758 Map configuration; |
| 756 String displayName; | 759 String displayName; |
| 757 int _expectations = 0; | 760 int _expectations = 0; |
| 758 int hash = 0; | 761 int hash = 0; |
| 759 Set<Expectation> expectedOutcomes; | 762 Set<Expectation> expectedOutcomes; |
| 760 | 763 |
| 761 TestCase(this.displayName, this.commands, this.configuration, | 764 TestCase(this.displayName, this.commands, this.configuration, |
| 762 this.expectedOutcomes, | 765 this.expectedOutcomes, |
| 763 {isNegative: false, TestInformation info: null}) { | 766 {bool isNegative: false, TestInformation info}) { |
| 764 if (isNegative || displayName.contains("negative_test")) { | 767 if (isNegative || displayName.contains("negative_test")) { |
| 765 _expectations |= IS_NEGATIVE; | 768 _expectations |= IS_NEGATIVE; |
| 766 } | 769 } |
| 767 if (info != null) { | 770 if (info != null) { |
| 768 _setExpectations(info); | 771 _setExpectations(info); |
| 769 hash = | 772 hash = |
| 770 info.originTestPath.relativeTo(TestUtils.dartDir).toString().hashCode; | 773 info.originTestPath.relativeTo(TestUtils.dartDir).toString().hashCode; |
| 771 } | 774 } |
| 772 } | 775 } |
| 773 | 776 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 commands.length == commandOutputs.length); | 866 commands.length == commandOutputs.length); |
| 864 } | 867 } |
| 865 } | 868 } |
| 866 | 869 |
| 867 /** | 870 /** |
| 868 * BrowserTestCase has an extra compilation command that is run in a separate | 871 * BrowserTestCase has an extra compilation command that is run in a separate |
| 869 * process, before the regular test is run as in the base class [TestCase]. | 872 * process, before the regular test is run as in the base class [TestCase]. |
| 870 * If the compilation command fails, then the rest of the test is not run. | 873 * If the compilation command fails, then the rest of the test is not run. |
| 871 */ | 874 */ |
| 872 class BrowserTestCase extends TestCase { | 875 class BrowserTestCase extends TestCase { |
| 873 BrowserTestCase(displayName, commands, configuration, expectedOutcomes, info, | 876 BrowserTestCase( |
| 874 isNegative, this._testingUrl) | 877 String displayName, |
| 878 List<Command> commands, |
| 879 configuration, |
| 880 Set<Expectation> expectedOutcomes, |
| 881 TestInformation info, |
| 882 bool isNegative, |
| 883 this._testingUrl) |
| 875 : super(displayName, commands, configuration, expectedOutcomes, | 884 : super(displayName, commands, configuration, expectedOutcomes, |
| 876 isNegative: isNegative, info: info); | 885 isNegative: isNegative, info: info); |
| 877 | 886 |
| 878 String _testingUrl; | 887 String _testingUrl; |
| 879 | 888 |
| 880 String get testingUrl => _testingUrl; | 889 String get testingUrl => _testingUrl; |
| 881 } | 890 } |
| 882 | 891 |
| 883 class UnittestSuiteMessagesMixin { | 892 class UnittestSuiteMessagesMixin { |
| 884 bool _isAsyncTest(String testOutput) { | 893 bool _isAsyncTest(String testOutput) { |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1073 command.browser == "ie11") { | 1082 command.browser == "ie11") { |
| 1074 DebugLogger.warning("Timeout of ie11 on test page ${command.url}"); | 1083 DebugLogger.warning("Timeout of ie11 on test page ${command.url}"); |
| 1075 return true; | 1084 return true; |
| 1076 } | 1085 } |
| 1077 return false; | 1086 return false; |
| 1078 } | 1087 } |
| 1079 | 1088 |
| 1080 bool _infraFailure; | 1089 bool _infraFailure; |
| 1081 | 1090 |
| 1082 BrowserCommandOutputImpl( | 1091 BrowserCommandOutputImpl( |
| 1083 command, exitCode, timedOut, stdout, stderr, time, compilationSkipped) | 1092 Command command, |
| 1093 int exitCode, |
| 1094 bool timedOut, |
| 1095 List<int> stdout, |
| 1096 List<int> stderr, |
| 1097 Duration time, |
| 1098 bool compilationSkipped) |
| 1084 : _infraFailure = | 1099 : _infraFailure = |
| 1085 _failedBecauseOfFlakyInfrastructure(command, timedOut, stderr), | 1100 _failedBecauseOfFlakyInfrastructure(command, timedOut, stderr), |
| 1086 super(command, exitCode, timedOut, stdout, stderr, time, | 1101 super(command, exitCode, timedOut, stdout, stderr, time, |
| 1087 compilationSkipped, 0); | 1102 compilationSkipped, 0); |
| 1088 | 1103 |
| 1089 Expectation result(TestCase testCase) { | 1104 Expectation result(TestCase testCase) { |
| 1090 if (_infraFailure) { | 1105 if (_infraFailure) { |
| 1091 return Expectation.IGNORE; | 1106 return Expectation.IGNORE; |
| 1092 } | 1107 } |
| 1093 // Handle crashes and timeouts first | 1108 // Handle crashes and timeouts first |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 (!isWindows || exitCode != WHITELISTED_CONTENTSHELL_EXITCODE)); | 1195 (!isWindows || exitCode != WHITELISTED_CONTENTSHELL_EXITCODE)); |
| 1181 } | 1196 } |
| 1182 DebugLogger.warning("Couldn't find 'Content-Type: text/plain' in output. " | 1197 DebugLogger.warning("Couldn't find 'Content-Type: text/plain' in output. " |
| 1183 "($command)."); | 1198 "($command)."); |
| 1184 return true; | 1199 return true; |
| 1185 } | 1200 } |
| 1186 } | 1201 } |
| 1187 | 1202 |
| 1188 class HTMLBrowserCommandOutputImpl extends BrowserCommandOutputImpl { | 1203 class HTMLBrowserCommandOutputImpl extends BrowserCommandOutputImpl { |
| 1189 HTMLBrowserCommandOutputImpl( | 1204 HTMLBrowserCommandOutputImpl( |
| 1190 command, exitCode, timedOut, stdout, stderr, time, compilationSkipped) | 1205 Command command, |
| 1206 int exitCode, |
| 1207 bool timedOut, |
| 1208 List<int> stdout, |
| 1209 List<int> stderr, |
| 1210 Duration time, |
| 1211 bool compilationSkipped) |
| 1191 : super(command, exitCode, timedOut, stdout, stderr, time, | 1212 : super(command, exitCode, timedOut, stdout, stderr, time, |
| 1192 compilationSkipped); | 1213 compilationSkipped); |
| 1193 | 1214 |
| 1194 bool didFail(TestCase testCase) { | 1215 bool didFail(TestCase testCase) { |
| 1195 return _getOutcome() != Expectation.PASS; | 1216 return _getOutcome() != Expectation.PASS; |
| 1196 } | 1217 } |
| 1197 | 1218 |
| 1198 bool get _browserTestFailure { | 1219 bool get _browserTestFailure { |
| 1199 // We should not need to convert back and forward. | 1220 // We should not need to convert back and forward. |
| 1200 var output = decodeUtf8(super.stdout); | 1221 var output = decodeUtf8(super.stdout); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1222 BrowserTestJsonResult(this.outcome, this.htmlDom, this.events); | 1243 BrowserTestJsonResult(this.outcome, this.htmlDom, this.events); |
| 1223 | 1244 |
| 1224 static BrowserTestJsonResult parseFromString(String content) { | 1245 static BrowserTestJsonResult parseFromString(String content) { |
| 1225 void validate(String assertion, bool value) { | 1246 void validate(String assertion, bool value) { |
| 1226 if (!value) { | 1247 if (!value) { |
| 1227 throw "InvalidFormat sent from browser driving page: $assertion:\n\n" | 1248 throw "InvalidFormat sent from browser driving page: $assertion:\n\n" |
| 1228 "$content"; | 1249 "$content"; |
| 1229 } | 1250 } |
| 1230 } | 1251 } |
| 1231 | 1252 |
| 1232 var events; | |
| 1233 try { | 1253 try { |
| 1234 events = JSON.decode(content); | 1254 var events = JSON.decode(content); |
| 1235 if (events != null) { | 1255 if (events != null) { |
| 1236 validate("Message must be a List", events is List); | 1256 validate("Message must be a List", events is List); |
| 1237 | 1257 |
| 1238 Map<String, List<String>> messagesByType = {}; | 1258 Map<String, List<String>> messagesByType = {}; |
| 1239 ALLOWED_TYPES.forEach((type) => messagesByType[type] = <String>[]); | 1259 ALLOWED_TYPES.forEach((type) => messagesByType[type] = <String>[]); |
| 1240 | 1260 |
| 1241 for (var entry in events) { | 1261 for (var entry in events) { |
| 1242 validate("An entry must be a Map", entry is Map); | 1262 validate("An entry must be a Map", entry is Map); |
| 1243 | 1263 |
| 1244 var type = entry['type']; | 1264 var type = entry['type']; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1268 // If something goes wrong, we know the content was not in the correct | 1288 // If something goes wrong, we know the content was not in the correct |
| 1269 // JSON format. So we can't parse it. | 1289 // JSON format. So we can't parse it. |
| 1270 // The caller is responsible for falling back to the old way of | 1290 // The caller is responsible for falling back to the old way of |
| 1271 // determining if a test failed. | 1291 // determining if a test failed. |
| 1272 } | 1292 } |
| 1273 | 1293 |
| 1274 return null; | 1294 return null; |
| 1275 } | 1295 } |
| 1276 | 1296 |
| 1277 static Expectation _getOutcome(Map<String, List<String>> messagesByType) { | 1297 static Expectation _getOutcome(Map<String, List<String>> messagesByType) { |
| 1278 occured(type) => messagesByType[type].length > 0; | 1298 occured(String type) => messagesByType[type].length > 0; |
| 1279 searchForMsg(types, message) { | 1299 searchForMsg(List<String> types, String message) { |
| 1280 return types.any((type) => messagesByType[type].contains(message)); | 1300 return types.any((type) => messagesByType[type].contains(message)); |
| 1281 } | 1301 } |
| 1282 | 1302 |
| 1283 // FIXME(kustermann,ricow): I think this functionality doesn't work in | 1303 // FIXME(kustermann,ricow): I think this functionality doesn't work in |
| 1284 // test_controller.js: So far I haven't seen anything being reported on | 1304 // test_controller.js: So far I haven't seen anything being reported on |
| 1285 // "window.compilationerror" | 1305 // "window.compilationerror" |
| 1286 if (occured('window_compilationerror')) { | 1306 if (occured('window_compilationerror')) { |
| 1287 return Expectation.COMPILETIME_ERROR; | 1307 return Expectation.COMPILETIME_ERROR; |
| 1288 } | 1308 } |
| 1289 | 1309 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 | 1435 |
| 1416 class AnalysisCommandOutputImpl extends CommandOutputImpl { | 1436 class AnalysisCommandOutputImpl extends CommandOutputImpl { |
| 1417 // An error line has 8 fields that look like: | 1437 // An error line has 8 fields that look like: |
| 1418 // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source. | 1438 // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source. |
| 1419 final int ERROR_LEVEL = 0; | 1439 final int ERROR_LEVEL = 0; |
| 1420 final int ERROR_TYPE = 1; | 1440 final int ERROR_TYPE = 1; |
| 1421 final int FILENAME = 3; | 1441 final int FILENAME = 3; |
| 1422 final int FORMATTED_ERROR = 7; | 1442 final int FORMATTED_ERROR = 7; |
| 1423 | 1443 |
| 1424 AnalysisCommandOutputImpl( | 1444 AnalysisCommandOutputImpl( |
| 1425 command, exitCode, timedOut, stdout, stderr, time, compilationSkipped) | 1445 Command command, |
| 1446 int exitCode, |
| 1447 bool timedOut, |
| 1448 List<int> stdout, |
| 1449 List<int> stderr, |
| 1450 Duration time, |
| 1451 bool compilationSkipped) |
| 1426 : super(command, exitCode, timedOut, stdout, stderr, time, | 1452 : super(command, exitCode, timedOut, stdout, stderr, time, |
| 1427 compilationSkipped, 0); | 1453 compilationSkipped, 0); |
| 1428 | 1454 |
| 1429 Expectation result(TestCase testCase) { | 1455 Expectation result(TestCase testCase) { |
| 1430 // TODO(kustermann): If we run the analyzer not in batch mode, make sure | 1456 // TODO(kustermann): If we run the analyzer not in batch mode, make sure |
| 1431 // that command.exitCodes matches 2 (errors), 1 (warnings), 0 (no warnings, | 1457 // that command.exitCodes matches 2 (errors), 1 (warnings), 0 (no warnings, |
| 1432 // no errors) | 1458 // no errors) |
| 1433 | 1459 |
| 1434 // Handle crashes and timeouts first | 1460 // Handle crashes and timeouts first |
| 1435 if (hasCrashed) return Expectation.CRASH; | 1461 if (hasCrashed) return Expectation.CRASH; |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1841 head = null; | 1867 head = null; |
| 1842 tail = null; | 1868 tail = null; |
| 1843 _checkUtf8(complete); | 1869 _checkUtf8(complete); |
| 1844 } | 1870 } |
| 1845 return complete; | 1871 return complete; |
| 1846 } | 1872 } |
| 1847 } | 1873 } |
| 1848 | 1874 |
| 1849 // Helper to get a list of all child pids for a parent process. | 1875 // Helper to get a list of all child pids for a parent process. |
| 1850 // The first element of the list is the parent pid. | 1876 // The first element of the list is the parent pid. |
| 1851 Future<List<int>> _getPidList(pid, diagnostics) async { | 1877 Future<List<int>> _getPidList(int pid, List<String> diagnostics) async { |
| 1852 var pid_list = [pid]; | 1878 var pids = [pid]; |
| 1853 var lines; | 1879 List<String> lines; |
| 1854 var start_line = 0; | 1880 var startLine = 0; |
| 1855 if (io.Platform.isLinux || io.Platform.isMacOS) { | 1881 if (io.Platform.isLinux || io.Platform.isMacOS) { |
| 1856 var result = await io.Process | 1882 var result = |
| 1857 .run("pgrep", ["-P", "${pid_list[0]}"], runInShell: true); | 1883 await io.Process.run("pgrep", ["-P", "${pids[0]}"], runInShell: true); |
| 1858 lines = result.stdout.split('\n'); | 1884 lines = result.stdout.split('\n'); |
| 1859 } else if (io.Platform.isWindows) { | 1885 } else if (io.Platform.isWindows) { |
| 1860 var result = await io.Process.run( | 1886 var result = await io.Process.run( |
| 1861 "wmic", | 1887 "wmic", |
| 1862 [ | 1888 [ |
| 1863 "process", | 1889 "process", |
| 1864 "where", | 1890 "where", |
| 1865 "(ParentProcessId=${pid_list[0]})", | 1891 "(ParentProcessId=${pids[0]})", |
| 1866 "get", | 1892 "get", |
| 1867 "ProcessId" | 1893 "ProcessId" |
| 1868 ], | 1894 ], |
| 1869 runInShell: true); | 1895 runInShell: true); |
| 1870 lines = result.stdout.split('\n'); | 1896 lines = result.stdout.split('\n'); |
| 1871 // Skip first line containing header "ProcessId". | 1897 // Skip first line containing header "ProcessId". |
| 1872 start_line = 1; | 1898 startLine = 1; |
| 1873 } else { | 1899 } else { |
| 1874 assert(false); | 1900 assert(false); |
| 1875 } | 1901 } |
| 1876 if (lines.length > start_line) { | 1902 if (lines.length > startLine) { |
| 1877 for (int i = start_line; i < lines.length; ++i) { | 1903 for (var i = startLine; i < lines.length; ++i) { |
| 1878 var pid = int.parse(lines[i], onError: (source) => null); | 1904 var pid = int.parse(lines[i], onError: (source) => null); |
| 1879 if (pid != null) pid_list.add(pid); | 1905 if (pid != null) pids.add(pid); |
| 1880 } | 1906 } |
| 1881 } else { | 1907 } else { |
| 1882 diagnostics.add("Could not find child pids"); | 1908 diagnostics.add("Could not find child pids"); |
| 1883 diagnostics.addAll(lines); | 1909 diagnostics.addAll(lines); |
| 1884 } | 1910 } |
| 1885 return pid_list; | 1911 return pids; |
| 1886 } | 1912 } |
| 1887 | 1913 |
| 1888 /** | 1914 /** |
| 1889 * A RunningProcess actually runs a test, getting the command lines from | 1915 * A RunningProcess actually runs a test, getting the command lines from |
| 1890 * its [TestCase], starting the test process (and first, a compilation | 1916 * its [TestCase], starting the test process (and first, a compilation |
| 1891 * process if the TestCase is a [BrowserTestCase]), creating a timeout | 1917 * process if the TestCase is a [BrowserTestCase]), creating a timeout |
| 1892 * timer, and recording the results in a new [CommandOutput] object, which it | 1918 * timer, and recording the results in a new [CommandOutput] object, which it |
| 1893 * attaches to the TestCase. The lifetime of the RunningProcess is limited | 1919 * attaches to the TestCase. The lifetime of the RunningProcess is limited |
| 1894 * to the time it takes to start the process, run the process, and record | 1920 * to the time it takes to start the process, run the process, and record |
| 1895 * the result; there are no pointers to it, so it should be available to | 1921 * the result; there are no pointers to it, so it should be available to |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1928 var args = command.arguments; | 1954 var args = command.arguments; |
| 1929 Future processFuture = io.Process.start(command.executable, args, | 1955 Future processFuture = io.Process.start(command.executable, args, |
| 1930 environment: processEnvironment, | 1956 environment: processEnvironment, |
| 1931 workingDirectory: command.workingDirectory); | 1957 workingDirectory: command.workingDirectory); |
| 1932 processFuture.then((io.Process process) { | 1958 processFuture.then((io.Process process) { |
| 1933 StreamSubscription stdoutSubscription = | 1959 StreamSubscription stdoutSubscription = |
| 1934 _drainStream(process.stdout, stdout); | 1960 _drainStream(process.stdout, stdout); |
| 1935 StreamSubscription stderrSubscription = | 1961 StreamSubscription stderrSubscription = |
| 1936 _drainStream(process.stderr, stderr); | 1962 _drainStream(process.stderr, stderr); |
| 1937 | 1963 |
| 1938 var stdoutCompleter = new Completer(); | 1964 var stdoutCompleter = new Completer<Null>(); |
| 1939 var stderrCompleter = new Completer(); | 1965 var stderrCompleter = new Completer<Null>(); |
| 1940 | 1966 |
| 1941 bool stdoutDone = false; | 1967 bool stdoutDone = false; |
| 1942 bool stderrDone = false; | 1968 bool stderrDone = false; |
| 1943 pid = process.pid; | 1969 pid = process.pid; |
| 1944 | 1970 |
| 1945 // This timer is used to close stdio to the subprocess once we got | 1971 // This timer is used to close stdio to the subprocess once we got |
| 1946 // the exitCode. Sometimes descendants of the subprocess keep stdio | 1972 // the exitCode. Sometimes descendants of the subprocess keep stdio |
| 1947 // handles alive even though the direct subprocess is dead. | 1973 // handles alive even though the direct subprocess is dead. |
| 1948 Timer watchdogTimer; | 1974 Timer watchdogTimer; |
| 1949 | 1975 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1966 watchdogTimer.cancel(); | 1992 watchdogTimer.cancel(); |
| 1967 } | 1993 } |
| 1968 } | 1994 } |
| 1969 } | 1995 } |
| 1970 | 1996 |
| 1971 // Close stdin so that tests that try to block on input will fail. | 1997 // Close stdin so that tests that try to block on input will fail. |
| 1972 process.stdin.close(); | 1998 process.stdin.close(); |
| 1973 timeoutHandler() async { | 1999 timeoutHandler() async { |
| 1974 timedOut = true; | 2000 timedOut = true; |
| 1975 if (process != null) { | 2001 if (process != null) { |
| 1976 var executable; | 2002 String executable; |
| 1977 if (io.Platform.isLinux) { | 2003 if (io.Platform.isLinux) { |
| 1978 executable = 'eu-stack'; | 2004 executable = 'eu-stack'; |
| 1979 } else if (io.Platform.isMacOS) { | 2005 } else if (io.Platform.isMacOS) { |
| 1980 // Try to print stack traces of the timed out process. | 2006 // Try to print stack traces of the timed out process. |
| 1981 // `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 |
| 1982 // 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 |
| 1983 // sample the threads once. | 2009 // sample the threads once. |
| 1984 executable = '/usr/bin/sample'; | 2010 executable = '/usr/bin/sample'; |
| 1985 } else if (io.Platform.isWindows) { | 2011 } else if (io.Platform.isWindows) { |
| 1986 bool is_x64 = command.executable.contains("X64") || | 2012 bool is_x64 = command.executable.contains("X64") || |
| 1987 command.executable.contains("SIMARM64"); | 2013 command.executable.contains("SIMARM64"); |
| 1988 var win_sdk_path = configuration['win_sdk_path']; | 2014 var winSdkPath = configuration['win_sdk_path']; |
| 1989 if (win_sdk_path != null) { | 2015 if (winSdkPath != null) { |
| 1990 executable = win_sdk_path + | 2016 executable = winSdkPath + |
| 1991 "\\Debuggers\\" + | 2017 "\\Debuggers\\" + |
| 1992 (is_x64 ? "x64" : "x86") + | 2018 (is_x64 ? "x64" : "x86") + |
| 1993 "\\cdb.exe"; | 2019 "\\cdb.exe"; |
| 1994 diagnostics.add("Using $executable to print stack traces"); | 2020 diagnostics.add("Using $executable to print stack traces"); |
| 1995 } else { | 2021 } else { |
| 1996 diagnostics.add("win_sdk path not found"); | 2022 diagnostics.add("win_sdk path not found"); |
| 1997 } | 2023 } |
| 1998 } else { | 2024 } else { |
| 1999 diagnostics.add("Capturing stack traces on" | 2025 diagnostics.add("Capturing stack traces on" |
| 2000 "${io.Platform.operatingSystem} not supported"); | 2026 "${io.Platform.operatingSystem} not supported"); |
| 2001 } | 2027 } |
| 2002 if (executable != null) { | 2028 if (executable != null) { |
| 2003 var pid_list = await _getPidList(process.pid, diagnostics); | 2029 var pids = await _getPidList(process.pid, diagnostics); |
| 2004 diagnostics.add("Process list including children: $pid_list"); | 2030 diagnostics.add("Process list including children: $pids"); |
| 2005 for (pid in pid_list) { | 2031 for (pid in pids) { |
| 2006 var arguments; | 2032 List<String> arguments; |
| 2007 if (io.Platform.isLinux) { | 2033 if (io.Platform.isLinux) { |
| 2008 arguments = ['-p $pid']; | 2034 arguments = ['-p $pid']; |
| 2009 } else if (io.Platform.isMacOS) { | 2035 } else if (io.Platform.isMacOS) { |
| 2010 arguments = ['$pid', '1', '4000', '-mayDie']; | 2036 arguments = ['$pid', '1', '4000', '-mayDie']; |
| 2011 } else if (io.Platform.isWindows) { | 2037 } else if (io.Platform.isWindows) { |
| 2012 arguments = ['-p', '$pid', '-c', '!uniqstack;qd']; | 2038 arguments = ['-p', '$pid', '-c', '!uniqstack;qd']; |
| 2013 } else { | 2039 } else { |
| 2014 assert(false); | 2040 assert(false); |
| 2015 } | 2041 } |
| 2016 diagnostics.add("Trying to capture stack trace for pid $pid"); | 2042 diagnostics.add("Trying to capture stack trace for pid $pid"); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2122 } | 2148 } |
| 2123 } | 2149 } |
| 2124 | 2150 |
| 2125 class BatchRunnerProcess { | 2151 class BatchRunnerProcess { |
| 2126 Completer<CommandOutput> _completer; | 2152 Completer<CommandOutput> _completer; |
| 2127 ProcessCommand _command; | 2153 ProcessCommand _command; |
| 2128 List<String> _arguments; | 2154 List<String> _arguments; |
| 2129 String _runnerType; | 2155 String _runnerType; |
| 2130 | 2156 |
| 2131 io.Process _process; | 2157 io.Process _process; |
| 2132 Map _processEnvironmentOverrides; | 2158 Map<String, String> _processEnvironmentOverrides; |
| 2133 Completer _stdoutCompleter; | 2159 Completer<Null> _stdoutCompleter; |
| 2134 Completer _stderrCompleter; | 2160 Completer<Null> _stderrCompleter; |
| 2135 StreamSubscription<String> _stdoutSubscription; | 2161 StreamSubscription<String> _stdoutSubscription; |
| 2136 StreamSubscription<String> _stderrSubscription; | 2162 StreamSubscription<String> _stderrSubscription; |
| 2137 Function _processExitHandler; | 2163 Function _processExitHandler; |
| 2138 | 2164 |
| 2139 bool _currentlyRunning = false; | 2165 bool _currentlyRunning = false; |
| 2140 OutputLog _testStdout; | 2166 OutputLog _testStdout; |
| 2141 OutputLog _testStderr; | 2167 OutputLog _testStderr; |
| 2142 String _status; | 2168 String _status; |
| 2143 DateTime _startTime; | 2169 DateTime _startTime; |
| 2144 Timer _timer; | 2170 Timer _timer; |
| 2145 | 2171 |
| 2146 Future<CommandOutput> runCommand(String runnerType, ProcessCommand command, | 2172 Future<CommandOutput> runCommand(String runnerType, ProcessCommand command, |
| 2147 int timeout, List<String> arguments) { | 2173 int timeout, List<String> arguments) { |
| 2148 assert(_completer == null); | 2174 assert(_completer == null); |
| 2149 assert(!_currentlyRunning); | 2175 assert(!_currentlyRunning); |
| 2150 | 2176 |
| 2151 _completer = new Completer<CommandOutput>(); | 2177 _completer = new Completer(); |
| 2152 bool sameRunnerType = _runnerType == runnerType && | 2178 bool sameRunnerType = _runnerType == runnerType && |
| 2153 _dictEquals(_processEnvironmentOverrides, command.environmentOverrides); | 2179 _dictEquals(_processEnvironmentOverrides, command.environmentOverrides); |
| 2154 _runnerType = runnerType; | 2180 _runnerType = runnerType; |
| 2155 _currentlyRunning = true; | 2181 _currentlyRunning = true; |
| 2156 _command = command; | 2182 _command = command; |
| 2157 _arguments = arguments; | 2183 _arguments = arguments; |
| 2158 _processEnvironmentOverrides = command.environmentOverrides; | 2184 _processEnvironmentOverrides = command.environmentOverrides; |
| 2159 | 2185 |
| 2160 if (_process == null) { | 2186 if (_process == null) { |
| 2161 // Start process if not yet started. | 2187 // Start process if not yet started. |
| 2162 _startProcess(() { | 2188 _startProcess(() { |
| 2163 doStartTest(command, timeout); | 2189 doStartTest(command, timeout); |
| 2164 }); | 2190 }); |
| 2165 } else if (!sameRunnerType) { | 2191 } else if (!sameRunnerType) { |
| 2166 // Restart this runner with the right executable for this test if needed. | 2192 // Restart this runner with the right executable for this test if needed. |
| 2167 _processExitHandler = (_) { | 2193 _processExitHandler = (_) { |
| 2168 _startProcess(() { | 2194 _startProcess(() { |
| 2169 doStartTest(command, timeout); | 2195 doStartTest(command, timeout); |
| 2170 }); | 2196 }); |
| 2171 }; | 2197 }; |
| 2172 _process.kill(); | 2198 _process.kill(); |
| 2173 _stdoutSubscription.cancel(); | 2199 _stdoutSubscription.cancel(); |
| 2174 _stderrSubscription.cancel(); | 2200 _stderrSubscription.cancel(); |
| 2175 } else { | 2201 } else { |
| 2176 doStartTest(command, timeout); | 2202 doStartTest(command, timeout); |
| 2177 } | 2203 } |
| 2178 return _completer.future; | 2204 return _completer.future; |
| 2179 } | 2205 } |
| 2180 | 2206 |
| 2181 Future terminate() { | 2207 Future<bool> terminate() { |
| 2182 if (_process == null) return new Future.value(true); | 2208 if (_process == null) return new Future.value(true); |
| 2183 Completer terminateCompleter = new Completer(); | 2209 Completer terminateCompleter = new Completer<bool>(); |
| 2184 _processExitHandler = (_) { | 2210 _processExitHandler = (_) { |
| 2185 terminateCompleter.complete(true); | 2211 terminateCompleter.complete(true); |
| 2186 }; | 2212 }; |
| 2187 _process.kill(); | 2213 _process.kill(); |
| 2188 _stdoutSubscription.cancel(); | 2214 _stdoutSubscription.cancel(); |
| 2189 _stderrSubscription.cancel(); | 2215 _stderrSubscription.cancel(); |
| 2190 | 2216 |
| 2191 return terminateCompleter.future; | 2217 return terminateCompleter.future; |
| 2192 } | 2218 } |
| 2193 | 2219 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2249 } | 2275 } |
| 2250 | 2276 |
| 2251 return handler; | 2277 return handler; |
| 2252 } | 2278 } |
| 2253 | 2279 |
| 2254 void _timeoutHandler() { | 2280 void _timeoutHandler() { |
| 2255 _processExitHandler = makeExitHandler(">>> TEST TIMEOUT"); | 2281 _processExitHandler = makeExitHandler(">>> TEST TIMEOUT"); |
| 2256 _process.kill(); | 2282 _process.kill(); |
| 2257 } | 2283 } |
| 2258 | 2284 |
| 2259 _startProcess(callback) { | 2285 void _startProcess(Action callback) { |
| 2260 assert(_command is ProcessCommand); | 2286 assert(_command is ProcessCommand); |
| 2261 var executable = _command.executable; | 2287 var executable = _command.executable; |
| 2262 var arguments = _command.batchArguments.toList(); | 2288 var arguments = _command.batchArguments.toList(); |
| 2263 arguments.add('--batch'); | 2289 arguments.add('--batch'); |
| 2264 var environment = new Map.from(io.Platform.environment); | 2290 var environment = new Map.from(io.Platform.environment); |
| 2265 if (_processEnvironmentOverrides != null) { | 2291 if (_processEnvironmentOverrides != null) { |
| 2266 for (var key in _processEnvironmentOverrides.keys) { | 2292 for (var key in _processEnvironmentOverrides.keys) { |
| 2267 environment[key] = _processEnvironmentOverrides[key]; | 2293 environment[key] = _processEnvironmentOverrides[key]; |
| 2268 } | 2294 } |
| 2269 } | 2295 } |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2507 | 2533 |
| 2508 CommandQueue(this.graph, this.enqueuer, this.executor, this._maxProcesses, | 2534 CommandQueue(this.graph, this.enqueuer, this.executor, this._maxProcesses, |
| 2509 this._maxBrowserProcesses, this._verbose) { | 2535 this._maxBrowserProcesses, this._verbose) { |
| 2510 var eventCondition = graph.events.where; | 2536 var eventCondition = graph.events.where; |
| 2511 eventCondition((e) => e is dgraph.StateChangedEvent).listen((e) { | 2537 eventCondition((e) => e is dgraph.StateChangedEvent).listen((e) { |
| 2512 var event = e as dgraph.StateChangedEvent; | 2538 var event = e as dgraph.StateChangedEvent; |
| 2513 if (event.to == dgraph.NodeState.Enqueuing) { | 2539 if (event.to == dgraph.NodeState.Enqueuing) { |
| 2514 assert(event.from == dgraph.NodeState.Initialized || | 2540 assert(event.from == dgraph.NodeState.Initialized || |
| 2515 event.from == dgraph.NodeState.Waiting); | 2541 event.from == dgraph.NodeState.Waiting); |
| 2516 graph.changeState(event.node, dgraph.NodeState.Processing); | 2542 graph.changeState(event.node, dgraph.NodeState.Processing); |
| 2517 var command = event.node.userData; | 2543 var command = event.node.userData as Command; |
| 2518 if (event.node.dependencies.length > 0) { | 2544 if (event.node.dependencies.length > 0) { |
| 2519 _runQueue.addFirst(command); | 2545 _runQueue.addFirst(command); |
| 2520 } else { | 2546 } else { |
| 2521 _runQueue.add(command); | 2547 _runQueue.add(command); |
| 2522 } | 2548 } |
| 2523 Timer.run(() => _tryRunNextCommand()); | 2549 Timer.run(() => _tryRunNextCommand()); |
| 2524 } | 2550 } |
| 2525 }); | 2551 }); |
| 2526 // We're finished if the graph is sealed and all nodes are in a finished | 2552 // We're finished if the graph is sealed and all nodes are in a finished |
| 2527 // state (Successful, Failed or UnableToRun). | 2553 // state (Successful, Failed or UnableToRun). |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2725 return adbDevicePool.acquireDevice().then((AdbDevice device) { | 2751 return adbDevicePool.acquireDevice().then((AdbDevice device) { |
| 2726 return _runAdbPrecompilationCommand(device, command, timeout) | 2752 return _runAdbPrecompilationCommand(device, command, timeout) |
| 2727 .whenComplete(() { | 2753 .whenComplete(() { |
| 2728 adbDevicePool.releaseDevice(device); | 2754 adbDevicePool.releaseDevice(device); |
| 2729 }); | 2755 }); |
| 2730 }); | 2756 }); |
| 2731 } else if (command is VmBatchCommand) { | 2757 } else if (command is VmBatchCommand) { |
| 2732 var name = command.displayName; | 2758 var name = command.displayName; |
| 2733 return _getBatchRunner(command.displayName + command.dartFile) | 2759 return _getBatchRunner(command.displayName + command.dartFile) |
| 2734 .runCommand(name, command, timeout, command.arguments); | 2760 .runCommand(name, command, timeout, command.arguments); |
| 2735 } else { | 2761 } else if (command is ProcessCommand) { |
| 2736 return new RunningProcess(command, timeout, | 2762 return new RunningProcess(command, timeout, |
| 2737 configuration: globalConfiguration) | 2763 configuration: globalConfiguration) |
| 2738 .run(); | 2764 .run(); |
| 2765 } else { |
| 2766 throw new ArgumentError("Unknown command type ${command.runtimeType}."); |
| 2739 } | 2767 } |
| 2740 } | 2768 } |
| 2741 | 2769 |
| 2742 Future<CommandOutput> _runAdbPrecompilationCommand( | 2770 Future<CommandOutput> _runAdbPrecompilationCommand( |
| 2743 AdbDevice device, AdbPrecompilationCommand command, int timeout) async { | 2771 AdbDevice device, AdbPrecompilationCommand command, int timeout) async { |
| 2744 var runner = command.precompiledRunnerFilename; | 2772 var runner = command.precompiledRunnerFilename; |
| 2745 var processTest = command.processTestFilename; | 2773 var processTest = command.processTestFilename; |
| 2746 var testdir = command.precompiledTestDirectory; | 2774 var testdir = command.precompiledTestDirectory; |
| 2747 var arguments = command.arguments; | 2775 var arguments = command.arguments; |
| 2748 var devicedir = DartPrecompiledAdbRuntimeConfiguration.DeviceDir; | 2776 var devicedir = DartPrecompiledAdbRuntimeConfiguration.DeviceDir; |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3072 } | 3100 } |
| 3073 } | 3101 } |
| 3074 | 3102 |
| 3075 class ProcessQueue { | 3103 class ProcessQueue { |
| 3076 Map _globalConfiguration; | 3104 Map _globalConfiguration; |
| 3077 | 3105 |
| 3078 Function _allDone; | 3106 Function _allDone; |
| 3079 final dgraph.Graph _graph = new dgraph.Graph(); | 3107 final dgraph.Graph _graph = new dgraph.Graph(); |
| 3080 List<EventListener> _eventListener; | 3108 List<EventListener> _eventListener; |
| 3081 | 3109 |
| 3082 ProcessQueue(this._globalConfiguration, maxProcesses, maxBrowserProcesses, | 3110 ProcessQueue( |
| 3083 DateTime startTime, testSuites, this._eventListener, this._allDone, | 3111 this._globalConfiguration, |
| 3112 int maxProcesses, |
| 3113 int maxBrowserProcesses, |
| 3114 DateTime startTime, |
| 3115 List<TestSuite> testSuites, |
| 3116 this._eventListener, |
| 3117 this._allDone, |
| 3084 [bool verbose = false, | 3118 [bool verbose = false, |
| 3085 String recordingOutputFile, | 3119 String recordingOutputFile, |
| 3086 String recordedInputFile, | 3120 String recordedInputFile, |
| 3087 AdbDevicePool adbDevicePool]) { | 3121 AdbDevicePool adbDevicePool]) { |
| 3088 void setupForListing(TestCaseEnqueuer testCaseEnqueuer) { | 3122 void setupForListing(TestCaseEnqueuer testCaseEnqueuer) { |
| 3089 _graph.events | 3123 _graph.events |
| 3090 .where((event) => event is dgraph.GraphSealedEvent) | 3124 .where((event) => event is dgraph.GraphSealedEvent) |
| 3091 .listen((_) { | 3125 .listen((_) { |
| 3092 var testCases = new List.from(testCaseEnqueuer.remainingTestCases); | 3126 var testCases = testCaseEnqueuer.remainingTestCases.toList(); |
| 3093 testCases.sort((a, b) => a.displayName.compareTo(b.displayName)); | 3127 testCases.sort((a, b) => a.displayName.compareTo(b.displayName)); |
| 3094 | 3128 |
| 3095 print("\nGenerating all matching test cases ....\n"); | 3129 print("\nGenerating all matching test cases ....\n"); |
| 3096 | 3130 |
| 3097 for (TestCase testCase in testCases) { | 3131 for (TestCase testCase in testCases) { |
| 3098 eventFinishedTestCase(testCase); | 3132 eventFinishedTestCase(testCase); |
| 3099 print("${testCase.displayName} " | 3133 print("${testCase.displayName} " |
| 3100 "Expectations: ${testCase.expectedOutcomes.join(', ')} " | 3134 "Expectations: ${testCase.expectedOutcomes.join(', ')} " |
| 3101 "Configuration: '${testCase.configurationString}'"); | 3135 "Configuration: '${testCase.configurationString}'"); |
| 3102 } | 3136 } |
| 3103 eventAllTestsKnown(); | 3137 eventAllTestsKnown(); |
| 3104 }); | 3138 }); |
| 3105 } | 3139 } |
| 3106 | 3140 |
| 3107 var testCaseEnqueuer; | 3141 TestCaseEnqueuer testCaseEnqueuer; |
| 3108 CommandQueue commandQueue; | 3142 CommandQueue commandQueue; |
| 3109 | 3143 |
| 3110 void setupForRunning(TestCaseEnqueuer testCaseEnqueuer) { | 3144 void setupForRunning(TestCaseEnqueuer testCaseEnqueuer) { |
| 3111 Timer _debugTimer; | 3145 Timer _debugTimer; |
| 3112 // If we haven't seen a single test finishing during a 10 minute period | 3146 // If we haven't seen a single test finishing during a 10 minute period |
| 3113 // something is definitely wrong, so we dump the debugging information. | 3147 // something is definitely wrong, so we dump the debugging information. |
| 3114 final debugTimerDuration = const Duration(minutes: 10); | 3148 final debugTimerDuration = const Duration(minutes: 10); |
| 3115 | 3149 |
| 3116 void cancelDebugTimer() { | 3150 void cancelDebugTimer() { |
| 3117 if (_debugTimer != null) { | 3151 if (_debugTimer != null) { |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3255 } | 3289 } |
| 3256 } | 3290 } |
| 3257 | 3291 |
| 3258 void eventAllTestsDone() { | 3292 void eventAllTestsDone() { |
| 3259 for (var listener in _eventListener) { | 3293 for (var listener in _eventListener) { |
| 3260 listener.allDone(); | 3294 listener.allDone(); |
| 3261 } | 3295 } |
| 3262 _allDone(); | 3296 _allDone(); |
| 3263 } | 3297 } |
| 3264 } | 3298 } |
| OLD | NEW |