| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Classes and methods for executing tests. | 6 * Classes and methods for executing tests. |
| 7 * | 7 * |
| 8 * This module includes: | 8 * This module includes: |
| 9 * - Managing parallel execution of tests, including timeout checks. | 9 * - Managing parallel execution of tests, including timeout checks. |
| 10 * - Evaluating the output of each test as pass/fail/crash/timeout. | 10 * - Evaluating the output of each test as pass/fail/crash/timeout. |
| 11 */ | 11 */ |
| 12 #library("test_runner"); | 12 #library("test_runner"); |
| 13 | 13 |
| 14 #import("dart:io"); | 14 #import("dart:io"); |
| 15 #import("dart:isolate"); | 15 #import("dart:isolate"); |
| 16 #import("dart:uri"); | |
| 17 #import("status_file_parser.dart"); | 16 #import("status_file_parser.dart"); |
| 18 #import("test_progress.dart"); | 17 #import("test_progress.dart"); |
| 19 #import("test_suite.dart"); | 18 #import("test_suite.dart"); |
| 20 | 19 |
| 21 const int NO_TIMEOUT = 0; | 20 const int NO_TIMEOUT = 0; |
| 22 const int SLOW_TIMEOUT_MULTIPLIER = 4; | 21 const int SLOW_TIMEOUT_MULTIPLIER = 4; |
| 23 | 22 |
| 24 typedef void TestCaseEvent(TestCase testCase); | 23 typedef void TestCaseEvent(TestCase testCase); |
| 25 typedef void ExitCodeEvent(int exitCode); | 24 typedef void ExitCodeEvent(int exitCode); |
| 26 typedef void EnqueueMoreWork(ProcessQueue queue); | 25 typedef void EnqueueMoreWork(ProcessQueue queue); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 40 if (Platform.operatingSystem == 'windows') { | 39 if (Platform.operatingSystem == 'windows') { |
| 41 // Windows can't handle the first command if it is a .bat file or the like | 40 // Windows can't handle the first command if it is a .bat file or the like |
| 42 // with the slashes going the other direction. | 41 // with the slashes going the other direction. |
| 43 // TODO(efortuna): Remove this when fixed (Issue 1306). | 42 // TODO(efortuna): Remove this when fixed (Issue 1306). |
| 44 executable = executable.replaceAll('/', '\\'); | 43 executable = executable.replaceAll('/', '\\'); |
| 45 } | 44 } |
| 46 commandLine = "$executable ${Strings.join(arguments, ' ')}"; | 45 commandLine = "$executable ${Strings.join(arguments, ' ')}"; |
| 47 } | 46 } |
| 48 | 47 |
| 49 String toString() => commandLine; | 48 String toString() => commandLine; |
| 50 | |
| 51 Future<bool> get outputIsUpToDate => new Future.immediate(false); | |
| 52 } | |
| 53 | |
| 54 class Dart2JsCommand extends Command { | |
| 55 String _jsOutputFile; | |
| 56 bool _neverSkipCompilation; | |
| 57 List<Uri> _bootstrapDependencies; | |
| 58 | |
| 59 Dart2JsCommand(this._jsOutputFile, | |
| 60 this._neverSkipCompilation, | |
| 61 this._bootstrapDependencies, | |
| 62 String executable, | |
| 63 List<String> arguments) | |
| 64 : super(executable, arguments); | |
| 65 | |
| 66 Future<bool> get outputIsUpToDate { | |
| 67 if (_neverSkipCompilation) return new Future.immediate(false); | |
| 68 | |
| 69 Future<List<Uri>> readDepsFile(String path) { | |
| 70 var file = new File(new Path(path).toNativePath()); | |
| 71 if (!file.existsSync()) { | |
| 72 return new Future.immediate(null); | |
| 73 } | |
| 74 return file.readAsLines().transform((List<String> lines) { | |
| 75 var dependencies = new List<Uri>(); | |
| 76 for (var line in lines) { | |
| 77 line = line.trim(); | |
| 78 if (line.length > 0) { | |
| 79 dependencies.add(new Uri(line)); | |
| 80 } | |
| 81 } | |
| 82 return dependencies; | |
| 83 }); | |
| 84 } | |
| 85 | |
| 86 return readDepsFile("$_jsOutputFile.deps").transform((dependencies) { | |
| 87 if (dependencies != null) { | |
| 88 dependencies.addAll(_bootstrapDependencies); | |
| 89 var jsOutputLastModified = TestUtils.lastModifiedCache.getLastModified( | |
| 90 new Uri.fromComponents(scheme: 'file', path: _jsOutputFile)); | |
| 91 if (jsOutputLastModified != null) { | |
| 92 for (var dependency in dependencies) { | |
| 93 var dependencyLastModified = | |
| 94 TestUtils.lastModifiedCache.getLastModified(dependency); | |
| 95 if (dependencyLastModified == null || | |
| 96 dependencyLastModified > jsOutputLastModified) { | |
| 97 return false; | |
| 98 } | |
| 99 } | |
| 100 return true; | |
| 101 } | |
| 102 } | |
| 103 return false; | |
| 104 }); | |
| 105 } | |
| 106 } | 49 } |
| 107 | 50 |
| 108 /** | 51 /** |
| 109 * 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 |
| 110 * its output. Running a test involves starting a separate process, with | 53 * its output. Running a test involves starting a separate process, with |
| 111 * the executable and arguments given by the TestCase, and recording its | 54 * the executable and arguments given by the TestCase, and recording its |
| 112 * stdout and stderr output streams, and its exit code. TestCase only | 55 * stdout and stderr output streams, and its exit code. TestCase only |
| 113 * contains static information about the test; actually running the test is | 56 * contains static information about the test; actually running the test is |
| 114 * performed by [ProcessQueue] using a [RunningProcess] object. | 57 * performed by [ProcessQueue] using a [RunningProcess] object. |
| 115 * | 58 * |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 * [TestCase] this is the output of. | 255 * [TestCase] this is the output of. |
| 313 */ | 256 */ |
| 314 abstract class CommandOutput { | 257 abstract class CommandOutput { |
| 315 factory CommandOutput.fromCase(TestCase testCase, | 258 factory CommandOutput.fromCase(TestCase testCase, |
| 316 Command command, | 259 Command command, |
| 317 int exitCode, | 260 int exitCode, |
| 318 bool incomplete, | 261 bool incomplete, |
| 319 bool timedOut, | 262 bool timedOut, |
| 320 List<String> stdout, | 263 List<String> stdout, |
| 321 List<String> stderr, | 264 List<String> stderr, |
| 322 Duration time, | 265 Duration time) { |
| 323 bool compilationSkipped) { | |
| 324 return new CommandOutputImpl.fromCase(testCase, | 266 return new CommandOutputImpl.fromCase(testCase, |
| 325 command, | 267 command, |
| 326 exitCode, | 268 exitCode, |
| 327 incomplete, | 269 incomplete, |
| 328 timedOut, | 270 timedOut, |
| 329 stdout, | 271 stdout, |
| 330 stderr, | 272 stderr, |
| 331 time, | 273 time); |
| 332 compilationSkipped); | |
| 333 } | 274 } |
| 334 | 275 |
| 335 bool get incomplete; | 276 bool get incomplete; |
| 336 | 277 |
| 337 String get result; | 278 String get result; |
| 338 | 279 |
| 339 bool get unexpectedOutput; | 280 bool get unexpectedOutput; |
| 340 | 281 |
| 341 bool get hasCrashed; | 282 bool get hasCrashed; |
| 342 | 283 |
| 343 bool get hasTimedOut; | 284 bool get hasTimedOut; |
| 344 | 285 |
| 345 bool get didFail; | 286 bool get didFail; |
| 346 | 287 |
| 347 bool requestRetry; | 288 bool requestRetry; |
| 348 | 289 |
| 349 Duration get time; | 290 Duration get time; |
| 350 | 291 |
| 351 int get exitCode; | 292 int get exitCode; |
| 352 | 293 |
| 353 List<String> get stdout; | 294 List<String> get stdout; |
| 354 | 295 |
| 355 List<String> get stderr; | 296 List<String> get stderr; |
| 356 | 297 |
| 357 List<String> get diagnostics; | 298 List<String> get diagnostics; |
| 358 | |
| 359 bool get compilationSkipped; | |
| 360 } | 299 } |
| 361 | 300 |
| 362 class CommandOutputImpl implements CommandOutput { | 301 class CommandOutputImpl implements CommandOutput { |
| 363 TestCase testCase; | 302 TestCase testCase; |
| 364 int exitCode; | 303 int exitCode; |
| 365 | 304 |
| 366 /// Records if all commands were run, true if they weren't. | 305 /// Records if all commands were run, true if they weren't. |
| 367 final bool incomplete; | 306 final bool incomplete; |
| 368 | 307 |
| 369 bool timedOut; | 308 bool timedOut; |
| 370 bool failed = false; | 309 bool failed = false; |
| 371 List<String> stdout; | 310 List<String> stdout; |
| 372 List<String> stderr; | 311 List<String> stderr; |
| 373 Duration time; | 312 Duration time; |
| 374 List<String> diagnostics; | 313 List<String> diagnostics; |
| 375 bool compilationSkipped; | |
| 376 | 314 |
| 377 /** | 315 /** |
| 378 * A flag to indicate we have already printed a warning about ignoring the VM | 316 * A flag to indicate we have already printed a warning about ignoring the VM |
| 379 * crash, to limit the amount of output produced per test. | 317 * crash, to limit the amount of output produced per test. |
| 380 */ | 318 */ |
| 381 bool alreadyPrintedWarning = false; | 319 bool alreadyPrintedWarning = false; |
| 382 | 320 |
| 383 /** | 321 /** |
| 384 * Set to true if we encounter a condition in the output that indicates we | 322 * Set to true if we encounter a condition in the output that indicates we |
| 385 * need to rerun this test. | 323 * need to rerun this test. |
| 386 */ | 324 */ |
| 387 bool requestRetry = false; | 325 bool requestRetry = false; |
| 388 | 326 |
| 389 // Don't call this constructor, call CommandOutput.fromCase() to | 327 // Don't call this constructor, call CommandOutput.fromCase() to |
| 390 // get a new TestOutput instance. | 328 // get a new TestOutput instance. |
| 391 CommandOutputImpl(TestCase this.testCase, | 329 CommandOutputImpl(TestCase this.testCase, |
| 392 Command command, | 330 Command command, |
| 393 int this.exitCode, | 331 int this.exitCode, |
| 394 bool this.incomplete, | 332 bool this.incomplete, |
| 395 bool this.timedOut, | 333 bool this.timedOut, |
| 396 List<String> this.stdout, | 334 List<String> this.stdout, |
| 397 List<String> this.stderr, | 335 List<String> this.stderr, |
| 398 Duration this.time, | 336 Duration this.time) { |
| 399 bool this.compilationSkipped) { | |
| 400 testCase.commandOutputs[command] = this; | 337 testCase.commandOutputs[command] = this; |
| 401 diagnostics = []; | 338 diagnostics = []; |
| 402 } | 339 } |
| 403 factory CommandOutputImpl.fromCase(TestCase testCase, | 340 factory CommandOutputImpl.fromCase(TestCase testCase, |
| 404 Command command, | 341 Command command, |
| 405 int exitCode, | 342 int exitCode, |
| 406 bool incomplete, | 343 bool incomplete, |
| 407 bool timedOut, | 344 bool timedOut, |
| 408 List<String> stdout, | 345 List<String> stdout, |
| 409 List<String> stderr, | 346 List<String> stderr, |
| 410 Duration time, | 347 Duration time) { |
| 411 bool compilationSkipped) { | |
| 412 if (testCase is BrowserTestCase) { | 348 if (testCase is BrowserTestCase) { |
| 413 return new BrowserCommandOutputImpl(testCase, | 349 return new BrowserCommandOutputImpl(testCase, |
| 414 command, | 350 command, |
| 415 exitCode, | 351 exitCode, |
| 416 incomplete, | 352 incomplete, |
| 417 timedOut, | 353 timedOut, |
| 418 stdout, | 354 stdout, |
| 419 stderr, | 355 stderr, |
| 420 time, | 356 time); |
| 421 compilationSkipped); | |
| 422 } else if (testCase.configuration['compiler'] == 'dartc') { | 357 } else if (testCase.configuration['compiler'] == 'dartc') { |
| 423 return new AnalysisCommandOutputImpl(testCase, | 358 return new AnalysisCommandOutputImpl(testCase, |
| 424 command, | 359 command, |
| 425 exitCode, | 360 exitCode, |
| 426 timedOut, | 361 timedOut, |
| 427 stdout, | 362 stdout, |
| 428 stderr, | 363 stderr, |
| 429 time, | 364 time); |
| 430 compilationSkipped); | |
| 431 } | 365 } |
| 432 return new CommandOutputImpl(testCase, | 366 return new CommandOutputImpl(testCase, |
| 433 command, | 367 command, |
| 434 exitCode, | 368 exitCode, |
| 435 incomplete, | 369 incomplete, |
| 436 timedOut, | 370 timedOut, |
| 437 stdout, | 371 stdout, |
| 438 stderr, | 372 stderr, |
| 439 time, | 373 time); |
| 440 compilationSkipped); | |
| 441 } | 374 } |
| 442 | 375 |
| 443 String get result => | 376 String get result => |
| 444 hasCrashed ? CRASH : (hasTimedOut ? TIMEOUT : (hasFailed ? FAIL : PASS)); | 377 hasCrashed ? CRASH : (hasTimedOut ? TIMEOUT : (hasFailed ? FAIL : PASS)); |
| 445 | 378 |
| 446 bool get unexpectedOutput => !testCase.expectedOutcomes.contains(result); | 379 bool get unexpectedOutput => !testCase.expectedOutcomes.contains(result); |
| 447 | 380 |
| 448 bool get hasCrashed { | 381 bool get hasCrashed { |
| 449 // The Java dartc runner and dart2js exits with code 253 in case | 382 // The Java dartc runner and dart2js exits with code 253 in case |
| 450 // of unhandled exceptions. | 383 // of unhandled exceptions. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 479 | 412 |
| 480 class BrowserCommandOutputImpl extends CommandOutputImpl { | 413 class BrowserCommandOutputImpl extends CommandOutputImpl { |
| 481 BrowserCommandOutputImpl( | 414 BrowserCommandOutputImpl( |
| 482 testCase, | 415 testCase, |
| 483 command, | 416 command, |
| 484 exitCode, | 417 exitCode, |
| 485 incomplete, | 418 incomplete, |
| 486 timedOut, | 419 timedOut, |
| 487 stdout, | 420 stdout, |
| 488 stderr, | 421 stderr, |
| 489 time, | 422 time) : |
| 490 compilationSkipped) : | |
| 491 super(testCase, | 423 super(testCase, |
| 492 command, | 424 command, |
| 493 exitCode, | 425 exitCode, |
| 494 incomplete, | 426 incomplete, |
| 495 timedOut, | 427 timedOut, |
| 496 stdout, | 428 stdout, |
| 497 stderr, | 429 stderr, |
| 498 time, | 430 time); |
| 499 compilationSkipped); | |
| 500 | 431 |
| 501 bool get didFail { | 432 bool get didFail { |
| 502 // Browser case: | 433 // Browser case: |
| 503 // If the browser test failed, it may have been because DumpRenderTree | 434 // If the browser test failed, it may have been because DumpRenderTree |
| 504 // and the virtual framebuffer X server didn't hook up, or DRT crashed with | 435 // and the virtual framebuffer X server didn't hook up, or DRT crashed with |
| 505 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS, | 436 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS, |
| 506 // so we have to do this check first. | 437 // so we have to do this check first. |
| 507 for (String line in super.stderr) { | 438 for (String line in super.stderr) { |
| 508 if (line.contains('Gtk-WARNING **: cannot open display: :99') || | 439 if (line.contains('Gtk-WARNING **: cannot open display: :99') || |
| 509 line.contains('Failed to run command. return code=1')) { | 440 line.contains('Failed to run command. return code=1')) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 // to stderr. | 472 // to stderr. |
| 542 class AnalysisCommandOutputImpl extends CommandOutputImpl { | 473 class AnalysisCommandOutputImpl extends CommandOutputImpl { |
| 543 // An error line has 8 fields that look like: | 474 // An error line has 8 fields that look like: |
| 544 // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source. | 475 // ERROR|COMPILER|MISSING_SOURCE|file:/tmp/t.dart|15|1|24|Missing source. |
| 545 final int ERROR_LEVEL = 0; | 476 final int ERROR_LEVEL = 0; |
| 546 final int ERROR_TYPE = 1; | 477 final int ERROR_TYPE = 1; |
| 547 final int FORMATTED_ERROR = 7; | 478 final int FORMATTED_ERROR = 7; |
| 548 | 479 |
| 549 bool alreadyComputed = false; | 480 bool alreadyComputed = false; |
| 550 bool failResult; | 481 bool failResult; |
| 551 | |
| 552 AnalysisCommandOutputImpl(testCase, | 482 AnalysisCommandOutputImpl(testCase, |
| 553 command, | 483 command, |
| 554 exitCode, | 484 exitCode, |
| 555 timedOut, | 485 timedOut, |
| 556 stdout, | 486 stdout, |
| 557 stderr, | 487 stderr, |
| 558 time, | 488 time) : |
| 559 compilationSkipped) : | 489 super(testCase, command, exitCode, false, timedOut, stdout, stderr, time); |
| 560 super(testCase, | |
| 561 command, | |
| 562 exitCode, | |
| 563 false, | |
| 564 timedOut, | |
| 565 stdout, | |
| 566 stderr, | |
| 567 time, | |
| 568 compilationSkipped); | |
| 569 | 490 |
| 570 bool get didFail { | 491 bool get didFail { |
| 571 if (!alreadyComputed) { | 492 if (!alreadyComputed) { |
| 572 failResult = _didFail(); | 493 failResult = _didFail(); |
| 573 alreadyComputed = true; | 494 alreadyComputed = true; |
| 574 } | 495 } |
| 575 return failResult; | 496 return failResult; |
| 576 } | 497 } |
| 577 | 498 |
| 578 bool _didFail() { | 499 bool _didFail() { |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 */ | 647 */ |
| 727 class RunningProcess { | 648 class RunningProcess { |
| 728 ProcessQueue processQueue; | 649 ProcessQueue processQueue; |
| 729 Process process; | 650 Process process; |
| 730 TestCase testCase; | 651 TestCase testCase; |
| 731 bool timedOut = false; | 652 bool timedOut = false; |
| 732 Date startTime; | 653 Date startTime; |
| 733 Timer timeoutTimer; | 654 Timer timeoutTimer; |
| 734 List<String> stdout; | 655 List<String> stdout; |
| 735 List<String> stderr; | 656 List<String> stderr; |
| 736 bool compilationSkipped; | |
| 737 bool allowRetries; | 657 bool allowRetries; |
| 738 | 658 |
| 739 /** Which command of [testCase.commands] is currently being executed. */ | 659 /** Which command of [testCase.commands] is currently being executed. */ |
| 740 int currentStep; | 660 int currentStep; |
| 741 | 661 |
| 742 RunningProcess(TestCase this.testCase, | 662 RunningProcess(TestCase this.testCase, |
| 743 [this.allowRetries = false, this.processQueue]); | 663 [this.allowRetries = false, this.processQueue]); |
| 744 | 664 |
| 745 /** | 665 /** |
| 746 * Called when all commands are executed. | 666 * Called when all commands are executed. |
| 747 */ | 667 */ |
| 748 void testComplete(CommandOutput lastCommandOutput) { | 668 void testComplete(CommandOutput lastCommandOutput) { |
| 749 if (timeoutTimer != null) { | 669 timeoutTimer.cancel(); |
| 750 timeoutTimer.cancel(); | |
| 751 } | |
| 752 if (lastCommandOutput.unexpectedOutput | 670 if (lastCommandOutput.unexpectedOutput |
| 753 && testCase.configuration['verbose'] != null | 671 && testCase.configuration['verbose'] != null |
| 754 && testCase.configuration['verbose']) { | 672 && testCase.configuration['verbose']) { |
| 755 print(testCase.displayName); | 673 print(testCase.displayName); |
| 756 for (var line in lastCommandOutput.stderr) print(line); | 674 for (var line in lastCommandOutput.stderr) print(line); |
| 757 for (var line in lastCommandOutput.stdout) print(line); | 675 for (var line in lastCommandOutput.stdout) print(line); |
| 758 } | 676 } |
| 759 if (allowRetries && testCase.usesWebDriver | 677 if (allowRetries && testCase.usesWebDriver |
| 760 && lastCommandOutput.unexpectedOutput | 678 && lastCommandOutput.unexpectedOutput |
| 761 && (testCase as BrowserTestCase).numRetries > 0) { | 679 && (testCase as BrowserTestCase).numRetries > 0) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 // One compilation step successfully completed, move on to the | 721 // One compilation step successfully completed, move on to the |
| 804 // next step. | 722 // next step. |
| 805 stderr.add('test.dart: Compilation finished $suffix\n'); | 723 stderr.add('test.dart: Compilation finished $suffix\n'); |
| 806 stdout.add('test.dart: Compilation finished $suffix\n'); | 724 stdout.add('test.dart: Compilation finished $suffix\n'); |
| 807 if (currentStep == totalSteps - 1 && testCase.usesWebDriver && | 725 if (currentStep == totalSteps - 1 && testCase.usesWebDriver && |
| 808 !testCase.configuration['noBatch']) { | 726 !testCase.configuration['noBatch']) { |
| 809 // Note: processQueue will always be non-null for runtime == ie9, ie10, | 727 // Note: processQueue will always be non-null for runtime == ie9, ie10, |
| 810 // ff, safari, chrome, opera. (It is only null for runtime == vm) | 728 // ff, safari, chrome, opera. (It is only null for runtime == vm) |
| 811 // This RunningProcess object is done, and hands over control to | 729 // This RunningProcess object is done, and hands over control to |
| 812 // BatchRunner.startTest(), which handles reporting, etc. | 730 // BatchRunner.startTest(), which handles reporting, etc. |
| 813 if (timeoutTimer != null) { | 731 timeoutTimer.cancel(); |
| 814 timeoutTimer.cancel(); | |
| 815 } | |
| 816 processQueue._getBatchRunner(testCase).startTest(testCase); | 732 processQueue._getBatchRunner(testCase).startTest(testCase); |
| 817 } else { | 733 } else { |
| 818 runCommand(testCase.commands[currentStep++], commandComplete); | 734 runCommand(testCase.commands[currentStep++], commandComplete); |
| 819 } | 735 } |
| 820 } | 736 } |
| 821 } | 737 } |
| 822 | 738 |
| 823 /** | 739 /** |
| 824 * Called for all executed commands. | 740 * Called for all executed commands. |
| 825 */ | 741 */ |
| 826 CommandOutput createCommandOutput(Command command, | 742 CommandOutput createCommandOutput(Command command, |
| 827 int exitCode, | 743 int exitCode, |
| 828 bool incomplete) { | 744 bool incomplete) { |
| 829 var commandOutput = new CommandOutput.fromCase( | 745 var commandOutput = new CommandOutput.fromCase( |
| 830 testCase, | 746 testCase, |
| 831 command, | 747 command, |
| 832 exitCode, | 748 exitCode, |
| 833 incomplete, | 749 incomplete, |
| 834 timedOut, | 750 timedOut, |
| 835 stdout, | 751 stdout, |
| 836 stderr, | 752 stderr, |
| 837 new Date.now().difference(startTime), | 753 new Date.now().difference(startTime)); |
| 838 compilationSkipped); | |
| 839 resetLocalOutputInformation(); | 754 resetLocalOutputInformation(); |
| 840 return commandOutput; | 755 return commandOutput; |
| 841 } | 756 } |
| 842 | 757 |
| 843 void resetLocalOutputInformation() { | 758 void resetLocalOutputInformation() { |
| 844 stdout = new List<String>(); | 759 stdout = new List<String>(); |
| 845 stderr = new List<String>(); | 760 stderr = new List<String>(); |
| 846 compilationSkipped = false; | |
| 847 } | 761 } |
| 848 | 762 |
| 849 VoidFunction makeReadHandler(StringInputStream source, | 763 VoidFunction makeReadHandler(StringInputStream source, |
| 850 List<String> destination) { | 764 List<String> destination) { |
| 851 void handler () { | 765 void handler () { |
| 852 if (source.closed) return; // TODO(whesse): Remove when bug is fixed. | 766 if (source.closed) return; // TODO(whesse): Remove when bug is fixed. |
| 853 var line = source.readLine(); | 767 var line = source.readLine(); |
| 854 while (null != line) { | 768 while (null != line) { |
| 855 destination.add(line); | 769 destination.add(line); |
| 856 line = source.readLine(); | 770 line = source.readLine(); |
| 857 } | 771 } |
| 858 } | 772 } |
| 859 return handler; | 773 return handler; |
| 860 } | 774 } |
| 861 | 775 |
| 862 void start() { | 776 void start() { |
| 863 Expect.isFalse(testCase.expectedOutcomes.contains(SKIP)); | 777 Expect.isFalse(testCase.expectedOutcomes.contains(SKIP)); |
| 864 resetLocalOutputInformation(); | 778 resetLocalOutputInformation(); |
| 865 currentStep = 0; | 779 currentStep = 0; |
| 866 startTime = new Date.now(); | 780 startTime = new Date.now(); |
| 867 runCommand(testCase.commands[currentStep++], commandComplete); | 781 runCommand(testCase.commands[currentStep++], commandComplete); |
| 868 } | 782 } |
| 869 | 783 |
| 870 void runCommand(Command command, void commandCompleteHandler(Command, int)) { | 784 void runCommand(Command command, void commandCompleteHandler(Command, int)) { |
| 871 void processExitHandler(int returnCode) { | 785 void processExitHandler(int returnCode) { |
| 872 commandCompleteHandler(command, returnCode); | 786 commandCompleteHandler(command, returnCode); |
| 873 } | 787 } |
| 874 | 788 |
| 875 command.outputIsUpToDate.then((bool isUpToDate) { | 789 Future processFuture = Process.start(command.executable, command.arguments); |
| 876 if (isUpToDate) { | 790 processFuture.then((Process p) { |
| 877 stdout.add("Skipped compilation because the old output is " | 791 process = p; |
| 878 "still up to date!"); | 792 process.onExit = processExitHandler; |
| 879 compilationSkipped = true; | 793 var stdoutStringStream = new StringInputStream(process.stdout); |
| 880 commandComplete(command, 0); | 794 var stderrStringStream = new StringInputStream(process.stderr); |
| 881 } else { | 795 stdoutStringStream.onLine = |
| 882 Future processFuture = Process.start(command.executable, | 796 makeReadHandler(stdoutStringStream, stdout); |
| 883 command.arguments); | 797 stderrStringStream.onLine = |
| 884 processFuture.then((Process p) { | 798 makeReadHandler(stderrStringStream, stderr); |
| 885 process = p; | 799 if (timeoutTimer == null) { |
| 886 process.onExit = processExitHandler; | 800 // Create one timeout timer when starting test case, remove it at end. |
| 887 var stdoutStringStream = new StringInputStream(process.stdout); | 801 timeoutTimer = new Timer(1000 * testCase.timeout, timeoutHandler); |
| 888 var stderrStringStream = new StringInputStream(process.stderr); | |
| 889 stdoutStringStream.onLine = | |
| 890 makeReadHandler(stdoutStringStream, stdout); | |
| 891 stderrStringStream.onLine = | |
| 892 makeReadHandler(stderrStringStream, stderr); | |
| 893 if (timeoutTimer == null) { | |
| 894 // Create one timeout timer when starting test case, remove it at | |
| 895 // the end. | |
| 896 timeoutTimer = new Timer(1000 * testCase.timeout, timeoutHandler); | |
| 897 } | |
| 898 // If the timeout fired in between two commands, kill the just | |
| 899 // started process immediately. | |
| 900 if (timedOut) safeKill(process); | |
| 901 }); | |
| 902 processFuture.handleException((e) { | |
| 903 print("Process error:"); | |
| 904 print(" Command: $command"); | |
| 905 print(" Error: $e"); | |
| 906 testComplete(createCommandOutput(command, -1, false)); | |
| 907 return true; | |
| 908 }); | |
| 909 } | 802 } |
| 803 // If the timeout fired in between two commands, kill the just |
| 804 // started process immediately. |
| 805 if (timedOut) safeKill(process); |
| 806 }); |
| 807 processFuture.handleException((e) { |
| 808 print("Process error:"); |
| 809 print(" Command: $command"); |
| 810 print(" Error: $e"); |
| 811 testComplete(createCommandOutput(command, -1, false)); |
| 812 return true; |
| 910 }); | 813 }); |
| 911 } | 814 } |
| 912 | 815 |
| 913 void timeoutHandler(Timer unusedTimer) { | 816 void timeoutHandler(Timer unusedTimer) { |
| 914 timedOut = true; | 817 timedOut = true; |
| 915 safeKill(process); | 818 safeKill(process); |
| 916 } | 819 } |
| 917 | 820 |
| 918 void safeKill(Process p) { | 821 void safeKill(Process p) { |
| 919 if (p != null) { | 822 if (p != null) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 var exitCode = 0; | 952 var exitCode = 0; |
| 1050 if (outcome == "CRASH") exitCode = -10; | 953 if (outcome == "CRASH") exitCode = -10; |
| 1051 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; | 954 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; |
| 1052 new CommandOutput.fromCase(_currentTest, | 955 new CommandOutput.fromCase(_currentTest, |
| 1053 _command, | 956 _command, |
| 1054 exitCode, | 957 exitCode, |
| 1055 false, | 958 false, |
| 1056 (outcome == "TIMEOUT"), | 959 (outcome == "TIMEOUT"), |
| 1057 _testStdout, | 960 _testStdout, |
| 1058 _testStderr, | 961 _testStderr, |
| 1059 new Date.now().difference(_startTime), | 962 new Date.now().difference(_startTime)); |
| 1060 false); | |
| 1061 var test = _currentTest; | 963 var test = _currentTest; |
| 1062 _currentTest = null; | 964 _currentTest = null; |
| 1063 test.completed(); | 965 test.completed(); |
| 1064 } | 966 } |
| 1065 | 967 |
| 1066 void _stderrDone() { | 968 void _stderrDone() { |
| 1067 _stderrDrained = true; | 969 _stderrDrained = true; |
| 1068 // Move on when both stdout and stderr has been drained. | 970 // Move on when both stdout and stderr has been drained. |
| 1069 if (_stdoutDrained) _reportResult(); | 971 if (_stdoutDrained) _reportResult(); |
| 1070 } | 972 } |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1515 // the developer doesn't waste his or her time trying to fix a bunch of | 1417 // the developer doesn't waste his or her time trying to fix a bunch of |
| 1516 // tests that appear to be broken but were actually just flakes that | 1418 // tests that appear to be broken but were actually just flakes that |
| 1517 // didn't get retried because there had already been one failure. | 1419 // didn't get retried because there had already been one failure. |
| 1518 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; | 1420 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; |
| 1519 new RunningProcess(test, allowRetry, this).start(); | 1421 new RunningProcess(test, allowRetry, this).start(); |
| 1520 } | 1422 } |
| 1521 _numProcesses++; | 1423 _numProcesses++; |
| 1522 } | 1424 } |
| 1523 } | 1425 } |
| 1524 } | 1426 } |
| OLD | NEW |