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:async"; | 14 import "dart:async"; |
15 import "dart:collection" show Queue; | 15 import "dart:collection" show Queue; |
16 // We need to use the 'io' prefix here, otherwise io.exitCode will shadow | 16 // We need to use the 'io' prefix here, otherwise io.exitCode will shadow |
17 // CommandOutput.exitCode in subclasses of CommandOutput. | 17 // CommandOutput.exitCode in subclasses of CommandOutput. |
18 import "dart:io" as io; | 18 import "dart:io" as io; |
19 import "dart:isolate"; | 19 import "dart:isolate"; |
20 import "dart:uri"; | 20 import "dart:uri"; |
21 import "browser_controller.dart"; | 21 import "browser_controller.dart"; |
22 import "http_server.dart" as http_server; | 22 import "http_server.dart" as http_server; |
23 import "status_file_parser.dart"; | 23 import "status_file_parser.dart"; |
24 import "test_progress.dart"; | 24 import "test_progress.dart"; |
25 import "test_suite.dart"; | 25 import "test_suite.dart"; |
26 import "utils.dart"; | 26 import "utils.dart"; |
| 27 import 'record_and_replay.dart'; |
27 | 28 |
28 const int NO_TIMEOUT = 0; | 29 const int NO_TIMEOUT = 0; |
29 const int SLOW_TIMEOUT_MULTIPLIER = 4; | 30 const int SLOW_TIMEOUT_MULTIPLIER = 4; |
30 | 31 |
31 const int CRASHING_BROWSER_EXITCODE = -10; | 32 const int CRASHING_BROWSER_EXITCODE = -10; |
32 | 33 |
33 typedef void TestCaseEvent(TestCase testCase); | 34 typedef void TestCaseEvent(TestCase testCase); |
34 typedef void ExitCodeEvent(int exitCode); | 35 typedef void ExitCodeEvent(int exitCode); |
35 typedef void EnqueueMoreWork(ProcessQueue queue); | 36 typedef void EnqueueMoreWork(ProcessQueue queue); |
36 | 37 |
(...skipping 1293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 * upon to enqueue its tests again. | 1331 * upon to enqueue its tests again. |
1331 */ | 1332 */ |
1332 class ProcessQueue { | 1333 class ProcessQueue { |
1333 int _numProcesses = 0; | 1334 int _numProcesses = 0; |
1334 int _maxProcesses; | 1335 int _maxProcesses; |
1335 int _numBrowserProcesses = 0; | 1336 int _numBrowserProcesses = 0; |
1336 int _maxBrowserProcesses; | 1337 int _maxBrowserProcesses; |
1337 int _numFailedTests = 0; | 1338 int _numFailedTests = 0; |
1338 bool _allTestsWereEnqueued = false; | 1339 bool _allTestsWereEnqueued = false; |
1339 | 1340 |
| 1341 // Support for recording and replaying test commands. |
| 1342 TestCaseRecorder _testCaseRecorder; |
| 1343 TestCaseOutputArchive _testCaseOutputArchive; |
| 1344 |
1340 /** The number of tests we allow to actually fail before we stop retrying. */ | 1345 /** The number of tests we allow to actually fail before we stop retrying. */ |
1341 int _MAX_FAILED_NO_RETRY = 4; | 1346 int _MAX_FAILED_NO_RETRY = 4; |
1342 bool _verbose; | 1347 bool _verbose; |
1343 bool _listTests; | 1348 bool _listTests; |
1344 Function _allDone; | 1349 Function _allDone; |
1345 Queue<TestCase> _tests; | 1350 Queue<TestCase> _tests; |
1346 List<EventListener> _eventListener; | 1351 List<EventListener> _eventListener; |
1347 | 1352 |
1348 // For dartc/selenium batch processing we keep a list of batch processes. | 1353 // For dartc/selenium batch processing we keep a list of batch processes. |
1349 Map<String, List<BatchRunnerProcess>> _batchProcesses; | 1354 Map<String, List<BatchRunnerProcess>> _batchProcesses; |
(...skipping 23 matching lines...) Expand all Loading... |
1373 /** True if we find that there is already a selenium jar running. */ | 1378 /** True if we find that there is already a selenium jar running. */ |
1374 bool _seleniumAlreadyRunning = false; | 1379 bool _seleniumAlreadyRunning = false; |
1375 | 1380 |
1376 ProcessQueue(this._maxProcesses, | 1381 ProcessQueue(this._maxProcesses, |
1377 this._maxBrowserProcesses, | 1382 this._maxBrowserProcesses, |
1378 DateTime startTime, | 1383 DateTime startTime, |
1379 testSuites, | 1384 testSuites, |
1380 this._eventListener, | 1385 this._eventListener, |
1381 this._allDone, | 1386 this._allDone, |
1382 [bool verbose = false, | 1387 [bool verbose = false, |
1383 bool listTests = false]) | 1388 bool listTests = false, |
| 1389 this._testCaseRecorder, |
| 1390 this._testCaseOutputArchive]) |
1384 : _verbose = verbose, | 1391 : _verbose = verbose, |
1385 _listTests = listTests, | 1392 _listTests = listTests, |
1386 _tests = new Queue<TestCase>(), | 1393 _tests = new Queue<TestCase>(), |
1387 _batchProcesses = new Map<String, List<BatchRunnerProcess>>(), | 1394 _batchProcesses = new Map<String, List<BatchRunnerProcess>>(), |
1388 _testCache = new Map<String, List<TestInformation>>(), | 1395 _testCache = new Map<String, List<TestInformation>>(), |
1389 _browserTestRunners = new Map<String, BrowserTestRunner>() { | 1396 _browserTestRunners = new Map<String, BrowserTestRunner>() { |
1390 _runTests(testSuites); | 1397 _runTests(testSuites); |
1391 } | 1398 } |
1392 | 1399 |
1393 /** | 1400 /** |
(...skipping 10 matching lines...) Expand all Loading... |
1404 | 1411 |
1405 void _checkDone() { | 1412 void _checkDone() { |
1406 if (_allTestsWereEnqueued && _tests.isEmpty && _numProcesses == 0) { | 1413 if (_allTestsWereEnqueued && _tests.isEmpty && _numProcesses == 0) { |
1407 _terminateBatchRunners().then((_) { | 1414 _terminateBatchRunners().then((_) { |
1408 _terminateBrowserRunners().then((_) => _cleanupAndMarkDone()); | 1415 _terminateBrowserRunners().then((_) => _cleanupAndMarkDone()); |
1409 }); | 1416 }); |
1410 } | 1417 } |
1411 } | 1418 } |
1412 | 1419 |
1413 void _runTests(List<TestSuite> testSuites) { | 1420 void _runTests(List<TestSuite> testSuites) { |
| 1421 var newTest; |
| 1422 var allTestsKnown; |
| 1423 |
| 1424 if (_testCaseRecorder != null) { |
| 1425 // Mode: recording. |
| 1426 newTest = _testCaseRecorder.nextTestCase; |
| 1427 allTestsKnown = () { |
| 1428 // We don't call any event*() methods, so test_progress.dart will not be |
| 1429 // notified (that's fine, since we're not running any tests). |
| 1430 _testCaseRecorder.finish(); |
| 1431 _allDone(); |
| 1432 }; |
| 1433 } else { |
| 1434 if (_testCaseOutputArchive != null) { |
| 1435 // Mode: replaying. |
| 1436 newTest = (TestCase testCase) { |
| 1437 // We're doing this asynchronously to emulate the normal behaviour. |
| 1438 eventTestAdded(testCase); |
| 1439 Timer.run(() { |
| 1440 var output = _testCaseOutputArchive.outputOf(testCase); |
| 1441 testCase.completed(); |
| 1442 eventFinishedTestCase(testCase); |
| 1443 }); |
| 1444 }; |
| 1445 allTestsKnown = () { |
| 1446 // If we're replaying commands, we need to call [_cleanupAndMarkDone] |
| 1447 // manually. We're putting it at the end of the event queue to make |
| 1448 // sure all the previous events were fired. |
| 1449 Timer.run(() => _cleanupAndMarkDone()); |
| 1450 }; |
| 1451 } else { |
| 1452 // Mode: none (we're not recording/replaying). |
| 1453 newTest = (TestCase testCase) { |
| 1454 _tests.add(testCase); |
| 1455 eventTestAdded(testCase); |
| 1456 _runTest(testCase); |
| 1457 }; |
| 1458 allTestsKnown = _checkDone; |
| 1459 } |
| 1460 } |
| 1461 |
1414 // FIXME: For some reason we cannot call this method on all test suites | 1462 // FIXME: For some reason we cannot call this method on all test suites |
1415 // in parallel. | 1463 // in parallel. |
1416 // If we do, not all tests get enqueued (if --arch=all was specified, | 1464 // If we do, not all tests get enqueued (if --arch=all was specified, |
1417 // we don't get twice the number of tests [tested on -rvm -cnone]) | 1465 // we don't get twice the number of tests [tested on -rvm -cnone]) |
1418 // Issue: 7927 | 1466 // Issue: 7927 |
1419 Iterator<TestSuite> iterator = testSuites.iterator; | 1467 Iterator<TestSuite> iterator = testSuites.iterator; |
1420 void enqueueNextSuite() { | 1468 void enqueueNextSuite() { |
1421 if (!iterator.moveNext()) { | 1469 if (!iterator.moveNext()) { |
1422 _allTestsWereEnqueued = true; | 1470 _allTestsWereEnqueued = true; |
| 1471 allTestsKnown(); |
1423 eventAllTestsKnown(); | 1472 eventAllTestsKnown(); |
1424 _checkDone(); | |
1425 } else { | 1473 } else { |
1426 iterator.current.forEachTest(_runTest, _testCache, enqueueNextSuite); | 1474 iterator.current.forEachTest(newTest, _testCache, enqueueNextSuite); |
1427 } | 1475 } |
1428 } | 1476 } |
1429 enqueueNextSuite(); | 1477 enqueueNextSuite(); |
1430 } | 1478 } |
1431 | 1479 |
1432 /** | 1480 /** |
1433 * True if we are using a browser + platform combination that needs the | 1481 * True if we are using a browser + platform combination that needs the |
1434 * Selenium server jar. | 1482 * Selenium server jar. |
1435 */ | 1483 */ |
1436 bool get _needsSelenium => (io.Platform.operatingSystem == 'macos' && | 1484 bool get _needsSelenium => (io.Platform.operatingSystem == 'macos' && |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1488 return true; | 1536 return true; |
1489 }); | 1537 }); |
1490 } | 1538 } |
1491 } | 1539 } |
1492 | 1540 |
1493 void _runTest(TestCase test) { | 1541 void _runTest(TestCase test) { |
1494 if (test.usesWebDriver) { | 1542 if (test.usesWebDriver) { |
1495 browserUsed = test.configuration['runtime']; | 1543 browserUsed = test.configuration['runtime']; |
1496 if (_needsSelenium) _ensureSeleniumServerRunning(); | 1544 if (_needsSelenium) _ensureSeleniumServerRunning(); |
1497 } | 1545 } |
1498 eventTestAdded(test); | |
1499 _tests.add(test); | |
1500 _tryRunTest(); | 1546 _tryRunTest(); |
1501 } | 1547 } |
1502 | 1548 |
1503 /** | 1549 /** |
1504 * Monitor the output of the Selenium server, to know when we are ready to | 1550 * Monitor the output of the Selenium server, to know when we are ready to |
1505 * begin running tests. | 1551 * begin running tests. |
1506 * source: Output(Stream) from the Java server. | 1552 * source: Output(Stream) from the Java server. |
1507 */ | 1553 */ |
1508 void seleniumServerHandler(String line) { | 1554 void seleniumServerHandler(String line) { |
1509 if (new RegExp(r".*Started.*Server.*").hasMatch(line) || | 1555 if (new RegExp(r".*Started.*Server.*").hasMatch(line) || |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 } | 1905 } |
1860 } | 1906 } |
1861 | 1907 |
1862 void eventAllTestsDone() { | 1908 void eventAllTestsDone() { |
1863 for (var listener in _eventListener) { | 1909 for (var listener in _eventListener) { |
1864 listener.allDone(); | 1910 listener.allDone(); |
1865 } | 1911 } |
1866 } | 1912 } |
1867 } | 1913 } |
1868 | 1914 |
OLD | NEW |