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

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

Issue 11348060: Revert of commit 14947 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 1 month 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
« no previous file with comments | « tools/testing/dart/test_progress.dart ('k') | tools/testing/dart/test_suite.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 } 49 }
50 50
51 /** 51 /**
52 * TestCase contains all the information needed to run a test and evaluate 52 * TestCase contains all the information needed to run a test and evaluate
53 * its output. Running a test involves starting a separate process, with 53 * its output. Running a test involves starting a separate process, with
54 * the executable and arguments given by the TestCase, and recording its 54 * the executable and arguments given by the TestCase, and recording its
55 * stdout and stderr output streams, and its exit code. TestCase only 55 * stdout and stderr output streams, and its exit code. TestCase only
56 * contains static information about the test; actually running the test is 56 * contains static information about the test; actually running the test is
57 * performed by [ProcessQueue] using a [RunningProcess] object. 57 * performed by [ProcessQueue] using a [RunningProcess] object.
58 * 58 *
59 * The output information is stored in a [CommandOutput] instance contained 59 * The output information is stored in a [TestOutput] instance contained
60 * in TestCase.commandOutputs. The last CommandOutput instance is responsible 60 * in the TestCase. The TestOutput instance is responsible for evaluating
61 * for evaluating if the test has passed, failed, crashed, or timed out, and the 61 * if the test has passed, failed, crashed, or timed out, and the TestCase
62 * TestCase has information about what the expected result of the test should 62 * has information about what the expected result of the test should be.
63 * be.
64 * 63 *
65 * The TestCase has a callback function, [completedHandler], that is run when 64 * The TestCase has a callback function, [completedHandler], that is run when
66 * the test is completed. 65 * the test is completed.
67 */ 66 */
68 class TestCase { 67 class TestCase {
69 /** 68 /**
70 * A list of commands to execute. Most test cases have a single command. 69 * A list of commands to execute. Most test cases have a single command. Frog
71 * Dart2js tests have two commands, one to compile the source and another 70 * tests have two commands, one to compilate the source and another to execute
72 * to execute it. Some isolate tests might even have three, if they require 71 * it. Some isolate tests might even have three, if they require compiling
73 * compiling multiple sources that are run in isolation. 72 * multiple sources that are run in isolation.
74 */ 73 */
75 List<Command> commands; 74 List<Command> commands;
76 Map<Command, CommandOutput> commandOutputs = new Map<Command,CommandOutput>();
77 75
78 Map configuration; 76 Map configuration;
79 String displayName; 77 String displayName;
78 TestOutput output;
80 bool isNegative; 79 bool isNegative;
81 Set<String> expectedOutcomes; 80 Set<String> expectedOutcomes;
82 TestCaseEvent completedHandler; 81 TestCaseEvent completedHandler;
83 TestInformation info; 82 TestInformation info;
84 83
85 TestCase(this.displayName, 84 TestCase(this.displayName,
86 this.commands, 85 this.commands,
87 this.configuration, 86 this.configuration,
88 this.completedHandler, 87 this.completedHandler,
89 this.expectedOutcomes, 88 this.expectedOutcomes,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 newCommands.add(newCommand); 137 newCommands.add(newCommand);
139 // If there are extra spaces inside the prefix or suffix, this fails. 138 // If there are extra spaces inside the prefix or suffix, this fails.
140 String expected = 139 String expected =
141 '$prefix ${c.executable} $suffix ${Strings.join(c.arguments, ' ')}'; 140 '$prefix ${c.executable} $suffix ${Strings.join(c.arguments, ' ')}';
142 Expect.stringEquals(expected.trim(), newCommand.commandLine); 141 Expect.stringEquals(expected.trim(), newCommand.commandLine);
143 } 142 }
144 commands = newCommands; 143 commands = newCommands;
145 } 144 }
146 } 145 }
147 146
148 CommandOutput get lastCommandOutput {
149 if (commandOutputs.length == 0) {
150 throw new Exception("CommandOutputs is empty, maybe no command was run? ("
151 "displayName: '$displayName', "
152 "configurationString: '$configurationString')");
153 }
154 return commandOutputs[commands[commandOutputs.length - 1]];
155 }
156
157 int get timeout { 147 int get timeout {
158 if (expectedOutcomes.contains(SLOW)) { 148 if (expectedOutcomes.contains(SLOW)) {
159 return configuration['timeout'] * SLOW_TIMEOUT_MULTIPLIER; 149 return configuration['timeout'] * SLOW_TIMEOUT_MULTIPLIER;
160 } else { 150 } else {
161 return configuration['timeout']; 151 return configuration['timeout'];
162 } 152 }
163 } 153 }
164 154
165 String get configurationString { 155 String get configurationString {
166 final compiler = configuration['compiler']; 156 final compiler = configuration['compiler'];
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 */ 232 */
243 void notifyObservers() { 233 void notifyObservers() {
244 for (BrowserTestCase testCase in observers) { 234 for (BrowserTestCase testCase in observers) {
245 testCase.waitingForOtherTest = false; 235 testCase.waitingForOtherTest = false;
246 } 236 }
247 } 237 }
248 } 238 }
249 239
250 240
251 /** 241 /**
252 * CommandOutput records the output of a completed command: the process's exit 242 * TestOutput records the output of a completed test: the process's exit code,
253 * code, the standard output and standard error, whether the process timed out, 243 * the standard output and standard error, whether the process timed out, and
254 * and the time the process took to run. It also contains a pointer to the 244 * the time the process took to run. It also contains a pointer to the
255 * [TestCase] this is the output of. 245 * [TestCase] this is the output of.
256 */ 246 */
257 abstract class CommandOutput { 247 abstract class TestOutput {
258 factory CommandOutput.fromCase(TestCase testCase, 248 factory TestOutput.fromCase(TestCase testCase,
259 Command command, 249 int exitCode,
260 int exitCode, 250 bool incomplete,
261 bool incomplete, 251 bool timedOut,
262 bool timedOut, 252 List<String> stdout,
263 List<String> stdout, 253 List<String> stderr,
264 List<String> stderr, 254 Duration time) {
265 Duration time) { 255 return new TestOutputImpl.fromCase(
266 return new CommandOutputImpl.fromCase(testCase, 256 testCase, exitCode, incomplete, timedOut, stdout, stderr, time);
267 command,
268 exitCode,
269 incomplete,
270 timedOut,
271 stdout,
272 stderr,
273 time);
274 } 257 }
275 258
276 bool get incomplete; 259 bool get incomplete;
277 260
278 String get result; 261 String get result;
279 262
280 bool get unexpectedOutput; 263 bool get unexpectedOutput;
281 264
282 bool get hasCrashed; 265 bool get hasCrashed;
283 266
284 bool get hasTimedOut; 267 bool get hasTimedOut;
285 268
286 bool get didFail; 269 bool get didFail;
287 270
288 bool requestRetry; 271 bool requestRetry;
289 272
290 Duration get time; 273 Duration get time;
291 274
292 int get exitCode; 275 int get exitCode;
293 276
294 List<String> get stdout; 277 List<String> get stdout;
295 278
296 List<String> get stderr; 279 List<String> get stderr;
297 280
298 List<String> get diagnostics; 281 List<String> get diagnostics;
299 } 282 }
300 283
301 class CommandOutputImpl implements CommandOutput { 284 class TestOutputImpl implements TestOutput {
302 TestCase testCase; 285 TestCase testCase;
303 int exitCode; 286 int exitCode;
304 287
305 /// Records if all commands were run, true if they weren't. 288 /// Records if all commands were run, true if they weren't.
306 final bool incomplete; 289 final bool incomplete;
307 290
308 bool timedOut; 291 bool timedOut;
309 bool failed = false; 292 bool failed = false;
310 List<String> stdout; 293 List<String> stdout;
311 List<String> stderr; 294 List<String> stderr;
312 Duration time; 295 Duration time;
313 List<String> diagnostics; 296 List<String> diagnostics;
314 297
315 /** 298 /**
316 * A flag to indicate we have already printed a warning about ignoring the VM 299 * A flag to indicate we have already printed a warning about ignoring the VM
317 * crash, to limit the amount of output produced per test. 300 * crash, to limit the amount of output produced per test.
318 */ 301 */
319 bool alreadyPrintedWarning = false; 302 bool alreadyPrintedWarning = false;
320 303
321 /** 304 /**
322 * Set to true if we encounter a condition in the output that indicates we 305 * Set to true if we encounter a condition in the output that indicates we
323 * need to rerun this test. 306 * need to rerun this test.
324 */ 307 */
325 bool requestRetry = false; 308 bool requestRetry = false;
326 309
327 // Don't call this constructor, call CommandOutput.fromCase() to 310 // Don't call this constructor, call TestOutput.fromCase() to
328 // get a new TestOutput instance. 311 // get a new TestOutput instance.
329 CommandOutputImpl(TestCase this.testCase, 312 TestOutputImpl(TestCase this.testCase,
330 Command command, 313 int this.exitCode,
331 int this.exitCode, 314 bool this.incomplete,
332 bool this.incomplete, 315 bool this.timedOut,
333 bool this.timedOut, 316 List<String> this.stdout,
334 List<String> this.stdout, 317 List<String> this.stderr,
335 List<String> this.stderr, 318 Duration this.time) {
336 Duration this.time) { 319 testCase.output = this;
337 testCase.commandOutputs[command] = this;
338 diagnostics = []; 320 diagnostics = [];
339 } 321 }
340 factory CommandOutputImpl.fromCase(TestCase testCase, 322 factory TestOutputImpl.fromCase(TestCase testCase,
341 Command command, 323 int exitCode,
342 int exitCode, 324 bool incomplete,
343 bool incomplete, 325 bool timedOut,
344 bool timedOut, 326 List<String> stdout,
345 List<String> stdout, 327 List<String> stderr,
346 List<String> stderr, 328 Duration time) {
347 Duration time) {
348 if (testCase is BrowserTestCase) { 329 if (testCase is BrowserTestCase) {
349 return new BrowserCommandOutputImpl(testCase, 330 return new BrowserTestOutputImpl(testCase, exitCode, incomplete,
350 command, 331 timedOut, stdout, stderr, time);
351 exitCode,
352 incomplete,
353 timedOut,
354 stdout,
355 stderr,
356 time);
357 } else if (testCase.configuration['compiler'] == 'dartc') { 332 } else if (testCase.configuration['compiler'] == 'dartc') {
358 return new AnalysisCommandOutputImpl(testCase, 333 return new AnalysisTestOutputImpl(testCase, exitCode, timedOut,
359 command, 334 stdout, stderr, time);
360 exitCode,
361 timedOut,
362 stdout,
363 stderr,
364 time);
365 } 335 }
366 return new CommandOutputImpl(testCase, 336 return new TestOutputImpl(testCase, exitCode, incomplete, timedOut,
367 command, 337 stdout, stderr, time);
368 exitCode,
369 incomplete,
370 timedOut,
371 stdout,
372 stderr,
373 time);
374 } 338 }
375 339
376 String get result => 340 String get result =>
377 hasCrashed ? CRASH : (hasTimedOut ? TIMEOUT : (hasFailed ? FAIL : PASS)); 341 hasCrashed ? CRASH : (hasTimedOut ? TIMEOUT : (hasFailed ? FAIL : PASS));
378 342
379 bool get unexpectedOutput => !testCase.expectedOutcomes.contains(result); 343 bool get unexpectedOutput => !testCase.expectedOutcomes.contains(result);
380 344
381 bool get hasCrashed { 345 bool get hasCrashed {
382 // The Java dartc runner and dart2js exits with code 253 in case 346 // The Java dartc runner and dart2js exits with code 253 in case
383 // of unhandled exceptions. 347 // of unhandled exceptions.
(...skipping 19 matching lines...) Expand all
403 bool get hasFailed { 367 bool get hasFailed {
404 // Always fail if a runtime-error is expected and compilation failed. 368 // Always fail if a runtime-error is expected and compilation failed.
405 if (testCase.info != null && testCase.info.hasRuntimeError && incomplete) { 369 if (testCase.info != null && testCase.info.hasRuntimeError && incomplete) {
406 return true; 370 return true;
407 } 371 }
408 return testCase.isNegative ? !didFail : didFail; 372 return testCase.isNegative ? !didFail : didFail;
409 } 373 }
410 374
411 } 375 }
412 376
413 class BrowserCommandOutputImpl extends CommandOutputImpl { 377 class BrowserTestOutputImpl extends TestOutputImpl {
414 BrowserCommandOutputImpl( 378 BrowserTestOutputImpl(testCase, exitCode, incomplete,
415 testCase, 379 timedOut, stdout, stderr, time) :
416 command, 380 super(testCase, exitCode, incomplete, timedOut, stdout, stderr, time);
417 exitCode,
418 incomplete,
419 timedOut,
420 stdout,
421 stderr,
422 time) :
423 super(testCase,
424 command,
425 exitCode,
426 incomplete,
427 timedOut,
428 stdout,
429 stderr,
430 time);
431 381
432 bool get didFail { 382 bool get didFail {
433 // Browser case: 383 // Browser case:
434 // If the browser test failed, it may have been because DumpRenderTree 384 // If the browser test failed, it may have been because DumpRenderTree
435 // and the virtual framebuffer X server didn't hook up, or DRT crashed with 385 // and the virtual framebuffer X server didn't hook up, or DRT crashed with
436 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS, 386 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS,
437 // so we have to do this check first. 387 // so we have to do this check first.
438 for (String line in super.stderr) { 388 for (String line in super.stderr) {
439 if (line.contains('Gtk-WARNING **: cannot open display: :99') || 389 if (line.contains('Gtk-WARNING **: cannot open display: :99') ||
440 line.contains('Failed to run command. return code=1')) { 390 line.contains('Failed to run command. return code=1')) {
(...skipping 22 matching lines...) Expand all
463 break; 413 break;
464 } 414 }
465 } 415 }
466 return true; 416 return true;
467 } 417 }
468 } 418 }
469 419
470 // The static analyzer does not actually execute code, so 420 // The static analyzer does not actually execute code, so
471 // the criteria for success now depend on the text sent 421 // the criteria for success now depend on the text sent
472 // to stderr. 422 // to stderr.
473 class AnalysisCommandOutputImpl extends CommandOutputImpl { 423 class AnalysisTestOutputImpl extends TestOutputImpl {
474 // An error line has 8 fields that look like: 424 // An error line has 8 fields that look like:
475 // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source. 425 // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source.
476 final int ERROR_LEVEL = 0; 426 final int ERROR_LEVEL = 0;
477 final int ERROR_TYPE = 1; 427 final int ERROR_TYPE = 1;
478 final int FORMATTED_ERROR = 7; 428 final int FORMATTED_ERROR = 7;
479 429
480 bool alreadyComputed = false; 430 bool alreadyComputed = false;
481 bool failResult; 431 bool failResult;
482 AnalysisCommandOutputImpl(testCase, 432 AnalysisTestOutputImpl(testCase, exitCode, timedOut, stdout, stderr, time) :
483 command, 433 super(testCase, exitCode, false, timedOut, stdout, stderr, time);
484 exitCode,
485 timedOut,
486 stdout,
487 stderr,
488 time) :
489 super(testCase, command, exitCode, false, timedOut, stdout, stderr, time);
490 434
491 bool get didFail { 435 bool get didFail {
492 if (!alreadyComputed) { 436 if (!alreadyComputed) {
493 failResult = _didFail(); 437 failResult = _didFail();
494 alreadyComputed = true; 438 alreadyComputed = true;
495 } 439 }
496 return failResult; 440 return failResult;
497 } 441 }
498 442
499 bool _didFail() { 443 bool _didFail() {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 } 576 }
633 result.add(field.toString()); 577 result.add(field.toString());
634 return result; 578 return result;
635 } 579 }
636 } 580 }
637 581
638 /** 582 /**
639 * A RunningProcess actually runs a test, getting the command lines from 583 * A RunningProcess actually runs a test, getting the command lines from
640 * its [TestCase], starting the test process (and first, a compilation 584 * its [TestCase], starting the test process (and first, a compilation
641 * process if the TestCase is a [BrowserTestCase]), creating a timeout 585 * process if the TestCase is a [BrowserTestCase]), creating a timeout
642 * timer, and recording the results in a new [CommandOutput] object, which it 586 * timer, and recording the results in a new [TestOutput] object, which it
643 * attaches to the TestCase. The lifetime of the RunningProcess is limited 587 * attaches to the TestCase. The lifetime of the RunningProcess is limited
644 * to the time it takes to start the process, run the process, and record 588 * to the time it takes to start the process, run the process, and record
645 * the result; there are no pointers to it, so it should be available to 589 * the result; there are no pointers to it, so it should be available to
646 * be garbage collected as soon as it is done. 590 * be garbage collected as soon as it is done.
647 */ 591 */
648 class RunningProcess { 592 class RunningProcess {
649 ProcessQueue processQueue; 593 ProcessQueue processQueue;
650 Process process; 594 Process process;
651 TestCase testCase; 595 TestCase testCase;
652 bool timedOut = false; 596 bool timedOut = false;
653 Date startTime; 597 Date startTime;
654 Timer timeoutTimer; 598 Timer timeoutTimer;
655 List<String> stdout; 599 List<String> stdout;
656 List<String> stderr; 600 List<String> stderr;
657 bool allowRetries; 601 bool allowRetries;
658 602
659 /** Which command of [testCase.commands] is currently being executed. */ 603 /** Which command of [testCase.commands] is currently being executed. */
660 int currentStep; 604 int currentStep;
661 605
662 RunningProcess(TestCase this.testCase, 606 RunningProcess(TestCase this.testCase,
663 [this.allowRetries = false, this.processQueue]); 607 [this.allowRetries = false, this.processQueue]);
664 608
665 /** 609 /**
666 * Called when all commands are executed. [exitCode] is 0 if all command 610 * Called when all commands are executed. [exitCode] is 0 if all command
667 * succeded, otherwise it will have the exit code of the first failing 611 * succeded, otherwise it will have the exit code of the first failing
668 * command. 612 * command.
669 */ 613 */
670 void testComplete(Command lastCommand, int exitCode, bool incomplete) { 614 void testComplete(int exitCode, bool incomplete) {
671 var lastCommandOutput = 615 new TestOutput.fromCase(testCase, exitCode, incomplete, timedOut, stdout,
672 new CommandOutput.fromCase(testCase, 616 stderr, new Date.now().difference(startTime));
673 lastCommand,
674 exitCode,
675 incomplete,
676 timedOut,
677 stdout,
678 stderr,
679 new Date.now().difference(startTime));
680 timeoutTimer.cancel(); 617 timeoutTimer.cancel();
681 if (lastCommandOutput.unexpectedOutput 618 if (testCase.output.unexpectedOutput
682 && testCase.configuration['verbose'] != null 619 && testCase.configuration['verbose'] != null
683 && testCase.configuration['verbose']) { 620 && testCase.configuration['verbose']) {
684 print(testCase.displayName); 621 print(testCase.displayName);
685 for (var line in lastCommandOutput.stderr) print(line); 622 for (var line in testCase.output.stderr) print(line);
686 for (var line in lastCommandOutput.stdout) print(line); 623 for (var line in testCase.output.stdout) print(line);
687 } 624 }
688 if (allowRetries && testCase.usesWebDriver 625 if (allowRetries && testCase.usesWebDriver
689 && lastCommandOutput.unexpectedOutput 626 && testCase.output.unexpectedOutput
690 && (testCase as BrowserTestCase).numRetries > 0) { 627 && (testCase as BrowserTestCase).numRetries > 0) {
691 // Selenium tests can be flaky. Try rerunning. 628 // Selenium tests can be flaky. Try rerunning.
692 lastCommandOutput.requestRetry = true; 629 testCase.output.requestRetry = true;
693 } 630 }
694 if (lastCommandOutput.requestRetry) { 631 if (testCase.output.requestRetry) {
695 lastCommandOutput.requestRetry = false; 632 testCase.output.requestRetry = false;
696 this.timedOut = false; 633 this.timedOut = false;
697 (testCase as BrowserTestCase).numRetries--; 634 (testCase as BrowserTestCase).numRetries--;
698 print("Potential flake. Re-running ${testCase.displayName} " 635 print("Potential flake. Re-running ${testCase.displayName} "
699 "(${(testCase as BrowserTestCase).numRetries} attempt(s) remains)"); 636 "(${(testCase as BrowserTestCase).numRetries} attempt(s) remains)");
700 // When retrying we need to reset the timeout as well. 637 // When retrying we need to reset the timeout as well.
701 // Otherwise there will be no timeout handling for the retry. 638 // Otherwise there will be no timeout handling for the retry.
702 timeoutTimer = null; 639 timeoutTimer = null;
703 this.start(); 640 this.start();
704 } else { 641 } else {
705 testCase.completed(); 642 testCase.completed();
706 } 643 }
707 } 644 }
708 645
709 /** 646 /**
710 * Process exit handler called at the end of every command. It internally 647 * Process exit handler called at the end of every command. It internally
711 * treats all but the last command as compilation steps. The last command is 648 * treats all but the last command as compilation steps. The last command is
712 * the actual test and its output is analyzed in [testComplete]. 649 * the actual test and its output is analyzed in [testComplete].
713 */ 650 */
714 void commandComplete(Command command, int exitCode) { 651 void stepExitHandler(int exitCode) {
715 process = null; 652 process = null;
716 int totalSteps = testCase.commands.length; 653 int totalSteps = testCase.commands.length;
717 String suffix =' (step $currentStep of $totalSteps)'; 654 String suffix =' (step $currentStep of $totalSteps)';
718 if (timedOut) { 655 if (timedOut) {
719 // Non-webdriver test timed out before it could complete. Webdriver tests 656 // Non-webdriver test timed out before it could complete. Webdriver tests
720 // run their own timeouts by timing from the launch of the browser (which 657 // run their own timeouts by timing from the launch of the browser (which
721 // could be delayed). 658 // could be delayed).
722 testComplete(command, 0, true); 659 testComplete(0, true);
723 } else if (currentStep == totalSteps) { 660 } else if (currentStep == totalSteps) {
724 // Done with all test commands. 661 // Done with all test commands.
725 testComplete(command, exitCode, false); 662 testComplete(exitCode, false);
726 } else if (exitCode != 0) { 663 } else if (exitCode != 0) {
727 // One of the steps failed. 664 // One of the steps failed.
728 stderr.add('test.dart: Compilation failed$suffix, exit code $exitCode\n'); 665 stderr.add('test.dart: Compilation failed$suffix, exit code $exitCode\n');
729 testComplete(command, exitCode, true); 666 testComplete(exitCode, true);
730 } else { 667 } else {
731 // One compilation step successfully completed, move on to the 668 // One compilation step successfully completed, move on to the
732 // next step. 669 // next step.
733 stderr.add('test.dart: Compilation finished $suffix\n'); 670 stderr.add('test.dart: Compilation finished $suffix\n');
734 stdout.add('test.dart: Compilation finished $suffix\n'); 671 stdout.add('test.dart: Compilation finished $suffix\n');
735 if (currentStep == totalSteps - 1 && testCase.usesWebDriver && 672 if (currentStep == totalSteps - 1 && testCase.usesWebDriver &&
736 !testCase.configuration['noBatch']) { 673 !testCase.configuration['noBatch']) {
737 // Note: processQueue will always be non-null for runtime == ie9, ie10, 674 // Note: processQueue will always be non-null for runtime == ie9, ie10,
738 // ff, safari, chrome, opera. (It is only null for runtime == vm) 675 // ff, safari, chrome, opera. (It is only null for runtime == vm)
739 // This RunningProcess object is done, and hands over control to 676 // This RunningProcess object is done, and hands over control to
740 // BatchRunner.startTest(), which handles reporting, etc. 677 // BatchRunner.startTest(), which handles reporting, etc.
741 timeoutTimer.cancel(); 678 timeoutTimer.cancel();
742 processQueue._getBatchRunner(testCase).startTest(testCase); 679 processQueue._getBatchRunner(testCase).startTest(testCase);
743 } else { 680 } else {
744 runCommand(testCase.commands[currentStep++], commandComplete); 681 runCommand(testCase.commands[currentStep++], stepExitHandler);
745 } 682 }
746 } 683 }
747 } 684 }
748 685
749 VoidFunction makeReadHandler(StringInputStream source, 686 VoidFunction makeReadHandler(StringInputStream source,
750 List<String> destination) { 687 List<String> destination) {
751 void handler () { 688 void handler () {
752 if (source.closed) return; // TODO(whesse): Remove when bug is fixed. 689 if (source.closed) return; // TODO(whesse): Remove when bug is fixed.
753 var line = source.readLine(); 690 var line = source.readLine();
754 while (null != line) { 691 while (null != line) {
755 destination.add(line); 692 destination.add(line);
756 line = source.readLine(); 693 line = source.readLine();
757 } 694 }
758 } 695 }
759 return handler; 696 return handler;
760 } 697 }
761 698
762 void start() { 699 void start() {
763 Expect.isFalse(testCase.expectedOutcomes.contains(SKIP)); 700 Expect.isFalse(testCase.expectedOutcomes.contains(SKIP));
764 stdout = new List<String>(); 701 stdout = new List<String>();
765 stderr = new List<String>(); 702 stderr = new List<String>();
766 currentStep = 0; 703 currentStep = 0;
767 startTime = new Date.now(); 704 startTime = new Date.now();
768 runCommand(testCase.commands[currentStep++], commandComplete); 705 runCommand(testCase.commands[currentStep++], stepExitHandler);
769 } 706 }
770 707
771 void runCommand(Command command, void commandCompleteHandler(Command, int)) { 708 void runCommand(Command command, void exitHandler(int exitCode)) {
772 void processExitHandler(int returnCode) {
773 commandCompleteHandler(command, returnCode);
774 }
775
776 Future processFuture = Process.start(command.executable, command.arguments); 709 Future processFuture = Process.start(command.executable, command.arguments);
777 processFuture.then((Process p) { 710 processFuture.then((Process p) {
778 process = p; 711 process = p;
779 process.onExit = processExitHandler; 712 process.onExit = exitHandler;
780 var stdoutStringStream = new StringInputStream(process.stdout); 713 var stdoutStringStream = new StringInputStream(process.stdout);
781 var stderrStringStream = new StringInputStream(process.stderr); 714 var stderrStringStream = new StringInputStream(process.stderr);
782 stdoutStringStream.onLine = 715 stdoutStringStream.onLine =
783 makeReadHandler(stdoutStringStream, stdout); 716 makeReadHandler(stdoutStringStream, stdout);
784 stderrStringStream.onLine = 717 stderrStringStream.onLine =
785 makeReadHandler(stderrStringStream, stderr); 718 makeReadHandler(stderrStringStream, stderr);
786 if (timeoutTimer == null) { 719 if (timeoutTimer == null) {
787 // Create one timeout timer when starting test case, remove it at end. 720 // Create one timeout timer when starting test case, remove it at end.
788 timeoutTimer = new Timer(1000 * testCase.timeout, timeoutHandler); 721 timeoutTimer = new Timer(1000 * testCase.timeout, timeoutHandler);
789 } 722 }
790 // If the timeout fired in between two commands, kill the just 723 // If the timeout fired in between two commands, kill the just
791 // started process immediately. 724 // started process immediately.
792 if (timedOut) safeKill(process); 725 if (timedOut) safeKill(process);
793 }); 726 });
794 processFuture.handleException((e) { 727 processFuture.handleException((e) {
795 print("Process error:"); 728 print("Process error:");
796 print(" Command: $command"); 729 print(" Command: $command");
797 print(" Error: $e"); 730 print(" Error: $e");
798 testComplete(command, -1, false); 731 testComplete(-1, false);
799 return true; 732 return true;
800 }); 733 });
801 } 734 }
802 735
803 void timeoutHandler(Timer unusedTimer) { 736 void timeoutHandler(Timer unusedTimer) {
804 timedOut = true; 737 timedOut = true;
805 safeKill(process); 738 safeKill(process);
806 } 739 }
807 740
808 void safeKill(Process p) { 741 void safeKill(Process p) {
(...skipping 10 matching lines...) Expand all
819 /** 752 /**
820 * This class holds a value, that can be changed. It is used when 753 * This class holds a value, that can be changed. It is used when
821 * closures need a shared value, that they can all change and read. 754 * closures need a shared value, that they can all change and read.
822 */ 755 */
823 class MutableValue<T> { 756 class MutableValue<T> {
824 MutableValue(T this.value); 757 MutableValue(T this.value);
825 T value; 758 T value;
826 } 759 }
827 760
828 class BatchRunnerProcess { 761 class BatchRunnerProcess {
829 Command _command;
830 String _executable; 762 String _executable;
831 List<String> _batchArguments; 763 List<String> _batchArguments;
832 764
833 Process _process; 765 Process _process;
834 StringInputStream _stdoutStream; 766 StringInputStream _stdoutStream;
835 StringInputStream _stderrStream; 767 StringInputStream _stderrStream;
836 768
837 TestCase _currentTest; 769 TestCase _currentTest;
838 List<String> _testStdout; 770 List<String> _testStdout;
839 List<String> _testStderr; 771 List<String> _testStderr;
840 String _status; 772 String _status;
841 bool _stdoutDrained = false; 773 bool _stdoutDrained = false;
842 bool _stderrDrained = false; 774 bool _stderrDrained = false;
843 MutableValue<bool> _ignoreStreams; 775 MutableValue<bool> _ignoreStreams;
844 Date _startTime; 776 Date _startTime;
845 Timer _timer; 777 Timer _timer;
846 778
847 bool _isWebDriver; 779 bool _isWebDriver;
848 780
849 BatchRunnerProcess(TestCase testCase) { 781 BatchRunnerProcess(TestCase testCase) {
850 _command = testCase.commands.last;
851 _executable = testCase.commands.last.executable; 782 _executable = testCase.commands.last.executable;
852 _batchArguments = testCase.batchRunnerArguments; 783 _batchArguments = testCase.batchRunnerArguments;
853 _isWebDriver = testCase.usesWebDriver; 784 _isWebDriver = testCase.usesWebDriver;
854 } 785 }
855 786
856 bool get active => _currentTest != null; 787 bool get active => _currentTest != null;
857 788
858 void startTest(TestCase testCase) { 789 void startTest(TestCase testCase) {
859 Expect.isNull(_currentTest); 790 Expect.isNull(_currentTest);
860 _currentTest = testCase; 791 _currentTest = testCase;
861 _command = testCase.commands.last;
862 if (_process == null) { 792 if (_process == null) {
863 // Start process if not yet started. 793 // Start process if not yet started.
864 _executable = testCase.commands.last.executable; 794 _executable = testCase.commands.last.executable;
865 _startProcess(() { 795 _startProcess(() {
866 doStartTest(testCase); 796 doStartTest(testCase);
867 }); 797 });
868 } else if (testCase.commands.last.executable != _executable) { 798 } else if (testCase.commands.last.executable != _executable) {
869 // Restart this runner with the right executable for this test 799 // Restart this runner with the right executable for this test
870 // if needed. 800 // if needed.
871 _executable = testCase.commands.last.executable; 801 _executable = testCase.commands.last.executable;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
932 } 862 }
933 863
934 void _reportResult() { 864 void _reportResult() {
935 if (!active) return; 865 if (!active) return;
936 // _status == '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' 866 // _status == '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}'
937 867
938 var outcome = _status.split(" ")[2]; 868 var outcome = _status.split(" ")[2];
939 var exitCode = 0; 869 var exitCode = 0;
940 if (outcome == "CRASH") exitCode = -10; 870 if (outcome == "CRASH") exitCode = -10;
941 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; 871 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1;
942 new CommandOutput.fromCase(_currentTest, 872 new TestOutput.fromCase(_currentTest, exitCode, false,
943 _command, 873 (outcome == "TIMEOUT"),
944 exitCode, 874 _testStdout, _testStderr,
945 false, 875 new Date.now().difference(_startTime));
946 (outcome == "TIMEOUT"),
947 _testStdout,
948 _testStderr,
949 new Date.now().difference(_startTime));
950 var test = _currentTest; 876 var test = _currentTest;
951 _currentTest = null; 877 _currentTest = null;
952 test.completed(); 878 test.completed();
953 } 879 }
954 880
955 void _stderrDone() { 881 void _stderrDone() {
956 _stderrDrained = true; 882 _stderrDrained = true;
957 // Move on when both stdout and stderr has been drained. 883 // Move on when both stdout and stderr has been drained.
958 if (_stdoutDrained) _reportResult(); 884 if (_stdoutDrained) _reportResult();
959 } 885 }
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
1404 // the developer doesn't waste his or her time trying to fix a bunch of 1330 // the developer doesn't waste his or her time trying to fix a bunch of
1405 // tests that appear to be broken but were actually just flakes that 1331 // tests that appear to be broken but were actually just flakes that
1406 // didn't get retried because there had already been one failure. 1332 // didn't get retried because there had already been one failure.
1407 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; 1333 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests;
1408 new RunningProcess(test, allowRetry, this).start(); 1334 new RunningProcess(test, allowRetry, this).start();
1409 } 1335 }
1410 _numProcesses++; 1336 _numProcesses++;
1411 } 1337 }
1412 } 1338 }
1413 } 1339 }
OLDNEW
« no previous file with comments | « tools/testing/dart/test_progress.dart ('k') | tools/testing/dart/test_suite.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698