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

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

Issue 12302016: Refactoring of ProgressIndicator (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased & Added LeftOverTempDirPrinter and StatusFileUpdatePrinter Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * Classes and methods for executing tests. 6 * Classes and methods for executing tests.
7 * 7 *
8 * This module includes: 8 * This module includes:
9 * - Managing parallel execution of tests, including timeout checks. 9 * - Managing parallel execution of tests, including timeout checks.
10 * - Evaluating the output of each test as pass/fail/crash/timeout. 10 * - Evaluating the output of each test as pass/fail/crash/timeout.
(...skipping 1297 matching lines...) Expand 10 before | Expand all | Expand 10 after
1308 * Because multiple configurations may be run on each test suite, the 1308 * Because multiple configurations may be run on each test suite, the
1309 * ProcessQueue contains a cache in which a test suite may record information 1309 * ProcessQueue contains a cache in which a test suite may record information
1310 * about its list of tests, and may retrieve that information when it is called 1310 * about its list of tests, and may retrieve that information when it is called
1311 * upon to enqueue its tests again. 1311 * upon to enqueue its tests again.
1312 */ 1312 */
1313 class ProcessQueue { 1313 class ProcessQueue {
1314 int _numProcesses = 0; 1314 int _numProcesses = 0;
1315 int _maxProcesses; 1315 int _maxProcesses;
1316 int _numBrowserProcesses = 0; 1316 int _numBrowserProcesses = 0;
1317 int _maxBrowserProcesses; 1317 int _maxBrowserProcesses;
1318 int _numFailedTests = 0;
1318 bool _allTestsWereEnqueued = false; 1319 bool _allTestsWereEnqueued = false;
1319 1320
1320 /** The number of tests we allow to actually fail before we stop retrying. */ 1321 /** The number of tests we allow to actually fail before we stop retrying. */
1321 int _MAX_FAILED_NO_RETRY = 4; 1322 int _MAX_FAILED_NO_RETRY = 4;
1322 bool _verbose; 1323 bool _verbose;
1323 bool _listTests; 1324 bool _listTests;
1324 Function _allDone; 1325 Function _allDone;
1325 Queue<TestCase> _tests; 1326 Queue<TestCase> _tests;
1326 ProgressIndicator _progress; 1327 List<EventListener> _eventListener;
1327 1328
1328 // For dartc/selenium batch processing we keep a list of batch processes. 1329 // For dartc/selenium batch processing we keep a list of batch processes.
1329 Map<String, List<BatchRunnerProcess>> _batchProcesses; 1330 Map<String, List<BatchRunnerProcess>> _batchProcesses;
1330 1331
1331 // Cache information about test cases per test suite. For multiple 1332 // Cache information about test cases per test suite. For multiple
1332 // configurations there is no need to repeatedly search the file 1333 // configurations there is no need to repeatedly search the file
1333 // system, generate tests, and search test files for options. 1334 // system, generate tests, and search test files for options.
1334 Map<String, List<TestInformation>> _testCache; 1335 Map<String, List<TestInformation>> _testCache;
1335 1336
1336 /** 1337 /**
1337 * String indicating the browser used to run the tests. Empty if no browser 1338 * String indicating the browser used to run the tests. Empty if no browser
1338 * used. 1339 * used.
1339 */ 1340 */
1340 String browserUsed = ''; 1341 String browserUsed = '';
1341 1342
1342 /** 1343 /**
1343 * Process running the selenium server .jar (only used for Safari and Opera 1344 * Process running the selenium server .jar (only used for Safari and Opera
1344 * tests.) 1345 * tests.)
1345 */ 1346 */
1346 io.Process _seleniumServer = null; 1347 io.Process _seleniumServer = null;
1347 1348
1348 /** True if we are in the process of starting the server. */ 1349 /** True if we are in the process of starting the server. */
1349 bool _startingServer = false; 1350 bool _startingServer = false;
1350 1351
1351 /** True if we find that there is already a selenium jar running. */ 1352 /** True if we find that there is already a selenium jar running. */
1352 bool _seleniumAlreadyRunning = false; 1353 bool _seleniumAlreadyRunning = false;
1353 1354
1354 ProcessQueue(this._maxProcesses, 1355 ProcessQueue(this._maxProcesses,
1355 this._maxBrowserProcesses, 1356 this._maxBrowserProcesses,
1356 String progress,
1357 Date startTime, 1357 Date startTime,
1358 bool printTiming,
1359 testSuites, 1358 testSuites,
1359 this._eventListener,
1360 this._allDone, 1360 this._allDone,
1361 [bool verbose = false, 1361 [bool verbose = false,
1362 bool listTests = false]) 1362 bool listTests = false])
1363 : _verbose = verbose, 1363 : _verbose = verbose,
1364 _listTests = listTests, 1364 _listTests = listTests,
1365 _tests = new Queue<TestCase>(), 1365 _tests = new Queue<TestCase>(),
1366 _progress = new ProgressIndicator.fromName(progress,
1367 startTime,
1368 printTiming),
1369 _batchProcesses = new Map<String, List<BatchRunnerProcess>>(), 1366 _batchProcesses = new Map<String, List<BatchRunnerProcess>>(),
1370 _testCache = new Map<String, List<TestInformation>>() { 1367 _testCache = new Map<String, List<TestInformation>>() {
1371 _runTests(testSuites); 1368 _runTests(testSuites);
1372 } 1369 }
1373 1370
1374 /** 1371 /**
1375 * Perform any cleanup needed once all tests in a TestSuite have completed 1372 * Perform any cleanup needed once all tests in a TestSuite have completed
1376 * and notify our progress indicator that we are done. 1373 * and notify our progress indicator that we are done.
1377 */ 1374 */
1378 void _cleanupAndMarkDone() { 1375 void _cleanupAndMarkDone() {
1379 _allDone(); 1376 _allDone();
1380 if (browserUsed != '' && _seleniumServer != null) { 1377 if (browserUsed != '' && _seleniumServer != null) {
1381 _seleniumServer.kill(); 1378 _seleniumServer.kill();
1382 } 1379 }
1383 _progress.allDone(); 1380 eventAllTestsDone();
1384 } 1381 }
1385 1382
1386 void _checkDone() { 1383 void _checkDone() {
1387 if (_allTestsWereEnqueued && _tests.isEmpty && _numProcesses == 0) { 1384 if (_allTestsWereEnqueued && _tests.isEmpty && _numProcesses == 0) {
1388 _terminateBatchRunners().then((_) => _cleanupAndMarkDone()); 1385 _terminateBatchRunners().then((_) => _cleanupAndMarkDone());
1389 } 1386 }
1390 } 1387 }
1391 1388
1392 void _runTests(List<TestSuite> testSuites) { 1389 void _runTests(List<TestSuite> testSuites) {
1393 // FIXME: For some reason we cannot call this method on all test suites 1390 // FIXME: For some reason we cannot call this method on all test suites
1394 // in parallel. 1391 // in parallel.
1395 // If we do, not all tests get enqueued (if --arch=all was specified, 1392 // If we do, not all tests get enqueued (if --arch=all was specified,
1396 // we don't get twice the number of tests [tested on -rvm -cnone]) 1393 // we don't get twice the number of tests [tested on -rvm -cnone])
1397 // Issue: 7927 1394 // Issue: 7927
1398 Iterator<TestSuite> iterator = testSuites.iterator; 1395 Iterator<TestSuite> iterator = testSuites.iterator;
1399 void enqueueNextSuite() { 1396 void enqueueNextSuite() {
1400 if (!iterator.moveNext()) { 1397 if (!iterator.moveNext()) {
1401 _allTestsWereEnqueued = true; 1398 _allTestsWereEnqueued = true;
1402 _progress.allTestsKnown(); 1399 eventAllTestsKnown();
1403 _checkDone(); 1400 _checkDone();
1404 } else { 1401 } else {
1405 iterator.current.forEachTest(_runTest, _testCache, enqueueNextSuite); 1402 iterator.current.forEachTest(_runTest, _testCache, enqueueNextSuite);
1406 } 1403 }
1407 } 1404 }
1408 enqueueNextSuite(); 1405 enqueueNextSuite();
1409 } 1406 }
1410 1407
1411 /** 1408 /**
1412 * True if we are using a browser + platform combination that needs the 1409 * True if we are using a browser + platform combination that needs the
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1469 return true; 1466 return true;
1470 }); 1467 });
1471 } 1468 }
1472 } 1469 }
1473 1470
1474 void _runTest(TestCase test) { 1471 void _runTest(TestCase test) {
1475 if (test.usesWebDriver) { 1472 if (test.usesWebDriver) {
1476 browserUsed = test.configuration['browser']; 1473 browserUsed = test.configuration['browser'];
1477 if (_needsSelenium) _ensureSeleniumServerRunning(); 1474 if (_needsSelenium) _ensureSeleniumServerRunning();
1478 } 1475 }
1479 _progress.testAdded(); 1476 eventTestAdded(test);
1480 _tests.add(test); 1477 _tests.add(test);
1481 _tryRunTest(); 1478 _tryRunTest();
1482 } 1479 }
1483 1480
1484 /** 1481 /**
1485 * Monitor the output of the Selenium server, to know when we are ready to 1482 * Monitor the output of the Selenium server, to know when we are ready to
1486 * begin running tests. 1483 * begin running tests.
1487 * source: Output(Stream) from the Java server. 1484 * source: Output(Stream) from the Java server.
1488 */ 1485 */
1489 VoidFunction makeSeleniumServerHandler(io.StringInputStream source) { 1486 VoidFunction makeSeleniumServerHandler(io.StringInputStream source) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1612 var isLastCommand = 1609 var isLastCommand =
1613 ((test.commands.length-1) == test.commandOutputs.length); 1610 ((test.commands.length-1) == test.commandOutputs.length);
1614 var isBrowserCommand = isLastCommand && (test is BrowserTestCase); 1611 var isBrowserCommand = isLastCommand && (test is BrowserTestCase);
1615 if (isBrowserCommand && _numBrowserProcesses == _maxBrowserProcesses) { 1612 if (isBrowserCommand && _numBrowserProcesses == _maxBrowserProcesses) {
1616 // If there is no free browser runner, put it back into the queue. 1613 // If there is no free browser runner, put it back into the queue.
1617 _tests.add(test); 1614 _tests.add(test);
1618 new Timer(100, (_) => _tryRunTest()); // Don't lose a process. 1615 new Timer(100, (_) => _tryRunTest()); // Don't lose a process.
1619 return; 1616 return;
1620 } 1617 }
1621 1618
1622 _progress.start(test); 1619 eventStartTestCase(test);
1623 1620
1624 // Dartc and browser test commands can be run by a [BatchRunnerProcess] 1621 // Dartc and browser test commands can be run by a [BatchRunnerProcess]
1625 var nextCommandIndex = test.commandOutputs.keys.length; 1622 var nextCommandIndex = test.commandOutputs.keys.length;
1626 var numberOfCommands = test.commands.length; 1623 var numberOfCommands = test.commands.length;
1627 var useBatchRunnerForDartc = test.configuration['compiler'] == 'dartc' && 1624 var useBatchRunnerForDartc = test.configuration['compiler'] == 'dartc' &&
1628 test.displayName != 'dartc/junit_tests'; 1625 test.displayName != 'dartc/junit_tests';
1629 var isWebdriverCommand = nextCommandIndex == (numberOfCommands - 1) && 1626 var isWebdriverCommand = nextCommandIndex == (numberOfCommands - 1) &&
1630 test.usesWebDriver && 1627 test.usesWebDriver &&
1631 !test.configuration['noBatch']; 1628 !test.configuration['noBatch'];
1632 if (useBatchRunnerForDartc || isWebdriverCommand) { 1629 if (useBatchRunnerForDartc || isWebdriverCommand) {
1633 TestCaseEvent oldCallback = test.completedHandler; 1630 TestCaseEvent oldCallback = test.completedHandler;
1634 void testCompleted(TestCase test_arg) { 1631 void testCompleted(TestCase test_arg) {
1635 _numProcesses--; 1632 _numProcesses--;
1636 if (isBrowserCommand) { 1633 if (isBrowserCommand) {
1637 _numBrowserProcesses--; 1634 _numBrowserProcesses--;
1638 } 1635 }
1639 _progress.done(test_arg); 1636 eventFinishedTestCase(test_arg);
1640 if (test_arg is BrowserTestCase) test_arg.notifyObservers(); 1637 if (test_arg is BrowserTestCase) test_arg.notifyObservers();
1641 oldCallback(test_arg); 1638 oldCallback(test_arg);
1642 _tryRunTest(); 1639 _tryRunTest();
1643 }; 1640 };
1644 test.completedHandler = testCompleted; 1641 test.completedHandler = testCompleted;
1645 _getBatchRunner(test).startTest(test); 1642 _getBatchRunner(test).startTest(test);
1646 } else { 1643 } else {
1647 // Once we've actually failed a test, technically, we wouldn't need to 1644 // Once we've actually failed a test, technically, we wouldn't need to
1648 // bother retrying any subsequent tests since the bot is already red. 1645 // bother retrying any subsequent tests since the bot is already red.
1649 // However, we continue to retry tests until we have actually failed 1646 // However, we continue to retry tests until we have actually failed
1650 // four tests (arbitrarily chosen) for more debugable output, so that 1647 // four tests (arbitrarily chosen) for more debugable output, so that
1651 // the developer doesn't waste his or her time trying to fix a bunch of 1648 // the developer doesn't waste his or her time trying to fix a bunch of
1652 // tests that appear to be broken but were actually just flakes that 1649 // tests that appear to be broken but were actually just flakes that
1653 // didn't get retried because there had already been one failure. 1650 // didn't get retried because there had already been one failure.
1654 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; 1651 bool allowRetry = _MAX_FAILED_NO_RETRY > _numFailedTests;
1655 runNextCommandWithRetries(test, allowRetry).then((TestCase testCase) { 1652 runNextCommandWithRetries(test, allowRetry).then((TestCase testCase) {
1656 _numProcesses--; 1653 _numProcesses--;
1657 if (isBrowserCommand) { 1654 if (isBrowserCommand) {
1658 _numBrowserProcesses--; 1655 _numBrowserProcesses--;
1659 } 1656 }
1660 if (isTestCaseFinished(testCase)) { 1657 if (isTestCaseFinished(testCase)) {
1661 testCase.completed(); 1658 testCase.completed();
1662 _progress.done(testCase); 1659 eventFinishedTestCase(testCase);
1663 if (testCase is BrowserTestCase) testCase.notifyObservers(); 1660 if (testCase is BrowserTestCase) testCase.notifyObservers();
1664 } else { 1661 } else {
1665 _tests.addFirst(testCase); 1662 _tests.addFirst(testCase);
1666 } 1663 }
1667 _tryRunTest(); 1664 _tryRunTest();
1668 }); 1665 });
1669 } 1666 }
1670 1667
1671 _numProcesses++; 1668 _numProcesses++;
1672 if (isBrowserCommand) { 1669 if (isBrowserCommand) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1744 runCommand(); 1741 runCommand();
1745 } else { 1742 } else {
1746 completer.complete(testCase); 1743 completer.complete(testCase);
1747 } 1744 }
1748 }); 1745 });
1749 } 1746 }
1750 runCommand(); 1747 runCommand();
1751 1748
1752 return completer.future; 1749 return completer.future;
1753 } 1750 }
1751
1752 void eventStartTestCase(TestCase testCase) {
1753 for (var listener in _eventListener) {
1754 listener.start(testCase);
1755 }
1756 }
1757
1758 void eventFinishedTestCase(TestCase testCase) {
1759 if (testCase.lastCommandOutput.unexpectedOutput) {
1760 _numFailedTests++;
1761 }
1762 for (var listener in _eventListener) {
1763 listener.done(testCase);
1764 }
1765 }
1766
1767 void eventTestAdded(TestCase testCase) {
1768 for (var listener in _eventListener) {
1769 listener.testAdded();
1770 }
1771 }
1772
1773 void eventAllTestsKnown() {
1774 for (var listener in _eventListener) {
1775 listener.allTestsKnown();
1776 }
1777 }
1778
1779 void eventAllTestsDone() {
1780 for (var listener in _eventListener) {
1781 listener.allDone();
1782 }
1783 }
1754 } 1784 }
1755 1785
OLDNEW
« tools/testing/dart/test_progress.dart ('K') | « tools/testing/dart/test_progress.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698