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

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