Chromium Code Reviews| 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 #library("test_runner"); |
| 13 | 13 |
| 14 #import("dart:io"); | 14 #import("dart:io"); |
| 15 #import("dart:isolate"); | 15 #import("dart:isolate"); |
| 16 #import("status_file_parser.dart"); | 16 #import("status_file_parser.dart"); |
| 17 #import("test_progress.dart"); | 17 #import("test_progress.dart"); |
| 18 #import("test_suite.dart"); | 18 #import("test_suite.dart"); |
| 19 | 19 |
| 20 const int NO_TIMEOUT = 0; | 20 const int NO_TIMEOUT = 0; |
| 21 const int SLOW_TIMEOUT_MULTIPLIER = 4; | 21 const int SLOW_TIMEOUT_MULTIPLIER = 4; |
| 22 | 22 |
| 23 typedef void TestCaseEvent(TestCase testCase); | 23 typedef void TestCaseEvent(TestCase testCase); |
| 24 typedef void ExitCodeEvent(int exitCode); | 24 typedef void ExitCodeEvent(int exitCode); |
| 25 typedef bool EnqueueMoreWork(ProcessQueue queue); | 25 typedef void EnqueueMoreWork(ProcessQueue queue); |
| 26 | 26 |
| 27 /** A command executed as a step in a test case. */ | 27 /** A command executed as a step in a test case. */ |
| 28 class Command { | 28 class Command { |
| 29 /** Path to the executable of this command. */ | 29 /** Path to the executable of this command. */ |
| 30 String executable; | 30 String executable; |
| 31 | 31 |
| 32 /** Command line arguments to the executable. */ | 32 /** Command line arguments to the executable. */ |
| 33 List<String> arguments; | 33 List<String> arguments; |
| 34 | 34 |
| 35 /** The actual command line that will be executed. */ | 35 /** The actual command line that will be executed. */ |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 602 } | 602 } |
| 603 } | 603 } |
| 604 | 604 |
| 605 /** | 605 /** |
| 606 * Process exit handler called at the end of every command. It internally | 606 * Process exit handler called at the end of every command. It internally |
| 607 * treats all but the last command as compilation steps. The last command is | 607 * treats all but the last command as compilation steps. The last command is |
| 608 * the actual test and its output is analyzed in [testComplete]. | 608 * the actual test and its output is analyzed in [testComplete]. |
| 609 */ | 609 */ |
| 610 void stepExitHandler(int exitCode) { | 610 void stepExitHandler(int exitCode) { |
| 611 process.close(); | 611 process.close(); |
| 612 process = null; | |
| 612 int totalSteps = testCase.commands.length; | 613 int totalSteps = testCase.commands.length; |
| 613 String suffix =' (step $currentStep of $totalSteps)'; | 614 String suffix =' (step $currentStep of $totalSteps)'; |
| 614 if (currentStep == totalSteps) { // done with test command | 615 if (timedOut) { |
| 616 // Test timed out before it could complete. | |
| 617 testComplete(0, true); | |
| 618 } else if (currentStep == totalSteps) { | |
| 619 // Done with all test commands. | |
| 615 testComplete(exitCode, false); | 620 testComplete(exitCode, false); |
| 616 } else if (exitCode != 0) { | 621 } else if (exitCode != 0) { |
| 622 // One of the steps failed. | |
| 617 stderr.add('test.dart: Compilation failed$suffix, exit code $exitCode\n'); | 623 stderr.add('test.dart: Compilation failed$suffix, exit code $exitCode\n'); |
| 618 testComplete(exitCode, true); | 624 testComplete(exitCode, true); |
| 619 } else { | 625 } else { |
| 626 // One compilation step successfully completed, move on to the | |
| 627 // next step. | |
| 620 stderr.add('test.dart: Compilation finished $suffix\n'); | 628 stderr.add('test.dart: Compilation finished $suffix\n'); |
| 621 stdout.add('test.dart: Compilation finished $suffix\n'); | 629 stdout.add('test.dart: Compilation finished $suffix\n'); |
| 622 if (currentStep == totalSteps - 1 && testCase.usesWebDriver && | 630 if (currentStep == totalSteps - 1 && testCase.usesWebDriver && |
| 623 !testCase.configuration['noBatch']) { | 631 !testCase.configuration['noBatch']) { |
| 624 // Note: processQueue will always be non-null for runtime == ie, ff, | 632 // Note: processQueue will always be non-null for runtime == ie, ff, |
| 625 // safari, chrome, opera. (It is only null for runtime == vm) | 633 // safari, chrome, opera. (It is only null for runtime == vm) |
| 626 // This RunningProcess object is done, and hands over control to | 634 // This RunningProcess object is done, and hands over control to |
| 627 // BatchRunner.startTest(), which handles reporting, etc. | 635 // BatchRunner.startTest(), which handles reporting, etc. |
| 628 timeoutTimer.cancel(); | 636 timeoutTimer.cancel(); |
| 629 processQueue._getBatchRunner(testCase).startTest(testCase); | 637 processQueue._getBatchRunner(testCase).startTest(testCase); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 649 void start() { | 657 void start() { |
| 650 Expect.isFalse(testCase.expectedOutcomes.contains(SKIP)); | 658 Expect.isFalse(testCase.expectedOutcomes.contains(SKIP)); |
| 651 stdout = new List<String>(); | 659 stdout = new List<String>(); |
| 652 stderr = new List<String>(); | 660 stderr = new List<String>(); |
| 653 currentStep = 0; | 661 currentStep = 0; |
| 654 startTime = new Date.now(); | 662 startTime = new Date.now(); |
| 655 runCommand(testCase.commands[currentStep++], stepExitHandler); | 663 runCommand(testCase.commands[currentStep++], stepExitHandler); |
| 656 } | 664 } |
| 657 | 665 |
| 658 void runCommand(Command command, void exitHandler(int exitCode)) { | 666 void runCommand(Command command, void exitHandler(int exitCode)) { |
| 659 process = Process.start(command.executable, command.arguments); | 667 void processErrorHandler(e) { |
| 660 process.onExit = exitHandler; | 668 print("Process error:"); |
| 661 process.onError = (e) { | |
| 662 print("Error starting process:"); | |
| 663 print(" Command: $command"); | 669 print(" Command: $command"); |
| 664 print(" Error: $e"); | 670 print(" Error: $e"); |
| 665 testComplete(-1, false); | 671 testComplete(-1, false); |
| 666 }; | |
| 667 InputStream stdoutStream = process.stdout; | |
| 668 InputStream stderrStream = process.stderr; | |
| 669 StringInputStream stdoutStringStream = new StringInputStream(stdoutStream); | |
| 670 StringInputStream stderrStringStream = new StringInputStream(stderrStream); | |
| 671 stdoutStringStream.onLine = | |
| 672 makeReadHandler(stdoutStringStream, stdout); | |
| 673 stderrStringStream.onLine = | |
| 674 makeReadHandler(stderrStringStream, stderr); | |
| 675 if (timeoutTimer == null) { | |
| 676 // Create one timeout timer when starting test case, remove it at end. | |
| 677 timeoutTimer = new Timer(1000 * testCase.timeout, timeoutHandler); | |
| 678 } | 672 } |
| 673 Future processFuture = Process.start(command.executable, command.arguments); | |
|
ahe
2012/10/11 18:39:50
Consider using cascading here.
Mads Ager (google)
2012/10/12 08:44:46
I did and for this code I found it too confusing b
| |
| 674 processFuture.then((p) { | |
| 675 process = p; | |
| 676 process.onExit = exitHandler; | |
| 677 process.onError = processErrorHandler; | |
| 678 InputStream stdoutStream = process.stdout; | |
| 679 InputStream stderrStream = process.stderr; | |
| 680 StringInputStream stdoutStringStream = | |
| 681 new StringInputStream(stdoutStream); | |
|
Emily Fortuna
2012/10/11 18:23:08
consider:
var stdoutStringStream = new StringInput
Mads Ager (google)
2012/10/12 08:44:46
Agreed! I kept it as it was but I will be more tha
| |
| 682 StringInputStream stderrStringStream = | |
| 683 new StringInputStream(stderrStream); | |
| 684 stdoutStringStream.onLine = | |
| 685 makeReadHandler(stdoutStringStream, stdout); | |
| 686 stderrStringStream.onLine = | |
| 687 makeReadHandler(stderrStringStream, stderr); | |
| 688 if (timeoutTimer == null) { | |
| 689 // Create one timeout timer when starting test case, remove it at end. | |
| 690 timeoutTimer = new Timer(1000 * testCase.timeout, timeoutHandler); | |
| 691 } | |
| 692 // If the timeout fired in between two commands, kill the just | |
| 693 // started process immediately. | |
| 694 if (timedOut) process.kill(); | |
|
ricow1
2012/10/11 17:27:34
Why not just do p.kill() at the start of this clos
Mads Ager (google)
2012/10/12 08:44:46
Because we need the exit handler set up so that we
| |
| 695 }); | |
| 696 processFuture.handleException((e) { | |
|
ahe
2012/10/11 18:39:50
Shouldn't this API be the same as process.onError
Mads Ager (google)
2012/10/12 08:44:46
That would be nice, yes. I'll eliminate onError on
| |
| 697 processErrorHandler(e); | |
| 698 return true; | |
| 699 }); | |
| 679 } | 700 } |
| 680 | 701 |
| 681 void timeoutHandler(Timer unusedTimer) { | 702 void timeoutHandler(Timer unusedTimer) { |
| 682 timedOut = true; | 703 timedOut = true; |
| 683 process.kill(); | 704 if (process != null) process.kill(); |
| 684 } | 705 } |
| 685 } | 706 } |
| 686 | 707 |
| 687 /** | 708 /** |
| 688 * This class holds a value, that can be changed. It is used when | 709 * This class holds a value, that can be changed. It is used when |
| 689 * closures need a shared value, that they can all change and read. | 710 * closures need a shared value, that they can all change and read. |
| 690 */ | 711 */ |
| 691 class MutableValue<T> { | 712 class MutableValue<T> { |
| 692 MutableValue(T this.value); | 713 MutableValue(T this.value); |
| 693 T value; | 714 T value; |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 894 line = _stdoutStream.readLine(); | 915 line = _stdoutStream.readLine(); |
| 895 } | 916 } |
| 896 line = _stderrStream.readLine(); | 917 line = _stderrStream.readLine(); |
| 897 while (line != null) { | 918 while (line != null) { |
| 898 _testStderr.add(line); | 919 _testStderr.add(line); |
| 899 line = _stderrStream.readLine(); | 920 line = _stderrStream.readLine(); |
| 900 } | 921 } |
| 901 _stderrDrained = true; | 922 _stderrDrained = true; |
| 902 _stdoutDrained = true; | 923 _stdoutDrained = true; |
| 903 _process.close(); | 924 _process.close(); |
| 904 _startProcess(() { _reportResult(); }); | 925 _startProcess(() { _reportResult(); }); |
|
ricow1
2012/10/11 17:27:34
why not just pass _reportResult in here instead of
Mads Ager (google)
2012/10/12 08:44:46
Done.
| |
| 905 } else { // No active test case running. | 926 } else { // No active test case running. |
| 906 _process.close(); | 927 _process.close(); |
| 907 _process = null; | 928 _process = null; |
| 908 } | 929 } |
| 909 } | 930 } |
| 910 return handler; | 931 return handler; |
| 911 } | 932 } |
| 912 | 933 |
| 913 void _timeoutHandler(ignore) { | 934 void _timeoutHandler(ignore) { |
| 914 _process.onExit = makeExitHandler(">>> TEST TIMEOUT"); | 935 _process.onExit = makeExitHandler(">>> TEST TIMEOUT"); |
| 915 _process.kill(); | 936 _process.kill(); |
| 916 } | 937 } |
| 917 | 938 |
| 918 void _startProcess(then) { | 939 void _processErrorHandler(e) { |
| 919 _process = Process.start(_executable, _batchArguments); | 940 print("Process error:"); |
| 920 _stdoutStream = new StringInputStream(_process.stdout); | 941 print(" Command: $_executable ${Strings.join(_batchArguments, ' ')}"); |
| 921 _stderrStream = new StringInputStream(_process.stderr); | 942 print(" Error: $e"); |
| 922 _process.onExit = makeExitHandler(">>> TEST CRASH"); | 943 // If there is an error starting a batch process, chances are that |
| 923 _process.onError = (e) { | 944 // it will always fail. So rather than re-trying a 1000+ times, we |
| 924 print("Error starting process:"); | 945 // exit. |
|
ahe
2012/10/11 18:39:50
+1000!
| |
| 925 print(" Command: $_executable ${Strings.join(_batchArguments, ' ')}"); | 946 exit(1); |
| 926 print(" Error: $e"); | 947 } |
| 927 // If there is an error starting a batch process, chances are that | 948 |
| 928 // it will always fail. So rather than re-trying a 1000+ times, we | 949 _startProcess(then) { |
|
ricow1
2012/10/11 17:27:34
should we change "then" to another name here to no
Emily Fortuna
2012/10/11 18:23:08
+1
Mads Ager (google)
2012/10/12 08:44:46
Done.
| |
| 929 // exit. | 950 Future processFuture = Process.start(_executable, _batchArguments); |
| 930 exit(1); | 951 processFuture.then((p) { |
| 931 }; | 952 _process = p; |
| 932 _process.onStart = then; | 953 _stdoutStream = new StringInputStream(_process.stdout); |
| 954 _stderrStream = new StringInputStream(_process.stderr); | |
| 955 _process.onExit = makeExitHandler(">>> TEST CRASH"); | |
| 956 _process.onError = _processErrorHandler; | |
| 957 then(); | |
| 958 }); | |
| 959 processFuture.handleException((e) { | |
| 960 _processErrorHandler(e); | |
|
ahe
2012/10/11 18:39:50
Aren't you getting tired of wrapping this? ;-)
| |
| 961 return true; | |
| 962 }); | |
| 933 } | 963 } |
| 934 } | 964 } |
| 935 | 965 |
| 936 /** | 966 /** |
| 937 * ProcessQueue is the master control class, responsible for running all | 967 * ProcessQueue is the master control class, responsible for running all |
| 938 * the tests in all the TestSuites that have been registered. It includes | 968 * the tests in all the TestSuites that have been registered. It includes |
| 939 * a rate-limited queue to run a limited number of tests in parallel, | 969 * a rate-limited queue to run a limited number of tests in parallel, |
| 940 * a ProgressIndicator which prints output when tests are started and | 970 * a ProgressIndicator which prints output when tests are started and |
| 941 * and completed, and a summary report when all tests are completed, | 971 * and completed, and a summary report when all tests are completed, |
| 942 * and counters to determine when all of the tests in all of the test suites | 972 * and counters to determine when all of the tests in all of the test suites |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1071 if (!_isSeleniumAvailable && !_startingServer) { | 1101 if (!_isSeleniumAvailable && !_startingServer) { |
| 1072 _startingServer = true; | 1102 _startingServer = true; |
| 1073 | 1103 |
| 1074 // Check to see if the jar was already running before the program started. | 1104 // Check to see if the jar was already running before the program started. |
| 1075 String cmd = 'ps'; | 1105 String cmd = 'ps'; |
| 1076 var arg = ['aux']; | 1106 var arg = ['aux']; |
| 1077 if (Platform.operatingSystem == 'windows') { | 1107 if (Platform.operatingSystem == 'windows') { |
| 1078 cmd = 'tasklist'; | 1108 cmd = 'tasklist'; |
| 1079 arg.add('/v'); | 1109 arg.add('/v'); |
| 1080 } | 1110 } |
| 1081 Process p = Process.start(cmd, arg); | 1111 |
| 1082 final StringInputStream stdoutStringStream = | 1112 processErrorHandler(e) { |
| 1083 new StringInputStream(p.stdout); | |
| 1084 p.onError = (e) { | |
| 1085 print("Error starting process:"); | 1113 print("Error starting process:"); |
| 1086 print(" Command: $cmd ${Strings.join(arg, ' ')}"); | 1114 print(" Command: $cmd ${Strings.join(arg, ' ')}"); |
| 1087 print(" Error: $e"); | 1115 print(" Error: $e"); |
| 1088 // TODO(ahe): How to report this as a test failure? | 1116 // TODO(ahe): How to report this as a test failure? |
| 1089 exit(1); | 1117 exit(1); |
| 1090 }; | 1118 } |
| 1091 stdoutStringStream.onLine = () { | 1119 |
| 1092 var line = stdoutStringStream.readLine(); | 1120 Future processFuture = Process.start(cmd, arg); |
| 1093 while (null != line) { | 1121 processFuture.then((p) { |
|
ahe
2012/10/11 18:39:50
A type for p would be nice.
Mads Ager (google)
2012/10/12 08:44:46
Done.
| |
| 1094 if (const RegExp(r".*selenium-server-standalone.*").hasMatch(line)) { | 1122 final StringInputStream stdoutStringStream = |
| 1095 _seleniumAlreadyRunning = true; | 1123 new StringInputStream(p.stdout); |
| 1096 resumeTesting(); | 1124 p.onError = processErrorHandler; |
| 1125 stdoutStringStream.onLine = () { | |
| 1126 var line = stdoutStringStream.readLine(); | |
| 1127 while (null != line) { | |
| 1128 var regexp = const RegExp(r".*selenium-server-standalone.*"); | |
| 1129 if (regexp.hasMatch(line)) { | |
| 1130 _seleniumAlreadyRunning = true; | |
| 1131 resumeTesting(); | |
| 1132 } | |
| 1133 line = stdoutStringStream.readLine(); | |
| 1097 } | 1134 } |
| 1098 line = stdoutStringStream.readLine(); | 1135 if (!_isSeleniumAvailable) { |
| 1099 } | 1136 _startSeleniumServer(); |
| 1100 if (!_isSeleniumAvailable) { | 1137 } |
| 1101 _startSeleniumServer(); | 1138 }; |
| 1102 } | 1139 }); |
| 1103 }; | 1140 processFuture.handleException((e) { |
|
ahe
2012/10/11 18:39:50
Boring! ;-)
Mads Ager (google)
2012/10/12 08:44:46
Yawn! ;-)
| |
| 1141 processErrorHandler(e); | |
| 1142 return true; | |
| 1143 }); | |
| 1104 } | 1144 } |
| 1105 } | 1145 } |
| 1106 | 1146 |
| 1107 void _runTest(TestCase test) { | 1147 void _runTest(TestCase test) { |
| 1108 if (test.usesWebDriver) { | 1148 if (test.usesWebDriver) { |
| 1109 browserUsed = test.configuration['browser']; | 1149 browserUsed = test.configuration['browser']; |
|
Mads Ager (google)
2012/10/11 16:00:54
This is not right. browserUsed is supposed to be a
Emily Fortuna
2012/10/11 18:23:08
Right. I've put in this CL: https://codereview.chr
Mads Ager (google)
2012/10/12 08:44:46
Thank you!
| |
| 1110 if (_needsSelenium) _ensureSeleniumServerRunning(); | 1150 if (_needsSelenium) _ensureSeleniumServerRunning(); |
| 1111 } | 1151 } |
| 1112 _progress.testAdded(); | 1152 _progress.testAdded(); |
| 1113 _tests.add(test); | 1153 _tests.add(test); |
| 1114 _tryRunTest(); | 1154 _tryRunTest(); |
| 1115 } | 1155 } |
| 1116 | 1156 |
| 1117 /** | 1157 /** |
| 1118 * Monitor the output of the Selenium server, to know when we are ready to | 1158 * Monitor the output of the Selenium server, to know when we are ready to |
| 1119 * begin running tests. | 1159 * begin running tests. |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1142 void _startSeleniumServer() { | 1182 void _startSeleniumServer() { |
| 1143 // Get the absolute path to the Selenium jar. | 1183 // Get the absolute path to the Selenium jar. |
| 1144 String filePath = TestUtils.testScriptPath; | 1184 String filePath = TestUtils.testScriptPath; |
| 1145 String pathSep = Platform.pathSeparator; | 1185 String pathSep = Platform.pathSeparator; |
| 1146 int index = filePath.lastIndexOf(pathSep); | 1186 int index = filePath.lastIndexOf(pathSep); |
| 1147 filePath = '${filePath.substring(0, index)}${pathSep}testing${pathSep}'; | 1187 filePath = '${filePath.substring(0, index)}${pathSep}testing${pathSep}'; |
| 1148 var lister = new Directory(filePath).list(); | 1188 var lister = new Directory(filePath).list(); |
| 1149 lister.onFile = (String file) { | 1189 lister.onFile = (String file) { |
| 1150 if (const RegExp(r"selenium-server-standalone-.*\.jar").hasMatch(file) | 1190 if (const RegExp(r"selenium-server-standalone-.*\.jar").hasMatch(file) |
| 1151 && _seleniumServer == null) { | 1191 && _seleniumServer == null) { |
| 1152 _seleniumServer = Process.start('java', ['-jar', file]); | 1192 void processErrorHandler(e) { |
| 1153 _seleniumServer.onError = (e) { | 1193 print("Process error:"); |
| 1154 print("Error starting process:"); | |
| 1155 print(" Command: java -jar $file"); | 1194 print(" Command: java -jar $file"); |
| 1156 print(" Error: $e"); | 1195 print(" Error: $e"); |
| 1157 // TODO(ahe): How to report this as a test failure? | 1196 // TODO(ahe): How to report this as a test failure? |
| 1158 exit(1); | 1197 exit(1); |
| 1159 }; | 1198 } |
| 1160 // Heads up: there seems to an obscure data race of some form in | 1199 Future processFuture = Process.start('java', ['-jar', file]); |
| 1161 // the VM between launching the server process and launching the test | 1200 processFuture.then((server) { |
| 1162 // tasks that disappears when you read IO (which is convenient, since | 1201 _seleniumServer = server; |
| 1163 // that is our condition for knowing that the server is ready). | 1202 _seleniumServer.onError = processErrorHandler; |
| 1164 StringInputStream stdoutStringStream = | 1203 // Heads up: there seems to an obscure data race of some form in |
| 1165 new StringInputStream(_seleniumServer.stdout); | 1204 // the VM between launching the server process and launching the test |
| 1166 StringInputStream stderrStringStream = | 1205 // tasks that disappears when you read IO (which is convenient, since |
| 1167 new StringInputStream(_seleniumServer.stderr); | 1206 // that is our condition for knowing that the server is ready). |
| 1168 stdoutStringStream.onLine = | 1207 StringInputStream stdoutStringStream = |
| 1169 makeSeleniumServerHandler(stdoutStringStream); | 1208 new StringInputStream(_seleniumServer.stdout); |
| 1170 stderrStringStream.onLine = | 1209 StringInputStream stderrStringStream = |
| 1171 makeSeleniumServerHandler(stderrStringStream); | 1210 new StringInputStream(_seleniumServer.stderr); |
| 1211 stdoutStringStream.onLine = | |
| 1212 makeSeleniumServerHandler(stdoutStringStream); | |
| 1213 stderrStringStream.onLine = | |
| 1214 makeSeleniumServerHandler(stderrStringStream); | |
| 1215 }); | |
| 1216 processFuture.handleException((e) { | |
| 1217 processErrorHandler(e); | |
| 1218 return true; | |
| 1219 }); | |
| 1172 } | 1220 } |
| 1173 }; | 1221 }; |
| 1174 } | 1222 } |
| 1175 | 1223 |
| 1176 Future _terminateBatchRunners() { | 1224 Future _terminateBatchRunners() { |
| 1177 var futures = new List(); | 1225 var futures = new List(); |
| 1178 for (var runners in _batchProcesses.getValues()) { | 1226 for (var runners in _batchProcesses.getValues()) { |
| 1179 for (var runner in runners) { | 1227 for (var runner in runners) { |
| 1180 futures.add(runner.terminate()); | 1228 futures.add(runner.terminate()); |
| 1181 } | 1229 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1247 // the developer doesn't waste his or her time trying to fix a bunch of | 1295 // the developer doesn't waste his or her time trying to fix a bunch of |
| 1248 // tests that appear to be broken but were actually just flakes that | 1296 // tests that appear to be broken but were actually just flakes that |
| 1249 // didn't get retried because there had already been one failure. | 1297 // didn't get retried because there had already been one failure. |
| 1250 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; | 1298 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; |
| 1251 new RunningProcess(test, allowRetry, this).start(); | 1299 new RunningProcess(test, allowRetry, this).start(); |
| 1252 } | 1300 } |
| 1253 _numProcesses++; | 1301 _numProcesses++; |
| 1254 } | 1302 } |
| 1255 } | 1303 } |
| 1256 } | 1304 } |
| OLD | NEW |