Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Classes and methods for executing tests. | 6 * Classes and methods for executing tests. |
| 7 * | 7 * |
| 8 * This module includes: | 8 * This module includes: |
| 9 * - Managing parallel execution of tests, including timeout checks. | 9 * - Managing parallel execution of tests, including timeout checks. |
| 10 * - Evaluating the output of each test as pass/fail/crash/timeout. | 10 * - Evaluating the output of each test as pass/fail/crash/timeout. |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 503 Function _enqueueMoreWork; | 503 Function _enqueueMoreWork; |
| 504 Queue<TestCase> _tests; | 504 Queue<TestCase> _tests; |
| 505 ProgressIndicator _progress; | 505 ProgressIndicator _progress; |
| 506 String _temporaryDirectory; | 506 String _temporaryDirectory; |
| 507 // For dartc batch processing we keep a list of batch processes. | 507 // For dartc batch processing we keep a list of batch processes. |
| 508 List<DartcBatchRunnerProcess> _batchProcesses; | 508 List<DartcBatchRunnerProcess> _batchProcesses; |
| 509 // Cache information about test cases per test suite. For multiple | 509 // Cache information about test cases per test suite. For multiple |
| 510 // configurations there is no need to repeatedly search the file | 510 // configurations there is no need to repeatedly search the file |
| 511 // system, generate tests, and search test files for options. | 511 // system, generate tests, and search test files for options. |
| 512 Map<String, List<TestInformation>> _testCache; | 512 Map<String, List<TestInformation>> _testCache; |
| 513 /** | |
| 514 * String indicating the browser used to run the tests. Empty if no browser | |
| 515 * used. | |
| 516 */ | |
| 517 String browserUsed; | |
| 513 | 518 |
| 514 ProcessQueue(int this._maxProcesses, | 519 ProcessQueue(int this._maxProcesses, |
| 515 String progress, | 520 String progress, |
| 516 Date startTime, | 521 Date startTime, |
| 517 bool printTiming, | 522 bool printTiming, |
| 518 Function this._enqueueMoreWork, | 523 Function this._enqueueMoreWork, |
| 519 [bool this._verbose = false, | 524 [bool this._verbose = false, |
| 520 bool this._listTests = false, | 525 bool this._listTests = false, |
| 521 bool this._keepGeneratedTests = false]) | 526 bool this._keepGeneratedTests = false]) |
| 522 : _tests = new Queue<TestCase>(), | 527 : _tests = new Queue<TestCase>(), |
| 523 _progress = new ProgressIndicator.fromName(progress, | 528 _progress = new ProgressIndicator.fromName(progress, |
| 524 startTime, | 529 startTime, |
| 525 printTiming), | 530 printTiming), |
| 526 _batchProcesses = new List<DartcBatchRunnerProcess>(), | 531 _batchProcesses = new List<DartcBatchRunnerProcess>(), |
| 527 _testCache = new Map<String, List<TestInformation>>() { | 532 _testCache = new Map<String, List<TestInformation>>() { |
| 528 if (!_enqueueMoreWork(this)) _progress.allDone(); | 533 if (!_enqueueMoreWork(this)) _progress.allDone(); |
| 534 browserUsed = ''; | |
| 529 } | 535 } |
| 530 | 536 |
| 531 /** | 537 /** |
| 532 * Registers a TestSuite so that all of its tests will be run. | 538 * Registers a TestSuite so that all of its tests will be run. |
| 533 */ | 539 */ |
| 534 void addTestSuite(TestSuite testSuite) { | 540 void addTestSuite(TestSuite testSuite) { |
| 535 _activeTestListers++; | 541 _activeTestListers++; |
| 536 testSuite.forEachTest(_runTest, _testCache, globalTemporaryDirectory, | 542 testSuite.forEachTest(_runTest, _testCache, globalTemporaryDirectory, |
| 537 _testListerDone); | 543 _testListerDone); |
| 544 testSuite.notifyIfBrowserCleanupNeeded(this); | |
|
Jennifer Messerly
2012/02/14 02:17:25
an alternate idea: instead of changing test_suite,
Emily Fortuna
2012/02/14 23:55:44
Done.
| |
| 538 } | 545 } |
| 539 | 546 |
| 540 void _testListerDone() { | 547 void _testListerDone() { |
| 541 _activeTestListers--; | 548 _activeTestListers--; |
| 542 _checkDone(); | 549 _checkDone(); |
| 543 } | 550 } |
| 544 | 551 |
| 545 String globalTemporaryDirectory() { | 552 String globalTemporaryDirectory() { |
| 546 if (_temporaryDirectory != null) return _temporaryDirectory; | 553 if (_temporaryDirectory != null) return _temporaryDirectory; |
| 547 | 554 |
| 548 if (new Platform().operatingSystem() == 'windows') { | 555 if (new Platform().operatingSystem() == 'windows') { |
| 549 throw new Exception( | 556 throw new Exception( |
| 550 'Test suite requires temporary directory. Not supported on Windows.'); | 557 'Test suite requires temporary directory. Not supported on Windows.'); |
| 551 } | 558 } |
| 552 var tempDir = new Directory(''); | 559 var tempDir = new Directory(''); |
| 553 tempDir.createTempSync(); | 560 tempDir.createTempSync(); |
| 554 _temporaryDirectory = tempDir.path; | 561 _temporaryDirectory = tempDir.path; |
| 555 return _temporaryDirectory; | 562 return _temporaryDirectory; |
| 556 } | 563 } |
| 557 | 564 |
| 565 /** | |
| 566 * Sometimes Webdriver doesn't close every browser window when it's done | |
| 567 * with a test. At the end of all tests we clear out any neglected processes | |
| 568 * that are still running. | |
| 569 */ | |
| 570 void killZombieBrowsers() { | |
| 571 String chromeName = 'chrome'; | |
| 572 if (new Platform().operatingSystem() == 'macos') { | |
| 573 chromeName = 'Google\ Chrome'; | |
| 574 } | |
| 575 Map<String, List<String>> processNames = {'ie': ['iexplore'], 'safari': | |
| 576 ['Safari'], 'ff': ['firefox'], 'chrome': ['chromedriver', chromeName]}; | |
| 577 if (new Platform().operatingSystem() == 'windows') { | |
| 578 for (String name in processNames[browserUsed]) { | |
| 579 Process process = new Process.start( | |
| 580 'C:\\Windows\\System32\\taskkill.exe', ['/F', '/IM', name + '.exe', | |
| 581 '/T']); | |
| 582 process.exitHandler = (exitCode) { | |
| 583 process.close(); | |
| 584 _progress.allDone(); | |
|
Jennifer Messerly
2012/02/14 02:17:25
is it okay that we're potentially calling allDone
Bill Hesse
2012/02/14 12:46:00
I don't think this is OK.
| |
| 585 }; | |
| 586 process.errorHandler = (error) { | |
| 587 _progress.allDone(); | |
| 588 }; | |
| 589 } | |
| 590 } else { | |
| 591 for (String name in processNames[browserUsed]) { | |
| 592 Process process = new Process.start('killall', ['-9', name]); | |
| 593 process.exitHandler = (exitCode) { | |
| 594 process.close(); | |
| 595 _progress.allDone(); | |
| 596 }; | |
| 597 process.errorHandler = (error) { | |
| 598 _progress.allDone(); | |
| 599 }; | |
| 600 } | |
| 601 } | |
| 602 } | |
| 558 | 603 |
| 559 void _checkDone() { | 604 void _checkDone() { |
| 560 // When there are no more active test listers ask for more work | 605 // When there are no more active test listers ask for more work |
| 561 // from process queue users. | 606 // from process queue users. |
| 562 if (_activeTestListers == 0 && !_enqueueMoreWork(this)) { | 607 if (_activeTestListers == 0 && !_enqueueMoreWork(this)) { |
| 563 _progress.allTestsKnown(); | 608 _progress.allTestsKnown(); |
| 564 if (_tests.isEmpty() && _numProcesses == 0) { | 609 if (_tests.isEmpty() && _numProcesses == 0) { |
| 565 _terminateDartcBatchRunners(); | 610 _terminateDartcBatchRunners(); |
| 566 if (_keepGeneratedTests || _temporaryDirectory == null) { | 611 if (_keepGeneratedTests || _temporaryDirectory == null) { |
| 567 _progress.allDone(); | 612 if (browserUsed != '') { |
| 613 killZombieBrowsers(); | |
| 614 } else { | |
| 615 _progress.allDone(); | |
| 616 } | |
|
Jennifer Messerly
2012/02/14 02:17:25
it'd be good to pull this pattern out into a funct
Emily Fortuna
2012/02/14 23:55:44
Done.
| |
| 568 } else if (!_temporaryDirectory.startsWith('/tmp/') || | 617 } else if (!_temporaryDirectory.startsWith('/tmp/') || |
| 569 _temporaryDirectory.contains('/../')) { | 618 _temporaryDirectory.contains('/../')) { |
| 570 // Let's be extra careful, since rm -rf is so dangerous. | 619 // Let's be extra careful, since rm -rf is so dangerous. |
| 571 print('Temporary directory $_temporaryDirectory unsafe to delete!'); | 620 print('Temporary directory $_temporaryDirectory unsafe to delete!'); |
| 572 _progress.allDone(); | 621 if (browserUsed != '') { |
| 622 killZombieBrowsers(); | |
| 623 } else { | |
| 624 _progress.allDone(); | |
| 625 } | |
| 573 } else { | 626 } else { |
| 574 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is | 627 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is |
| 575 // implemented, and add Windows support. | 628 // implemented, and add Windows support. |
| 576 var deletion = | 629 var deletion = |
| 577 new Process.start('/bin/rm', ['-rf', _temporaryDirectory]); | 630 new Process.start('/bin/rm', ['-rf', _temporaryDirectory]); |
| 578 deletion.exitHandler = (int exitCode) { | 631 deletion.exitHandler = (int exitCode) { |
| 579 if (exitCode == 0) { | 632 if (exitCode == 0) { |
| 580 if (!_listTests) { // Output of --list option is used by scripts. | 633 if (!_listTests) { // Output of --list option is used by scripts. |
| 581 print('\nTemporary directory $_temporaryDirectory deleted.'); | 634 print('\nTemporary directory $_temporaryDirectory deleted.'); |
| 582 } | 635 } |
| 583 } else { | 636 } else { |
| 584 print('\nDeletion of temp dir $_temporaryDirectory failed.'); | 637 print('\nDeletion of temp dir $_temporaryDirectory failed.'); |
| 585 } | 638 } |
| 586 _progress.allDone(); | 639 if (browserUsed != '') { |
| 640 killZombieBrowsers(); | |
| 641 } else { | |
| 642 _progress.allDone(); | |
| 643 } | |
| 587 }; | 644 }; |
| 588 } | 645 } |
| 589 } | 646 } |
| 590 } | 647 } |
| 591 } | 648 } |
| 592 | 649 |
| 593 void _runTest(TestCase test) { | 650 void _runTest(TestCase test) { |
| 594 _progress.testAdded(); | 651 _progress.testAdded(); |
| 595 _tests.add(test); | 652 _tests.add(test); |
| 596 _tryRunTest(); | 653 _tryRunTest(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 642 test.displayName != 'dartc/junit_tests') { | 699 test.displayName != 'dartc/junit_tests') { |
| 643 _ensureDartcBatchRunnersStarted(test.executablePath); | 700 _ensureDartcBatchRunnersStarted(test.executablePath); |
| 644 _getDartcBatchRunnerProcess().startTest(test); | 701 _getDartcBatchRunnerProcess().startTest(test); |
| 645 } else { | 702 } else { |
| 646 new RunningProcess(test).start(); | 703 new RunningProcess(test).start(); |
| 647 } | 704 } |
| 648 _numProcesses++; | 705 _numProcesses++; |
| 649 } | 706 } |
| 650 } | 707 } |
| 651 } | 708 } |
| OLD | NEW |