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

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

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