Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(387)

Side by Side Diff: tools/testing/dart/test_runner.dart

Issue 9479034: Update test.dart for detection output of machine formatted errors (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updates the multitest logic. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 14 matching lines...) Expand all
25 25
26 /** Command line arguments to the executable. */ 26 /** Command line arguments to the executable. */
27 List<String> arguments; 27 List<String> arguments;
28 28
29 /** The actual command line that will be executed. */ 29 /** The actual command line that will be executed. */
30 String commandLine; 30 String commandLine;
31 31
32 Command(this.executable, this.arguments) { 32 Command(this.executable, this.arguments) {
33 commandLine = "$executable ${Strings.join(arguments, ' ')}"; 33 commandLine = "$executable ${Strings.join(arguments, ' ')}";
34 } 34 }
35
36 String toString() => commandLine;
35 } 37 }
36 38
37 /** 39 /**
38 * TestCase contains all the information needed to run a test and evaluate 40 * TestCase contains all the information needed to run a test and evaluate
39 * its output. Running a test involves starting a separate process, with 41 * its output. Running a test involves starting a separate process, with
40 * the executable and arguments given by the TestCase, and recording its 42 * the executable and arguments given by the TestCase, and recording its
41 * stdout and stderr output streams, and its exit code. TestCase only 43 * stdout and stderr output streams, and its exit code. TestCase only
42 * contains static information about the test; actually running the test is 44 * contains static information about the test; actually running the test is
43 * performed by [ProcessQueue] using a [RunningProcess] object. 45 * performed by [ProcessQueue] using a [RunningProcess] object.
44 * 46 *
(...skipping 13 matching lines...) Expand all
58 * multiple sources that are run in isolation. 60 * multiple sources that are run in isolation.
59 */ 61 */
60 final List<Command> commands; 62 final List<Command> commands;
61 63
62 Map configuration; 64 Map configuration;
63 String displayName; 65 String displayName;
64 TestOutput output; 66 TestOutput output;
65 bool isNegative; 67 bool isNegative;
66 Set<String> expectedOutcomes; 68 Set<String> expectedOutcomes;
67 Function completedHandler; 69 Function completedHandler;
70 TestInformation info;
68 71
69 TestCase(this.displayName, 72 TestCase(this.displayName,
70 this.commands, 73 this.commands,
71 this.configuration, 74 this.configuration,
72 this.completedHandler, 75 this.completedHandler,
73 this.expectedOutcomes, 76 this.expectedOutcomes,
74 [this.isNegative = false]) { 77 [this.isNegative = false,
78 this.info = null]) {
75 if (!isNegative) { 79 if (!isNegative) {
76 this.isNegative = displayName.contains("NegativeTest"); 80 this.isNegative = displayName.contains("NegativeTest");
77 } 81 }
78 82
79 // Special command handling. If a special command is specified 83 // Special command handling. If a special command is specified
80 // we have to completely rewrite the command that we are using. 84 // we have to completely rewrite the command that we are using.
81 // We generate a new command-line that is the special command 85 // We generate a new command-line that is the special command
82 // where we replace '@' with the original command. 86 // where we replace '@' with the original command.
83 var specialCommand = configuration['special-command']; 87 var specialCommand = configuration['special-command'];
84 if (!specialCommand.isEmpty()) { 88 if (!specialCommand.isEmpty()) {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 _lastArguments.getRange(1, _lastArguments.length - 1); 162 _lastArguments.getRange(1, _lastArguments.length - 1);
159 } 163 }
160 164
161 165
162 /** 166 /**
163 * TestOutput records the output of a completed test: the process's exit code, 167 * TestOutput records the output of a completed test: the process's exit code,
164 * the standard output and standard error, whether the process timed out, and 168 * the standard output and standard error, whether the process timed out, and
165 * the time the process took to run. It also contains a pointer to the 169 * the time the process took to run. It also contains a pointer to the
166 * [TestCase] this is the output of. 170 * [TestCase] this is the output of.
167 */ 171 */
168 class TestOutput { 172 interface TestOutput default TestOutputImpl {
zundel 2012/02/29 08:11:40 I didn't come up with much better than what was he
173 TestOutput.fromCase(TestCase testCase, int exitCode, bool timedOut,
174 List<String> stdout, List<String> stderr, Duration time);
175
176 String get result();
177
178 bool get unexpectedOutput();
179
180 bool get hasCrashed();
181
182 bool get hasTimedOut();
183
184 bool get didFail();
185 }
186
187 class TestOutputImpl implements TestOutput {
169 TestCase testCase; 188 TestCase testCase;
170 int exitCode; 189 int exitCode;
171 bool timedOut; 190 bool timedOut;
172 bool failed = false; 191 bool failed = false;
173 List<String> stdout; 192 List<String> stdout;
174 List<String> stderr; 193 List<String> stderr;
175 Duration time; 194 Duration time;
195
176 /** 196 /**
177 * Set to true if we encounter a condition in the output that indicates we 197 * Set to true if we encounter a condition in the output that indicates we
178 * need to rerun this test. 198 * need to rerun this test.
179 */ 199 */
180 bool requestRetry; 200 bool requestRetry;
181 201
182 TestOutput(this.testCase, this.exitCode, this.timedOut, this.stdout, 202 // Don't call this constructor, call TestOutput.fromCase() to
203 // get anew TestOutput instance.
204 TestOutputImpl(this.testCase, this.exitCode, this.timedOut, this.stdout,
183 this.stderr, this.time) { 205 this.stderr, this.time) {
184 testCase.output = this; 206 testCase.output = this;
185 requestRetry = false; 207 requestRetry = false;
186 } 208 }
187 209
210 factory TestOutputImpl.fromCase (testCase, exitCode, timedOut, stdout, stderr,
211 time) {
212 if (testCase is BrowserTestCase) {
213 return new BrowserTestOutputImpl(testCase, exitCode, timedOut,
214 stdout, stderr, time);
215 } else if (testCase.configuration['component'] == 'dartc') {
216 return new AnalysisTestOutputImpl(testCase, exitCode, timedOut,
217 stdout, stderr, time);
218 }
219 return new TestOutputImpl(testCase, exitCode, timedOut,
220 stdout, stderr, time);
221 }
222
188 String get result() => 223 String get result() =>
189 hasCrashed ? CRASH : (hasTimedOut ? TIMEOUT : (hasFailed ? FAIL : PASS)); 224 hasCrashed ? CRASH : (hasTimedOut ? TIMEOUT : (hasFailed ? FAIL : PASS));
190 225
191 bool get unexpectedOutput() => !testCase.expectedOutcomes.contains(result); 226 bool get unexpectedOutput() => !testCase.expectedOutcomes.contains(result);
192 227
193 bool get hasCrashed() { 228 bool get hasCrashed() {
194 if (new Platform().operatingSystem() == 'windows') { 229 if (new Platform().operatingSystem() == 'windows') {
195 // The VM uses std::abort to terminate on asserts. 230 // The VM uses std::abort to terminate on asserts.
196 // std::abort terminates with exit code 3 on Windows. 231 // std::abort terminates with exit code 3 on Windows.
197 if (exitCode == 3) { 232 if (exitCode == 3) {
198 return !timedOut; 233 return !timedOut;
199 } 234 }
200 return (!timedOut && (exitCode < 0) && ((0x3FFFFF00 & exitCode) == 0)); 235 return (!timedOut && (exitCode < 0) && ((0x3FFFFF00 & exitCode) == 0));
201 } 236 }
202 // The Java dartc runner exits with code 253 in case of unhandled 237 // The Java dartc runner exits with code 253 in case of unhandled
203 // exceptions. 238 // exceptions.
204 return (!timedOut && ((exitCode < 0) || (exitCode == 253))); 239 return (!timedOut && ((exitCode < 0) || (exitCode == 253)));
205 } 240 }
206 241
207 bool get hasTimedOut() => timedOut; 242 bool get hasTimedOut() => timedOut;
208 243
209 bool get didFail() { 244 bool get didFail() {
210 if (testCase is !BrowserTestCase) return (exitCode != 0 && !hasCrashed); 245 return (exitCode != 0 && !hasCrashed);
246 }
247
248 // Reverse result of a negative test.
249 bool get hasFailed() => (testCase.isNegative ? !didFail : didFail);
250 }
211 251
252 class BrowserTestOutputImpl extends TestOutputImpl {
253 BrowserTestOutputImpl(testCase, exitCode, timedOut, stdout, stderr, time) :
254 super(testCase, exitCode, timedOut, stdout, stderr, time);
255
256 bool get didFail() {
212 // Browser case: 257 // Browser case:
213 // If the browser test failed, it may have been because DumpRenderTree 258 // If the browser test failed, it may have been because DumpRenderTree
214 // and the virtual framebuffer X server didn't hook up, or DRT crashed with 259 // and the virtual framebuffer X server didn't hook up, or DRT crashed with
215 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS, 260 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS,
216 // so we have to do this check first. 261 // so we have to do this check first.
217 for (String line in stderr) { 262 for (String line in stderr) {
218 if (line.contains('Gtk-WARNING **: cannot open display: :99') || 263 if (line.contains('Gtk-WARNING **: cannot open display: :99') ||
219 line.contains('Failed to run command. return code=1')) { 264 line.contains('Failed to run command. return code=1')) {
220 // If we get the X server error, or DRT crashes with a core dump, retry 265 // If we get the X server error, or DRT crashes with a core dump, retry
221 // the test. 266 // the test.
222 if (testCase.dynamic.numRetries > 0) { 267 if (testCase.dynamic.numRetries > 0) {
223 requestRetry = true; 268 requestRetry = true;
224 } 269 }
225 return true; 270 return true;
226 } 271 }
227 } 272 }
228 273
229 // Browser tests fail unless stdout contains 274 // Browser tests fail unless stdout contains
230 // 'Content-Type: text/plain\nPASS'. 275 // 'Content-Type: text/plain\nPASS'.
231 String previous_line = ''; 276 String previous_line = '';
232 for (String line in stdout) { 277 for (String line in stdout) {
233 if (line == 'PASS' && previous_line == 'Content-Type: text/plain') { 278 if (line == 'PASS' && previous_line == 'Content-Type: text/plain') {
234 return (exitCode != 0 && !hasCrashed); 279 return (exitCode != 0 && !hasCrashed);
235 } 280 }
236 previous_line = line; 281 previous_line = line;
237 } 282 }
238
239 return true; 283 return true;
240 } 284 }
285 }
241 286
242 // Reverse result of a negative test. 287 // The static analyzer does not actaully execute code, so
243 bool get hasFailed() => (testCase.isNegative ? !didFail : didFail); 288 // the criteria for success now depend on the text sent
289 // to stderr.
290 class AnalysisTestOutputImpl extends TestOutputImpl {
291 AnalysisTestOutputImpl(testCase, exitCode, timedOut, stdout, stderr, time) :
292 super(testCase, exitCode, timedOut, stdout, stderr, time) {
293 }
294
295 bool get didFail() {
296 if (hasCrashed) return false;
297
298 List<String> errors = [];
299 List<String> staticWarnings = [];
300
301 // Read the returned list of errors and stuff them away.
302 for (String line in stderr) {
303 if (line.length == 0) continue;
304 List<String> fields = splitMachineError(line);
305 switch(fields[0]) {
306 case 'ERROR':
307 errors.add(fields);
308 break;
309 case 'WARNING':
310 // We only care about testing Static type warnings
311 // ignore all others
312 if (fields[1] == 'STATIC_TYPE') {
313 staticWarnings.add(fields);
314 }
315 break;
316 default:
317 // Skip error output that doesn't match the machine format
318 }
319 }
320 if (testCase.info != null
321 && testCase.info.optionsFromFile['isMultitest']) {
322 return _didMultitestFail(errors, staticWarnings);
323 }
324 return _didStandardTestFail(errors, staticWarnings);
325 }
326
327 bool _didMultitestFail(List errors, List staticWarnings) {
328 String outcome = testCase.info.multitestOutcome;
329 if ((outcome == '' || outcome == 'compile-time error') && errors.length > 0) {
330 return true;
331 } else if (outcome == 'static type error' && staticWarnings.length > 0) {
332 return true;
333 }
334 return false;
335 }
336
337 bool _didStandardTestFail(List errors, List staticWarnings) {
338 bool hasFatalTypeErrors = false;
339 int numStaticTypeAnnotations = 0;
340 int numCompileTimeAnnotations = 0;
341 if (testCase.info != null) {
342 var optionsFromFile = testCase.info.optionsFromFile;
343 hasFatalTypeErrors = optionsFromFile['hasFatalTypeErrors'];
344 for (Command c in testCase.commands) {
345 for (String arg in c.arguments) {
346 if (arg == '--fatal-type-errors') {
347 hasFatalTypeErrors = true;
348 break;
349 }
350 }
351 }
352 numStaticTypeAnnotations = optionsFromFile['numStaticTypeAnnotations'];
353 numCompileTimeAnnotations = optionsFromFile['numCompileTimeAnnotations'];
354 }
355
356 // TODO(zundel): These assertions are catching some sort of issue
357 // where the output between two test cases is getting crossed.
358 if (errors.length == 0) {
359 if (!hasFatalTypeErrors) {
360 Expect.isTrue(exitCode == 0,
361 "Expected error: exitCode:${exitCode} command[0]:${testCase.commands [0]}");
362 }
363 } else {
364 Expect.isTrue(exitCode != 0,
365 "Unexpected error: exitCode:${exitCode} command[0]:${testCase.commands[0 ]} errors[0]:${errors[0]}");
366 }
367
368 if (numCompileTimeAnnotations > 0
369 && numCompileTimeAnnotations < errors.length) {
370 // Expected compile-time errors were not returned. The test did not 'fail ' in the way
371 // intended so don't return failed.
372 // TODO(zundel): give a good diagnostic message here
373 return false;
374 }
375
376 if (numStaticTypeAnnotations > 0 || hasFatalTypeErrors) {
377 // TODO(zundel): match up the annotation line numbers
378 // with the reported error line numbers
379 if (staticWarnings.length < numStaticTypeAnnotations) {
380 // TODO(zundel): How to give a good diagnostic message here?
381 return true;
382 }
383 return false;
384 } else if (errors.length != 0) {
385 return true;
386 }
387 return false;
388 }
389
390 // Parse a line delimited by the | character using \ as an escape charager
391 // like: FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ
392 List<String> splitMachineError(String line) {
393 StringBuffer field = new StringBuffer();
394 List<String> result = [];
395 bool escaped = false;
396 for (var i = 0 ; i < line.length; i++) {
397 var c = line[i];
398 if (!escaped && c == '\\') {
399 escaped = true;
400 continue;
401 }
402 escaped = false;
403 if (c == '|') {
404 result.add(field.toString());
405 field.clear();
406 continue;
407 }
408 field.add(c);
409 }
410 result.add(field.toString());
411 return result;
412 }
244 } 413 }
245 414
246 /** 415 /**
247 * A RunningProcess actually runs a test, getting the command lines from 416 * A RunningProcess actually runs a test, getting the command lines from
248 * its [TestCase], starting the test process (and first, a compilation 417 * its [TestCase], starting the test process (and first, a compilation
249 * process if the TestCase is a [BrowserTestCase]), creating a timeout 418 * process if the TestCase is a [BrowserTestCase]), creating a timeout
250 * timer, and recording the results in a new [TestOutput] object, which it 419 * timer, and recording the results in a new [TestOutput] object, which it
251 * attaches to the TestCase. The lifetime of the RunningProcess is limited 420 * attaches to the TestCase. The lifetime of the RunningProcess is limited
252 * to the time it takes to start the process, run the process, and record 421 * to the time it takes to start the process, run the process, and record
253 * the result; there are no pointers to it, so it should be available to 422 * the result; there are no pointers to it, so it should be available to
(...skipping 16 matching lines...) Expand all
270 439
271 RunningProcess(TestCase this.testCase, 440 RunningProcess(TestCase this.testCase,
272 [this.allowRetries, this.processQueue]); 441 [this.allowRetries, this.processQueue]);
273 442
274 /** 443 /**
275 * Called when all commands are executed. [exitCode] is 0 if all command 444 * Called when all commands are executed. [exitCode] is 0 if all command
276 * succeded, otherwise it will have the exit code of the first failing 445 * succeded, otherwise it will have the exit code of the first failing
277 * command. 446 * command.
278 */ 447 */
279 void testComplete(int exitCode) { 448 void testComplete(int exitCode) {
280 new TestOutput(testCase, exitCode, timedOut, stdout, 449 new TestOutput.fromCase(testCase, exitCode, timedOut, stdout,
281 stderr, new Date.now().difference(startTime)); 450 stderr, new Date.now().difference(startTime));
282 timeoutTimer.cancel(); 451 timeoutTimer.cancel();
283 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) { 452 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) {
284 print(testCase.displayName); 453 print(testCase.displayName);
285 for (var line in testCase.output.stderr) print(line); 454 for (var line in testCase.output.stderr) print(line);
286 for (var line in testCase.output.stdout) print(line); 455 for (var line in testCase.output.stdout) print(line);
287 } 456 }
288 if (allowRetries != null && allowRetries 457 if (allowRetries != null && allowRetries
289 && testCase.configuration['component'] == 'webdriver' && 458 && testCase.configuration['component'] == 'webdriver' &&
290 testCase.output.unexpectedOutput && testCase.numRetries > 0) { 459 testCase.output.unexpectedOutput && testCase.numRetries > 0) {
291 // Selenium tests can be flaky. Try rerunning. 460 // Selenium tests can be flaky. Try rerunning.
292 testCase.output.requestRetry = true; 461 testCase.output.requestRetry = true;
293 } 462 }
294 if (testCase.output.requestRetry) { 463 if (testCase.output.requestRetry) {
295 testCase.output.requestRetry = false; 464 testCase.output.requestRetry = false;
296 this.timedOut = false; 465 this.timedOut = false;
297 testCase.dynamic.numRetries--; 466 testCase.dynamic.numRetries--;
298 print("Potential flake. " + 467 print("Potential flake. Re-running ${testCase.displayName} " +
299 "Re-running ${testCase.displayName} " +
300 "(${testCase.dynamic.numRetries} attempt(s) remains)"); 468 "(${testCase.dynamic.numRetries} attempt(s) remains)");
301 this.start(); 469 this.start();
302 } else { 470 } else {
303 testCase.completed(); 471 testCase.completed();
304 } 472 }
305 } 473 }
306 474
307 /** 475 /**
308 * Process exit handler called at the end of every command. It internally 476 * Process exit handler called at the end of every command. It internally
309 * treats all but the last command as compilation steps. The last command is 477 * treats all but the last command as compilation steps. The last command is
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 bool shutdownMillisecs = 30000; 613 bool shutdownMillisecs = 30000;
446 new Timer((e) { if (!closed) _process.kill(); }, shutdownMillisecs); 614 new Timer((e) { if (!closed) _process.kill(); }, shutdownMillisecs);
447 } else { 615 } else {
448 _process.kill(); 616 _process.kill();
449 } 617 }
450 } 618 }
451 } 619 }
452 620
453 void doStartTest(TestCase testCase) { 621 void doStartTest(TestCase testCase) {
454 _startTime = new Date.now(); 622 _startTime = new Date.now();
455 _testStdout = new List<String>(); 623 _testStdout = [];
456 _testStderr = new List<String>(); 624 _testStderr = [];
457 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout); 625 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout);
458 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr); 626 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr);
459 _timer = new Timer(_timeoutHandler, testCase.timeout * 1000); 627 _timer = new Timer(_timeoutHandler, testCase.timeout * 1000);
460 var line = _createArgumentsLine(testCase.batchTestArguments); 628 var line = _createArgumentsLine(testCase.batchTestArguments);
461 _process.stdin.write(line.charCodes()); 629 _process.stdin.write(line.charCodes());
462 } 630 }
463 631
464 String _createArgumentsLine(List<String> arguments) { 632 String _createArgumentsLine(List<String> arguments) {
465 return Strings.join(arguments, ' ') + '\n'; 633 return Strings.join(arguments, ' ') + '\n';
466 } 634 }
467 635
468 int _reportResult(String output) { 636 int _reportResult(String output) {
469 var test = _currentTest; 637 var test = _currentTest;
470 _currentTest = null; 638 _currentTest = null;
471 639
472 // output = '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' 640 // output = '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}'
473 var outcome = output.split(" ")[2]; 641 var outcome = output.split(" ")[2];
474 var exitCode = 0; 642 var exitCode = 0;
475 if (outcome == "CRASH") exitCode = -10; 643 if (outcome == "CRASH") exitCode = -10;
476 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; 644 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1;
477 new TestOutput(test, exitCode, outcome == "TIMEOUT", _testStdout, 645 new TestOutput.fromCase(test, exitCode, outcome == "TIMEOUT", _testStdout,
478 _testStderr, new Date.now().difference(_startTime)); 646 _testStderr, new Date.now().difference(_startTime));
647 _testStdout = [];
648 _testStderr = [];
479 test.completed(); 649 test.completed();
480 } 650 }
481 651
482 Function _readOutput(StringInputStream stream, List<String> buffer) { 652 Function _readOutput(StringInputStream stream, List<String> buffer) {
483 return () { 653 return () {
484 var status; 654 var status;
485 var line = stream.readLine(); 655 var line = stream.readLine();
486 // Drain the input stream to get the error output. 656 // Drain the input stream to get the error output.
487 while (line != null) { 657 while (line != null) {
488 if (line.startsWith('>>> TEST')) { 658 if (line.startsWith('>>> TEST')) {
(...skipping 12 matching lines...) Expand all
501 // For crashing processes, let the exit handler deal with it. 671 // For crashing processes, let the exit handler deal with it.
502 if (!status.contains("CRASH")) { 672 if (!status.contains("CRASH")) {
503 _reportResult(status); 673 _reportResult(status);
504 } 674 }
505 } 675 }
506 }; 676 };
507 } 677 }
508 678
509 void _exitHandler(exitCode) { 679 void _exitHandler(exitCode) {
510 if (_timer != null) _timer.cancel(); 680 if (_timer != null) _timer.cancel();
681 _reportResult(">>> TEST CRASH");
zundel 2012/02/29 08:11:40 I moved this because _startProcess() clears the _t
511 _process.close(); 682 _process.close();
512 _startProcess(() { 683 _startProcess(() {});
513 _reportResult(">>> TEST CRASH");
514 });
515 } 684 }
516 685
517 void _timeoutHandler(ignore) { 686 void _timeoutHandler(ignore) {
518 _process.exitHandler = (exitCode) { 687 _process.exitHandler = (exitCode) {
688 _reportResult(">>> TEST TIMEOUT");
519 _process.close(); 689 _process.close();
520 _startProcess(() { 690 _startProcess(() {});
521 _reportResult(">>> TEST TIMEOUT");
522 });
523 }; 691 };
524 _process.kill(); 692 _process.kill();
525 } 693 }
526 694
527 void _startProcess(then) { 695 void _startProcess(then) {
528 _process = new Process.start(_executable, _batchArguments); 696 _process = new Process.start(_executable, _batchArguments);
529 _stdoutStream = new StringInputStream(_process.stdout); 697 _stdoutStream = new StringInputStream(_process.stdout);
530 _stderrStream = new StringInputStream(_process.stderr); 698 _stderrStream = new StringInputStream(_process.stderr);
531 _testStdout = new List<String>(); 699 _testStdout = new List<String>();
532 _testStderr = new List<String>(); 700 _testStderr = new List<String>();
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 // the developer doesn't waste his or her time trying to fix a bunch of 943 // the developer doesn't waste his or her time trying to fix a bunch of
776 // tests that appear to be broken but were actually just flakes that 944 // tests that appear to be broken but were actually just flakes that
777 // didn't get retried because there had already been one failure. 945 // didn't get retried because there had already been one failure.
778 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; 946 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests;
779 new RunningProcess(test, allowRetry, this).start(); 947 new RunningProcess(test, allowRetry, this).start();
780 } 948 }
781 _numProcesses++; 949 _numProcesses++;
782 } 950 }
783 } 951 }
784 } 952 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698