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

Unified Diff: tools/testing/dart/test_runner.dart

Issue 8729030: Support batch running of dartc tests. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor cleanup Created 9 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tests/standalone/src/TestRunnerTest.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/testing/dart/test_runner.dart
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index fe4af81e6928bfa4f3210523f25b9e34c88bc36a..73c4574068ad99f4e515d13332a0f2a7d2faaf79 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -101,7 +101,6 @@ class TestOutput {
class RunningProcess {
Process process;
TestCase testCase;
- int timeout;
bool timedOut = false;
Date startTime;
Timer timeoutTimer;
@@ -109,7 +108,7 @@ class RunningProcess {
List<String> stderr;
List<Function> handlers;
- RunningProcess(this.testCase, [this.timeout = NO_TIMEOUT]);
+ RunningProcess(this.testCase);
void exitHandler(int exitCode) {
new TestOutput(testCase, exitCode, timedOut, stdout,
@@ -147,9 +146,7 @@ class RunningProcess {
makeReadHandler(stdoutStringStream, stdout);
stderrStringStream.dataHandler =
makeReadHandler(stderrStringStream, stderr);
- if (timeout != NO_TIMEOUT) {
- timeoutTimer = new Timer(timeoutHandler, 1000 * timeout, false);
- }
+ timeoutTimer = new Timer(timeoutHandler, 1000 * testCase.timeout, false);
}
void timeoutHandler(Timer unusedTimer) {
@@ -159,42 +156,205 @@ class RunningProcess {
}
+class DartcBatchRunnerProcess {
+ String _executable;
+
+ Process _process;
+ StringInputStream _stdoutStream;
+ StringInputStream _stderrStream;
+
+ TestCase _currentTest;
+ StringBuffer _testStdout;
+ StringBuffer _testStderr;
+ Date _startTime;
+ Timer _timer;
+
+ DartcBatchRunnerProcess(String this._executable) {
+ _startProcess();
+ }
+
+ bool get active() => _currentTest != null;
+
+ void startTest(TestCase testCase) {
+ _startTime = new Date.now();
+ _currentTest = testCase;
+ _testStdout = new List<String>();
+ _testStderr = new List<String>();
+ _stdoutStream.dataHandler = _readOutput(_stdoutStream, _testStdout);
+ _stderrStream.dataHandler = _readOutput(_stderrStream, _testStderr);
+ _timer = new Timer(_timeoutHandler(testCase),
+ testCase.timeout * 1000,
+ false);
+ _process.stdin.write(_createArgumentsLine(testCase.arguments).charCodes());
+ }
+
+ void terminate() {
+ _process.exitHandler = (exitCode) {
+ _process.close();
+ };
+ _process.kill();
+ }
+
+ String _createArgumentsLine(List<String> arguments) {
+ var buffer = new StringBuffer();
+ for (var i = 0; i < arguments.length; i++) {
+ buffer.add("${arguments[i]} ");
+ }
+ buffer.add("\n");
+ return buffer.toString();
+ }
+
+ int _reportResult(String output) {
+ var test = _currentTest;
+ _currentTest = null;
+
+ // output = '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}'
+ var outcome = output.split(" ")[2];
+ var exitCode = 0;
+ if (outcome == "CRASH") exitCode = -10;
+ if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1;
+ new TestOutput(test, exitCode, outcome == "TIMEOUT", _testStdout,
+ _testStderr, new Date.now().difference(_startTime));
+ test.completed();
+ }
+
+ void _readOutput(StringInputStream stream, List<String> buffer) {
+ return () {
+ var status;
+ var line = stream.readLine();
+ // Drain the input stream to get the error output.
+ while (line != null) {
+ if (line.startsWith('>>> TEST')) {
+ status = line;
+ } else if (line.startsWith('>>> BATCH START')) {
+ // ignore
+ } else if (line.startsWith('>>> ')) {
+ throw new Exception('Unexpected command from dartc batch runner.');
+ } else {
+ buffer.add(line);
+ }
+ line = stream.readLine();
+ }
+ if (status != null) {
+ _timer.cancel();
+ // For crashing processes, let the exit handler deal with it.
+ if (!status.contains("CRASH")) {
+ _reportResult(status);
+ }
+ }
+ };
+ }
+
+ void _exitHandler(exitCode) {
+ if (_timer != null) _timer.cancel();
+ _process.close();
+ _startProcess();
+ _reportResult(">>> TEST CRASH");
+ }
+
+ void _timeoutHandler(TestCase test) {
+ return (ignore) {
+ _process.exitHandler = (exitCode) {
+ _process.close();
+ _startProcess();
+ _reportResult(">>> TEST TIMEOUT");
+ };
+ _process.kill();
+ };
+ }
+
+ void _startProcess() {
+ _process = new Process(_executable, ['-batch']);
+ _stdoutStream = new StringInputStream(_process.stdout);
+ _stderrStream = new StringInputStream(_process.stderr);
+ _testStdout = new List<String>();
+ _testStderr = new List<String>();
+ _stdoutStream.dataHandler = _readOutput(_stdoutStream, _testStdout);
+ _stderrStream.dataHandler = _readOutput(_stderrStream, _testStderr);
+ _process.exitHandler = _exitHandler;
+ _process.start();
+ }
+}
+
+
class ProcessQueue {
int _numProcesses = 0;
int _activeTestListers = 0;
- final int _maxProcesses;
+ int _maxProcesses;
Queue<TestCase> _tests;
ProgressIndicator _progress;
+ // For dartc batch processing we keep a list of batch processes for
+ // each of debug and release mode. If dartc tests are run in both
+ // release and debug mode this will spawn many processes but only
+ // half of them will be active at a time.
+ Map<String, List<DartcBatchRunnerProcess>> _batchProcessesMap;
+
ProcessQueue(int this._maxProcesses,
String progress,
Date start_time)
: _tests = new Queue<TestCase>(),
- _progress = new ProgressIndicator.fromName(progress, start_time);
+ _progress = new ProgressIndicator.fromName(progress, start_time),
+ _batchProcessesMap = new Map<String, List<DartcBatchRunnerProcess>>() {
+ _maxProcesses = _maxProcesses;
+ }
- addTestSuite(TestSuite testSuite) {
+ void addTestSuite(TestSuite testSuite) {
_activeTestListers++;
testSuite.forEachTest(_runTest, _testListerDone);
}
- _testListerDone() {
+ void _testListerDone() {
_activeTestListers--;
_checkDone();
}
- _checkDone() {
+ void _checkDone() {
if (_activeTestListers == 0 && _tests.isEmpty() && _numProcesses == 0) {
+ _terminateDartcBatchRunners();
_progress.allDone();
}
}
- _runTest(TestCase test) {
+ void _runTest(TestCase test) {
_progress.testAdded();
_tests.add(test);
_tryRunTest();
}
- _tryRunTest() {
+ void _terminateDartcBatchRunners() {
+ _batchProcessesMap.forEach((key, value) {
+ for (int i = 0; i < value.length; i++) {
+ value[i].terminate();
+ }
+ });
+ }
+
+ DartcBatchRunnerProcess _getDartcBatchRunnerProcess(TestCase test) {
+ var batchProcesses = _batchProcessesMap[test.executablePath];
+ if (batchProcesses == null) {
+ // Dartc batch processing is heavy. Scale down the number of
+ // concurrent tasks to be no more than the actual number of
+ // processors even when running dartc benchmarks in both debug
+ // and release mode.
+ var processors = new Platform().numberOfProcessors();
+ if (_maxProcesses >= (processors / 2)) {
+ _maxProcesses = (processors / 2).toInt();
+ }
+ batchProcesses = new List<DartcBatchRunnerProcess>(_maxProcesses);
+ _batchProcessesMap[test.executablePath] = batchProcesses;
+ for (int i = 0; i < _maxProcesses; i++) {
+ batchProcesses[i] = new DartcBatchRunnerProcess(test.executablePath);
+ }
+ }
+ for (int i = 0; i < batchProcesses.length; i++) {
+ var runner = batchProcesses[i];
+ if (!runner.active) return runner;
+ }
+ throw new Exception('Unable to find inactive batch runner.');
+ }
+
+ void _tryRunTest() {
_checkDone();
if (_numProcesses < _maxProcesses && !_tests.isEmpty()) {
TestCase test = _tests.removeFirst();
@@ -207,7 +367,11 @@ class ProcessQueue {
oldCallback(test_arg);
};
test.completedHandler = wrapper;
- new RunningProcess(test, test.timeout).start();
+ if (test.executablePath.contains('dartc_test')) {
+ _getDartcBatchRunnerProcess(test).startTest(test);
+ } else {
+ new RunningProcess(test).start();
+ }
_numProcesses++;
}
}
« no previous file with comments | « tests/standalone/src/TestRunnerTest.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698