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

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

Issue 9420037: reuse the same browser when running webdriver tests (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: added comment about processQueue Created 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/testing/dart/test_suite.dart » ('j') | 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 f9b07c647457c3f7f9a0b223ff136fc747dd09bb..7eddd3f73339cc679b4a7c3b8698506c21829d74 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -99,6 +99,9 @@ class TestCase {
return "$component ${mode}_$arch";
}
+ List<String> get batchRunnerArguments() => ['-batch'];
+ List<String> get batchTestArguments() => arguments;
+
void completed() { completedHandler(this); }
}
@@ -146,6 +149,10 @@ class BrowserTestCase extends TestCase {
}
numRetries = 2; // Allow two retries to compensate for flaky browser tests.
}
+
+ List<String> get batchRunnerArguments() => [arguments[0], '--batch'];
+ List<String> get batchTestArguments() =>
+ arguments.getRange(1, arguments.length - 1);
}
@@ -208,7 +215,7 @@ class TestOutput {
if (line.contains('Gtk-WARNING **: cannot open display: :99') ||
line.contains('Failed to run command. return code=1')) {
// If we get the X server error, or DRT crashes with a core dump, retry
- // the test.
+ // the test.
requestRetry = true;
return true;
}
@@ -242,6 +249,7 @@ class TestOutput {
* be garbage collected as soon as it is done.
*/
class RunningProcess {
+ ProcessQueue processQueue;
Process process;
TestCase testCase;
bool timedOut = false;
@@ -252,7 +260,8 @@ class RunningProcess {
List<Function> handlers;
bool allowRetries = false;
- RunningProcess(TestCase this.testCase, [this.allowRetries]);
+ RunningProcess(TestCase this.testCase,
+ [this.allowRetries, this.processQueue]);
void exitHandler(int exitCode) {
new TestOutput(testCase, exitCode, timedOut, stdout,
@@ -264,7 +273,7 @@ class RunningProcess {
for (var line in testCase.output.stderr) print(line);
for (var line in testCase.output.stdout) print(line);
}
- if (allowRetries != null && allowRetries
+ if (allowRetries != null && allowRetries
&& testCase.configuration['component'] == 'webdriver' &&
testCase.output.unexpectedOutput && testCase.numRetries > 0) {
// Selenium tests can be flaky. Try rerunning.
@@ -289,7 +298,13 @@ class RunningProcess {
process.close();
stderr.add('test.dart: Compilation finished, starting execution\n');
stdout.add('test.dart: Compilation finished, starting execution\n');
- runCommand(testCase.executablePath, testCase.arguments, exitHandler);
+ if (testCase.configuration['component'] == 'webdriver') {
+ // Note: processQueue will always be non-null for component == webdriver
+ // (It is only null for component == vm)
+ processQueue._getBatchRunner(testCase).startTest(testCase);
+ } else {
+ runCommand(testCase.executablePath, testCase.arguments, exitHandler);
+ }
}
}
@@ -346,9 +361,9 @@ class RunningProcess {
}
}
-
-class DartcBatchRunnerProcess {
+class BatchRunnerProcess {
String _executable;
+ List<String> _batchArguments;
Process _process;
StringInputStream _stdoutStream;
@@ -360,7 +375,13 @@ class DartcBatchRunnerProcess {
Date _startTime;
Timer _timer;
- DartcBatchRunnerProcess(String this._executable);
+ bool _isWebDriver;
+
+ BatchRunnerProcess(TestCase testCase) {
+ _executable = testCase.executablePath;
+ _batchArguments = testCase.batchRunnerArguments;
+ _isWebDriver = testCase.configuration['component'] == 'webdriver';
+ }
bool get active() => _currentTest != null;
@@ -376,6 +397,7 @@ class DartcBatchRunnerProcess {
// Restart this runner with the right executable for this test
// if needed.
_executable = testCase.executablePath;
+ _batchArguments = testCase.batchRunnerArguments;
_process.exitHandler = (exitCode) {
_process.close();
_startProcess(() {
@@ -390,10 +412,23 @@ class DartcBatchRunnerProcess {
void terminate() {
if (_process !== null) {
+ bool closed = false;
_process.exitHandler = (exitCode) {
+ closed = true;
_process.close();
};
- _process.kill();
+ if (_isWebDriver) {
+ // Use a graceful shutdown so our Selenium script can close
+ // the open browser processes. TODO(jmesserly): Send a signal once
+ // that's supported, see dartbug.com/1756.
+ _process.stdin.write('--terminate\n'.charCodes());
+
+ // In case the run_selenium process didn't close, kill it after 30s
+ bool shutdownMillisecs = 30000;
+ new Timer((e) { if (!closed) _process.kill(); }, shutdownMillisecs);
+ } else {
+ _process.kill();
+ }
}
}
@@ -403,8 +438,9 @@ class DartcBatchRunnerProcess {
_testStderr = new List<String>();
_stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout);
_stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr);
- _timer = new Timer(_timeoutHandler(testCase), testCase.timeout * 1000);
- _process.stdin.write(_createArgumentsLine(testCase.arguments).charCodes());
+ _timer = new Timer(_timeoutHandler, testCase.timeout * 1000);
+ var line = _createArgumentsLine(testCase.batchTestArguments);
+ _process.stdin.write(line.charCodes());
}
String _createArgumentsLine(List<String> arguments) {
@@ -460,20 +496,18 @@ class DartcBatchRunnerProcess {
});
}
- Function _timeoutHandler(TestCase test) {
- return (ignore) {
- _process.exitHandler = (exitCode) {
- _process.close();
- _startProcess(() {
- _reportResult(">>> TEST TIMEOUT");
- });
- };
- _process.kill();
+ void _timeoutHandler(ignore) {
+ _process.exitHandler = (exitCode) {
+ _process.close();
+ _startProcess(() {
+ _reportResult(">>> TEST TIMEOUT");
+ });
};
+ _process.kill();
}
void _startProcess(then) {
- _process = new Process.start(_executable, ['-batch']);
+ _process = new Process.start(_executable, _batchArguments);
_stdoutStream = new StringInputStream(_process.stdout);
_stderrStream = new StringInputStream(_process.stderr);
_testStdout = new List<String>();
@@ -485,7 +519,6 @@ class DartcBatchRunnerProcess {
}
}
-
/**
* ProcessQueue is the master control class, responsible for running all
* the tests in all the TestSuites that have been registered. It includes
@@ -513,8 +546,9 @@ class ProcessQueue {
Queue<TestCase> _tests;
ProgressIndicator _progress;
String _temporaryDirectory;
- // For dartc batch processing we keep a list of batch processes.
- List<DartcBatchRunnerProcess> _batchProcesses;
+ // For dartc/selenium batch processing we keep a list of batch processes.
+ Map<String, List<BatchRunnerProcess>> _batchProcesses;
+
// Cache information about test cases per test suite. For multiple
// configurations there is no need to repeatedly search the file
// system, generate tests, and search test files for options.
@@ -537,7 +571,7 @@ class ProcessQueue {
_progress = new ProgressIndicator.fromName(progress,
startTime,
printTiming),
- _batchProcesses = new List<DartcBatchRunnerProcess>(),
+ _batchProcesses = new Map<String, List<BatchRunnerProcess>>(),
_testCache = new Map<String, List<TestInformation>>() {
if (!_enqueueMoreWork(this)) _progress.allDone();
browserUsed = '';
@@ -580,8 +614,9 @@ class ProcessQueue {
if (new Platform().operatingSystem() == 'macos') {
chromeName = 'Google\ Chrome';
}
- Map<String, List<String>> processNames = {'ie': ['iexplore'], 'safari':
- ['Safari'], 'ff': ['firefox'], 'chrome': ['chromedriver', chromeName]};
+ Map<String, List<String>> processNames = {'ie': ['iexplore'],
+ 'safari': ['Safari'], 'ff': ['firefox', 'firefox-bin'],
+ 'chrome': ['chromedriver', chromeName]};
for (String name in processNames[browserUsed]) {
Process process = null;
if (new Platform().operatingSystem() == 'windows') {
@@ -626,7 +661,7 @@ class ProcessQueue {
if (_activeTestListers == 0 && !_enqueueMoreWork(this)) {
_progress.allTestsKnown();
if (_tests.isEmpty() && _numProcesses == 0) {
- _terminateDartcBatchRunners();
+ _terminateBatchRunners();
if (_keepGeneratedTests || _temporaryDirectory == null) {
_cleanupAndMarkDone();
} else if (!_temporaryDirectory.startsWith('/tmp/') ||
@@ -663,21 +698,27 @@ class ProcessQueue {
_tryRunTest();
}
- void _terminateDartcBatchRunners() {
- _batchProcesses.forEach((runner) => runner.terminate());
+ void _terminateBatchRunners() {
+ for (var runners in _batchProcesses.getValues()) {
+ for (var runner in runners) {
+ runner.terminate();
+ }
+ }
}
- void _ensureDartcBatchRunnersStarted(String executable) {
- if (_batchProcesses.length == 0) {
+ BatchRunnerProcess _getBatchRunner(TestCase test) {
+ // Start batch processes if needed
+ var component = test.configuration['component'];
+ var runners = _batchProcesses[component];
+ if (runners == null) {
+ runners = new List<BatchRunnerProcess>(_maxProcesses);
for (int i = 0; i < _maxProcesses; i++) {
- _batchProcesses.add(new DartcBatchRunnerProcess(executable));
+ runners[i] = new BatchRunnerProcess(test);
}
+ _batchProcesses[component] = runners;
}
- }
- DartcBatchRunnerProcess _getDartcBatchRunnerProcess() {
- for (int i = 0; i < _batchProcesses.length; i++) {
- var runner = _batchProcesses[i];
+ for (var runner in runners) {
if (!runner.active) return runner;
}
throw new Exception('Unable to find inactive batch runner.');
@@ -705,20 +746,19 @@ class ProcessQueue {
oldCallback(test_arg);
};
test.completedHandler = wrapper;
- if (test.configuration['component'] == 'dartc' &&
+ if (test.configuration['component'] == 'dartc' &&
test.displayName != 'dartc/junit_tests') {
- _ensureDartcBatchRunnersStarted(test.executablePath);
- _getDartcBatchRunnerProcess().startTest(test);
+ _getBatchRunner(test).startTest(test);
} else {
// Once we've actually failed a test, technically, we wouldn't need to
- // bother retrying any subsequent tests since the bot is already red.
- // However, we continue to retry tests until we have actually failed
- // four tests (arbitrarily chosen) for more debugable output, so that
- // the developer doesn't waste his or her time trying to fix a bunch of
- // tests that appear to be broken but were actually just flakes that
+ // bother retrying any subsequent tests since the bot is already red.
+ // However, we continue to retry tests until we have actually failed
+ // four tests (arbitrarily chosen) for more debugable output, so that
+ // the developer doesn't waste his or her time trying to fix a bunch of
+ // tests that appear to be broken but were actually just flakes that
// didn't get retried because there had already been one failure.
- new RunningProcess(test,
- _MAX_FAILED_NO_RETRY > _progress.numFailedTests).start();
+ bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests;
+ new RunningProcess(test, allowRetry, this).start();
}
_numProcesses++;
}
« no previous file with comments | « no previous file | tools/testing/dart/test_suite.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698