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 void addTestCase(TestCase testCase) { | |
1422 _tests.add(testCase); | |
1423 eventTestAdded(testCase); | |
1424 } | |
1425 var newTest = (TestCase testCase) { | |
1426 addTestCase(testCase); | |
1427 _runTest(testCase); | |
1428 }; | |
1429 if (_testCaseRecorder != null) { | |
1430 // FIXME: do we want to call [addTestCase]??? | |
ricow1
2013/05/27 09:05:17
FIXME -> TODO
I would probably organize this a lit
kustermann
2013/05/27 11:11:37
Done.
| |
1431 newTest = _testCaseRecorder.nextTestCase; | |
1432 } else if (_testCaseOutputArchive != null) { | |
1433 newTest = (TestCase testCase) { | |
1434 addTestCase(testCase); | |
1435 Timer.run(() { | |
ricow1
2013/05/27 09:05:17
add comment why we do this
| |
1436 var output = _testCaseOutputArchive.outputOf(testCase); | |
1437 testCase.completed(); | |
1438 eventFinishedTestCase(testCase); | |
1439 }); | |
1440 }; | |
1441 } | |
1442 | |
1414 // FIXME: For some reason we cannot call this method on all test suites | 1443 // FIXME: For some reason we cannot call this method on all test suites |
1415 // in parallel. | 1444 // in parallel. |
1416 // If we do, not all tests get enqueued (if --arch=all was specified, | 1445 // 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]) | 1446 // we don't get twice the number of tests [tested on -rvm -cnone]) |
1418 // Issue: 7927 | 1447 // Issue: 7927 |
1419 Iterator<TestSuite> iterator = testSuites.iterator; | 1448 Iterator<TestSuite> iterator = testSuites.iterator; |
1420 void enqueueNextSuite() { | 1449 void enqueueNextSuite() { |
1421 if (!iterator.moveNext()) { | 1450 if (!iterator.moveNext()) { |
1422 _allTestsWereEnqueued = true; | 1451 _allTestsWereEnqueued = true; |
1423 eventAllTestsKnown(); | 1452 eventAllTestsKnown(); |
1453 if (_testCaseRecorder!= null) { | |
1454 _testCaseRecorder.finish(); | |
1455 } | |
1424 _checkDone(); | 1456 _checkDone(); |
1425 } else { | 1457 } else { |
1426 iterator.current.forEachTest(_runTest, _testCache, enqueueNextSuite); | 1458 iterator.current.forEachTest(newTest, _testCache, enqueueNextSuite); |
1427 } | 1459 } |
1428 } | 1460 } |
1429 enqueueNextSuite(); | 1461 enqueueNextSuite(); |
1430 } | 1462 } |
1431 | 1463 |
1432 /** | 1464 /** |
1433 * True if we are using a browser + platform combination that needs the | 1465 * True if we are using a browser + platform combination that needs the |
1434 * Selenium server jar. | 1466 * Selenium server jar. |
1435 */ | 1467 */ |
1436 bool get _needsSelenium => (io.Platform.operatingSystem == 'macos' && | 1468 bool get _needsSelenium => (io.Platform.operatingSystem == 'macos' && |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1488 return true; | 1520 return true; |
1489 }); | 1521 }); |
1490 } | 1522 } |
1491 } | 1523 } |
1492 | 1524 |
1493 void _runTest(TestCase test) { | 1525 void _runTest(TestCase test) { |
1494 if (test.usesWebDriver) { | 1526 if (test.usesWebDriver) { |
1495 browserUsed = test.configuration['runtime']; | 1527 browserUsed = test.configuration['runtime']; |
1496 if (_needsSelenium) _ensureSeleniumServerRunning(); | 1528 if (_needsSelenium) _ensureSeleniumServerRunning(); |
1497 } | 1529 } |
1498 eventTestAdded(test); | |
1499 _tests.add(test); | |
1500 _tryRunTest(); | 1530 _tryRunTest(); |
1501 } | 1531 } |
1502 | 1532 |
1503 /** | 1533 /** |
1504 * Monitor the output of the Selenium server, to know when we are ready to | 1534 * Monitor the output of the Selenium server, to know when we are ready to |
1505 * begin running tests. | 1535 * begin running tests. |
1506 * source: Output(Stream) from the Java server. | 1536 * source: Output(Stream) from the Java server. |
1507 */ | 1537 */ |
1508 void seleniumServerHandler(String line) { | 1538 void seleniumServerHandler(String line) { |
1509 if (new RegExp(r".*Started.*Server.*").hasMatch(line) || | 1539 if (new RegExp(r".*Started.*Server.*").hasMatch(line) || |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1859 } | 1889 } |
1860 } | 1890 } |
1861 | 1891 |
1862 void eventAllTestsDone() { | 1892 void eventAllTestsDone() { |
1863 for (var listener in _eventListener) { | 1893 for (var listener in _eventListener) { |
1864 listener.allDone(); | 1894 listener.allDone(); |
1865 } | 1895 } |
1866 } | 1896 } |
1867 } | 1897 } |
1868 | 1898 |
OLD | NEW |