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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/testing/dart/test_suite.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 92
93 int get timeout() => configuration['timeout']; 93 int get timeout() => configuration['timeout'];
94 94
95 String get configurationString() { 95 String get configurationString() {
96 final component = configuration['component']; 96 final component = configuration['component'];
97 final mode = configuration['mode']; 97 final mode = configuration['mode'];
98 final arch = configuration['arch']; 98 final arch = configuration['arch'];
99 return "$component ${mode}_$arch"; 99 return "$component ${mode}_$arch";
100 } 100 }
101 101
102 List<String> get batchRunnerArguments() => ['-batch'];
103 List<String> get batchTestArguments() => arguments;
104
102 void completed() { completedHandler(this); } 105 void completed() { completedHandler(this); }
103 } 106 }
104 107
105 108
106 /** 109 /**
107 * BrowserTestCase has an extra compilation command that is run in a separate 110 * BrowserTestCase has an extra compilation command that is run in a separate
108 * process, before the regular test is run as in the base class [TestCase]. 111 * process, before the regular test is run as in the base class [TestCase].
109 * If the compilation command fails, then the rest of the test is not run. 112 * If the compilation command fails, then the rest of the test is not run.
110 */ 113 */
111 class BrowserTestCase extends TestCase { 114 class BrowserTestCase extends TestCase {
(...skipping 27 matching lines...) Expand all
139 expectedOutcomes, 142 expectedOutcomes,
140 isNegative) { 143 isNegative) {
141 if (compilerPath != null) { 144 if (compilerPath != null) {
142 commandLine = 'execution command: $commandLine'; 145 commandLine = 'execution command: $commandLine';
143 String compilationCommand = 146 String compilationCommand =
144 '$compilerPath ${Strings.join(compilerArguments, " ")}'; 147 '$compilerPath ${Strings.join(compilerArguments, " ")}';
145 commandLine = 'compilation command: $compilationCommand\n$commandLine'; 148 commandLine = 'compilation command: $compilationCommand\n$commandLine';
146 } 149 }
147 numRetries = 2; // Allow two retries to compensate for flaky browser tests. 150 numRetries = 2; // Allow two retries to compensate for flaky browser tests.
148 } 151 }
152
153 List<String> get batchRunnerArguments() => [arguments[0], '--batch'];
154 List<String> get batchTestArguments() =>
155 arguments.getRange(1, arguments.length - 1);
149 } 156 }
150 157
151 158
152 /** 159 /**
153 * TestOutput records the output of a completed test: the process's exit code, 160 * TestOutput records the output of a completed test: the process's exit code,
154 * the standard output and standard error, whether the process timed out, and 161 * the standard output and standard error, whether the process timed out, and
155 * the time the process took to run. It also contains a pointer to the 162 * the time the process took to run. It also contains a pointer to the
156 * [TestCase] this is the output of. 163 * [TestCase] this is the output of.
157 */ 164 */
158 class TestOutput { 165 class TestOutput {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 208
202 // Browser case: 209 // Browser case:
203 // If the browser test failed, it may have been because DumpRenderTree 210 // If the browser test failed, it may have been because DumpRenderTree
204 // and the virtual framebuffer X server didn't hook up, or DRT crashed with 211 // and the virtual framebuffer X server didn't hook up, or DRT crashed with
205 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS, 212 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS,
206 // so we have to do this check first. 213 // so we have to do this check first.
207 for (String line in stderr) { 214 for (String line in stderr) {
208 if (line.contains('Gtk-WARNING **: cannot open display: :99') || 215 if (line.contains('Gtk-WARNING **: cannot open display: :99') ||
209 line.contains('Failed to run command. return code=1')) { 216 line.contains('Failed to run command. return code=1')) {
210 // If we get the X server error, or DRT crashes with a core dump, retry 217 // If we get the X server error, or DRT crashes with a core dump, retry
211 // the test. 218 // the test.
212 requestRetry = true; 219 requestRetry = true;
213 return true; 220 return true;
214 } 221 }
215 } 222 }
216 223
217 // Browser tests fail unless stdout contains 224 // Browser tests fail unless stdout contains
218 // 'Content-Type: text/plain\nPASS'. 225 // 'Content-Type: text/plain\nPASS'.
219 String previous_line = ''; 226 String previous_line = '';
220 for (String line in stdout) { 227 for (String line in stdout) {
221 if (line == 'PASS' && previous_line == 'Content-Type: text/plain') { 228 if (line == 'PASS' && previous_line == 'Content-Type: text/plain') {
(...skipping 13 matching lines...) Expand all
235 * A RunningProcess actually runs a test, getting the command lines from 242 * A RunningProcess actually runs a test, getting the command lines from
236 * its [TestCase], starting the test process (and first, a compilation 243 * its [TestCase], starting the test process (and first, a compilation
237 * process if the TestCase is a [BrowserTestCase]), creating a timeout 244 * process if the TestCase is a [BrowserTestCase]), creating a timeout
238 * timer, and recording the results in a new [TestOutput] object, which it 245 * timer, and recording the results in a new [TestOutput] object, which it
239 * attaches to the TestCase. The lifetime of the RunningProcess is limited 246 * attaches to the TestCase. The lifetime of the RunningProcess is limited
240 * to the time it takes to start the process, run the process, and record 247 * to the time it takes to start the process, run the process, and record
241 * the result; there are no pointers to it, so it should be available to 248 * the result; there are no pointers to it, so it should be available to
242 * be garbage collected as soon as it is done. 249 * be garbage collected as soon as it is done.
243 */ 250 */
244 class RunningProcess { 251 class RunningProcess {
252 ProcessQueue processQueue;
245 Process process; 253 Process process;
246 TestCase testCase; 254 TestCase testCase;
247 bool timedOut = false; 255 bool timedOut = false;
248 Date startTime; 256 Date startTime;
249 Timer timeoutTimer; 257 Timer timeoutTimer;
250 List<String> stdout; 258 List<String> stdout;
251 List<String> stderr; 259 List<String> stderr;
252 List<Function> handlers; 260 List<Function> handlers;
253 bool allowRetries = false; 261 bool allowRetries = false;
254 262
255 RunningProcess(TestCase this.testCase, [this.allowRetries]); 263 RunningProcess(TestCase this.testCase,
264 [this.allowRetries, this.processQueue]);
256 265
257 void exitHandler(int exitCode) { 266 void exitHandler(int exitCode) {
258 new TestOutput(testCase, exitCode, timedOut, stdout, 267 new TestOutput(testCase, exitCode, timedOut, stdout,
259 stderr, new Date.now().difference(startTime)); 268 stderr, new Date.now().difference(startTime));
260 process.close(); 269 process.close();
261 timeoutTimer.cancel(); 270 timeoutTimer.cancel();
262 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) { 271 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) {
263 print(testCase.displayName); 272 print(testCase.displayName);
264 for (var line in testCase.output.stderr) print(line); 273 for (var line in testCase.output.stderr) print(line);
265 for (var line in testCase.output.stdout) print(line); 274 for (var line in testCase.output.stdout) print(line);
266 } 275 }
267 if (allowRetries != null && allowRetries 276 if (allowRetries != null && allowRetries
268 && testCase.configuration['component'] == 'webdriver' && 277 && testCase.configuration['component'] == 'webdriver' &&
269 testCase.output.unexpectedOutput && testCase.numRetries > 0) { 278 testCase.output.unexpectedOutput && testCase.numRetries > 0) {
270 // Selenium tests can be flaky. Try rerunning. 279 // Selenium tests can be flaky. Try rerunning.
271 testCase.output.requestRetry = true; 280 testCase.output.requestRetry = true;
272 } 281 }
273 if (testCase.output.requestRetry) { 282 if (testCase.output.requestRetry) {
274 testCase.output.requestRetry = false; 283 testCase.output.requestRetry = false;
275 this.timedOut = false; 284 this.timedOut = false;
276 testCase.dynamic.numRetries--; 285 testCase.dynamic.numRetries--;
277 print("Potential flake. Re-running " + testCase.displayName); 286 print("Potential flake. Re-running " + testCase.displayName);
278 this.start(); 287 this.start();
279 } else { 288 } else {
280 testCase.completed(); 289 testCase.completed();
281 } 290 }
282 } 291 }
283 292
284 void compilerExitHandler(int exitCode) { 293 void compilerExitHandler(int exitCode) {
285 if (exitCode != 0) { 294 if (exitCode != 0) {
286 stderr.add('test.dart: Compilation step failed (exit code $exitCode)\n'); 295 stderr.add('test.dart: Compilation step failed (exit code $exitCode)\n');
287 exitHandler(exitCode); 296 exitHandler(exitCode);
288 } else { 297 } else {
289 process.close(); 298 process.close();
290 stderr.add('test.dart: Compilation finished, starting execution\n'); 299 stderr.add('test.dart: Compilation finished, starting execution\n');
291 stdout.add('test.dart: Compilation finished, starting execution\n'); 300 stdout.add('test.dart: Compilation finished, starting execution\n');
292 runCommand(testCase.executablePath, testCase.arguments, exitHandler); 301 if (testCase.configuration['component'] == 'webdriver') {
302 // Note: processQueue will always be non-null for component == webdriver
303 // (It is only null for component == vm)
304 processQueue._getBatchRunner(testCase).startTest(testCase);
305 } else {
306 runCommand(testCase.executablePath, testCase.arguments, exitHandler);
307 }
293 } 308 }
294 } 309 }
295 310
296 Function makeReadHandler(StringInputStream source, List<String> destination) { 311 Function makeReadHandler(StringInputStream source, List<String> destination) {
297 return () { 312 return () {
298 if (source.closed) return; // TODO(whesse): Remove when bug is fixed. 313 if (source.closed) return; // TODO(whesse): Remove when bug is fixed.
299 var line = source.readLine(); 314 var line = source.readLine();
300 while (null != line) { 315 while (null != line) {
301 destination.add(line); 316 destination.add(line);
302 line = source.readLine(); 317 line = source.readLine();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 makeReadHandler(stderrStringStream, stderr); 354 makeReadHandler(stderrStringStream, stderr);
340 timeoutTimer = new Timer(timeoutHandler, 1000 * testCase.timeout); 355 timeoutTimer = new Timer(timeoutHandler, 1000 * testCase.timeout);
341 } 356 }
342 357
343 void timeoutHandler(Timer unusedTimer) { 358 void timeoutHandler(Timer unusedTimer) {
344 timedOut = true; 359 timedOut = true;
345 process.kill(); 360 process.kill();
346 } 361 }
347 } 362 }
348 363
349 364 class BatchRunnerProcess {
350 class DartcBatchRunnerProcess {
351 String _executable; 365 String _executable;
366 List<String> _batchArguments;
352 367
353 Process _process; 368 Process _process;
354 StringInputStream _stdoutStream; 369 StringInputStream _stdoutStream;
355 StringInputStream _stderrStream; 370 StringInputStream _stderrStream;
356 371
357 TestCase _currentTest; 372 TestCase _currentTest;
358 List<String> _testStdout; 373 List<String> _testStdout;
359 List<String> _testStderr; 374 List<String> _testStderr;
360 Date _startTime; 375 Date _startTime;
361 Timer _timer; 376 Timer _timer;
362 377
363 DartcBatchRunnerProcess(String this._executable); 378 bool _isWebDriver;
379
380 BatchRunnerProcess(TestCase testCase) {
381 _executable = testCase.executablePath;
382 _batchArguments = testCase.batchRunnerArguments;
383 _isWebDriver = testCase.configuration['component'] == 'webdriver';
384 }
364 385
365 bool get active() => _currentTest != null; 386 bool get active() => _currentTest != null;
366 387
367 void startTest(TestCase testCase) { 388 void startTest(TestCase testCase) {
368 _currentTest = testCase; 389 _currentTest = testCase;
369 if (_process === null) { 390 if (_process === null) {
370 // Start process if not yet started. 391 // Start process if not yet started.
371 _executable = testCase.executablePath; 392 _executable = testCase.executablePath;
Bill Hesse 2012/09/25 12:48:45 Why isn't there an assignment to _batchArguments h
372 _startProcess(() { 393 _startProcess(() {
373 doStartTest(testCase); 394 doStartTest(testCase);
374 }); 395 });
375 } else if (testCase.executablePath != _executable) { 396 } else if (testCase.executablePath != _executable) {
376 // Restart this runner with the right executable for this test 397 // Restart this runner with the right executable for this test
377 // if needed. 398 // if needed.
378 _executable = testCase.executablePath; 399 _executable = testCase.executablePath;
400 _batchArguments = testCase.batchRunnerArguments;
379 _process.exitHandler = (exitCode) { 401 _process.exitHandler = (exitCode) {
380 _process.close(); 402 _process.close();
381 _startProcess(() { 403 _startProcess(() {
382 doStartTest(testCase); 404 doStartTest(testCase);
383 }); 405 });
384 }; 406 };
385 _process.kill(); 407 _process.kill();
386 } else { 408 } else {
387 doStartTest(testCase); 409 doStartTest(testCase);
388 } 410 }
389 } 411 }
390 412
391 void terminate() { 413 void terminate() {
392 if (_process !== null) { 414 if (_process !== null) {
415 bool closed = false;
393 _process.exitHandler = (exitCode) { 416 _process.exitHandler = (exitCode) {
417 closed = true;
394 _process.close(); 418 _process.close();
395 }; 419 };
396 _process.kill(); 420 if (_isWebDriver) {
421 // Use a graceful shutdown so our Selenium script can close
422 // the open browser processes. TODO(jmesserly): Send a signal once
423 // that's supported, see dartbug.com/1756.
424 _process.stdin.write('--terminate\n'.charCodes());
425
426 // In case the run_selenium process didn't close, kill it after 30s
427 bool shutdownMillisecs = 30000;
428 new Timer((e) { if (!closed) _process.kill(); }, shutdownMillisecs);
429 } else {
430 _process.kill();
431 }
397 } 432 }
398 } 433 }
399 434
400 void doStartTest(TestCase testCase) { 435 void doStartTest(TestCase testCase) {
401 _startTime = new Date.now(); 436 _startTime = new Date.now();
402 _testStdout = new List<String>(); 437 _testStdout = new List<String>();
403 _testStderr = new List<String>(); 438 _testStderr = new List<String>();
404 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout); 439 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout);
405 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr); 440 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr);
406 _timer = new Timer(_timeoutHandler(testCase), testCase.timeout * 1000); 441 _timer = new Timer(_timeoutHandler, testCase.timeout * 1000);
407 _process.stdin.write(_createArgumentsLine(testCase.arguments).charCodes()); 442 var line = _createArgumentsLine(testCase.batchTestArguments);
443 _process.stdin.write(line.charCodes());
408 } 444 }
409 445
410 String _createArgumentsLine(List<String> arguments) { 446 String _createArgumentsLine(List<String> arguments) {
411 return Strings.join(arguments, ' ') + '\n'; 447 return Strings.join(arguments, ' ') + '\n';
412 } 448 }
413 449
414 int _reportResult(String output) { 450 int _reportResult(String output) {
415 var test = _currentTest; 451 var test = _currentTest;
416 _currentTest = null; 452 _currentTest = null;
417 453
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 } 489 }
454 490
455 void _exitHandler(exitCode) { 491 void _exitHandler(exitCode) {
456 if (_timer != null) _timer.cancel(); 492 if (_timer != null) _timer.cancel();
457 _process.close(); 493 _process.close();
458 _startProcess(() { 494 _startProcess(() {
459 _reportResult(">>> TEST CRASH"); 495 _reportResult(">>> TEST CRASH");
460 }); 496 });
461 } 497 }
462 498
463 Function _timeoutHandler(TestCase test) { 499 void _timeoutHandler(ignore) {
464 return (ignore) { 500 _process.exitHandler = (exitCode) {
465 _process.exitHandler = (exitCode) { 501 _process.close();
466 _process.close(); 502 _startProcess(() {
467 _startProcess(() { 503 _reportResult(">>> TEST TIMEOUT");
468 _reportResult(">>> TEST TIMEOUT"); 504 });
469 });
470 };
471 _process.kill();
472 }; 505 };
506 _process.kill();
473 } 507 }
474 508
475 void _startProcess(then) { 509 void _startProcess(then) {
476 _process = new Process.start(_executable, ['-batch']); 510 _process = new Process.start(_executable, _batchArguments);
477 _stdoutStream = new StringInputStream(_process.stdout); 511 _stdoutStream = new StringInputStream(_process.stdout);
478 _stderrStream = new StringInputStream(_process.stderr); 512 _stderrStream = new StringInputStream(_process.stderr);
479 _testStdout = new List<String>(); 513 _testStdout = new List<String>();
480 _testStderr = new List<String>(); 514 _testStderr = new List<String>();
481 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout); 515 _stdoutStream.lineHandler = _readOutput(_stdoutStream, _testStdout);
482 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr); 516 _stderrStream.lineHandler = _readOutput(_stderrStream, _testStderr);
483 _process.exitHandler = _exitHandler; 517 _process.exitHandler = _exitHandler;
484 _process.startHandler = then; 518 _process.startHandler = then;
485 } 519 }
486 } 520 }
487 521
488
489 /** 522 /**
490 * ProcessQueue is the master control class, responsible for running all 523 * ProcessQueue is the master control class, responsible for running all
491 * the tests in all the TestSuites that have been registered. It includes 524 * the tests in all the TestSuites that have been registered. It includes
492 * a rate-limited queue to run a limited number of tests in parallel, 525 * a rate-limited queue to run a limited number of tests in parallel,
493 * a ProgressIndicator which prints output when tests are started and 526 * a ProgressIndicator which prints output when tests are started and
494 * and completed, and a summary report when all tests are completed, 527 * and completed, and a summary report when all tests are completed,
495 * and counters to determine when all of the tests in all of the test suites 528 * and counters to determine when all of the tests in all of the test suites
496 * have completed. 529 * have completed.
497 * 530 *
498 * Because multiple configurations may be run on each test suite, the 531 * Because multiple configurations may be run on each test suite, the
499 * ProcessQueue contains a cache in which a test suite may record information 532 * ProcessQueue contains a cache in which a test suite may record information
500 * about its list of tests, and may retrieve that information when it is called 533 * about its list of tests, and may retrieve that information when it is called
501 * upon to enqueue its tests again. 534 * upon to enqueue its tests again.
502 */ 535 */
503 class ProcessQueue { 536 class ProcessQueue {
504 int _numProcesses = 0; 537 int _numProcesses = 0;
505 int _activeTestListers = 0; 538 int _activeTestListers = 0;
506 int _maxProcesses; 539 int _maxProcesses;
507 /** The number of tests we allow to actually fail before we stop retrying. */ 540 /** The number of tests we allow to actually fail before we stop retrying. */
508 int _MAX_FAILED_NO_RETRY = 4; 541 int _MAX_FAILED_NO_RETRY = 4;
509 bool _verbose; 542 bool _verbose;
510 bool _listTests; 543 bool _listTests;
511 bool _keepGeneratedTests; 544 bool _keepGeneratedTests;
512 Function _enqueueMoreWork; 545 Function _enqueueMoreWork;
513 Queue<TestCase> _tests; 546 Queue<TestCase> _tests;
514 ProgressIndicator _progress; 547 ProgressIndicator _progress;
515 String _temporaryDirectory; 548 String _temporaryDirectory;
516 // For dartc batch processing we keep a list of batch processes. 549 // For dartc/selenium batch processing we keep a list of batch processes.
517 List<DartcBatchRunnerProcess> _batchProcesses; 550 Map<String, List<BatchRunnerProcess>> _batchProcesses;
551
518 // Cache information about test cases per test suite. For multiple 552 // Cache information about test cases per test suite. For multiple
519 // configurations there is no need to repeatedly search the file 553 // configurations there is no need to repeatedly search the file
520 // system, generate tests, and search test files for options. 554 // system, generate tests, and search test files for options.
521 Map<String, List<TestInformation>> _testCache; 555 Map<String, List<TestInformation>> _testCache;
522 /** 556 /**
523 * String indicating the browser used to run the tests. Empty if no browser 557 * String indicating the browser used to run the tests. Empty if no browser
524 * used. 558 * used.
525 */ 559 */
526 String browserUsed; 560 String browserUsed;
527 561
528 ProcessQueue(int this._maxProcesses, 562 ProcessQueue(int this._maxProcesses,
529 String progress, 563 String progress,
530 Date startTime, 564 Date startTime,
531 bool printTiming, 565 bool printTiming,
532 Function this._enqueueMoreWork, 566 Function this._enqueueMoreWork,
533 [bool this._verbose = false, 567 [bool this._verbose = false,
534 bool this._listTests = false, 568 bool this._listTests = false,
535 bool this._keepGeneratedTests = false]) 569 bool this._keepGeneratedTests = false])
536 : _tests = new Queue<TestCase>(), 570 : _tests = new Queue<TestCase>(),
537 _progress = new ProgressIndicator.fromName(progress, 571 _progress = new ProgressIndicator.fromName(progress,
538 startTime, 572 startTime,
539 printTiming), 573 printTiming),
540 _batchProcesses = new List<DartcBatchRunnerProcess>(), 574 _batchProcesses = new Map<String, List<BatchRunnerProcess>>(),
541 _testCache = new Map<String, List<TestInformation>>() { 575 _testCache = new Map<String, List<TestInformation>>() {
542 if (!_enqueueMoreWork(this)) _progress.allDone(); 576 if (!_enqueueMoreWork(this)) _progress.allDone();
543 browserUsed = ''; 577 browserUsed = '';
544 } 578 }
545 579
546 /** 580 /**
547 * Registers a TestSuite so that all of its tests will be run. 581 * Registers a TestSuite so that all of its tests will be run.
548 */ 582 */
549 void addTestSuite(TestSuite testSuite) { 583 void addTestSuite(TestSuite testSuite) {
550 _activeTestListers++; 584 _activeTestListers++;
(...skipping 22 matching lines...) Expand all
573 /** 607 /**
574 * Sometimes Webdriver doesn't close every browser window when it's done 608 * Sometimes Webdriver doesn't close every browser window when it's done
575 * with a test. At the end of all tests we clear out any neglected processes 609 * with a test. At the end of all tests we clear out any neglected processes
576 * that are still running. 610 * that are still running.
577 */ 611 */
578 void killZombieBrowsers() { 612 void killZombieBrowsers() {
579 String chromeName = 'chrome'; 613 String chromeName = 'chrome';
580 if (new Platform().operatingSystem() == 'macos') { 614 if (new Platform().operatingSystem() == 'macos') {
581 chromeName = 'Google\ Chrome'; 615 chromeName = 'Google\ Chrome';
582 } 616 }
583 Map<String, List<String>> processNames = {'ie': ['iexplore'], 'safari': 617 Map<String, List<String>> processNames = {'ie': ['iexplore'],
584 ['Safari'], 'ff': ['firefox'], 'chrome': ['chromedriver', chromeName]}; 618 'safari': ['Safari'], 'ff': ['firefox', 'firefox-bin'],
619 'chrome': ['chromedriver', chromeName]};
585 for (String name in processNames[browserUsed]) { 620 for (String name in processNames[browserUsed]) {
586 Process process = null; 621 Process process = null;
587 if (new Platform().operatingSystem() == 'windows') { 622 if (new Platform().operatingSystem() == 'windows') {
588 process = new Process.start( 623 process = new Process.start(
589 'C:\\Windows\\System32\\taskkill.exe', ['/F', '/IM', name + '.exe', 624 'C:\\Windows\\System32\\taskkill.exe', ['/F', '/IM', name + '.exe',
590 '/T']); 625 '/T']);
591 } else { 626 } else {
592 process = new Process.start('killall', ['-9', name]); 627 process = new Process.start('killall', ['-9', name]);
593 } 628 }
594 629
(...skipping 24 matching lines...) Expand all
619 _progress.allDone(); 654 _progress.allDone();
620 } 655 }
621 } 656 }
622 657
623 void _checkDone() { 658 void _checkDone() {
624 // When there are no more active test listers ask for more work 659 // When there are no more active test listers ask for more work
625 // from process queue users. 660 // from process queue users.
626 if (_activeTestListers == 0 && !_enqueueMoreWork(this)) { 661 if (_activeTestListers == 0 && !_enqueueMoreWork(this)) {
627 _progress.allTestsKnown(); 662 _progress.allTestsKnown();
628 if (_tests.isEmpty() && _numProcesses == 0) { 663 if (_tests.isEmpty() && _numProcesses == 0) {
629 _terminateDartcBatchRunners(); 664 _terminateBatchRunners();
630 if (_keepGeneratedTests || _temporaryDirectory == null) { 665 if (_keepGeneratedTests || _temporaryDirectory == null) {
631 _cleanupAndMarkDone(); 666 _cleanupAndMarkDone();
632 } else if (!_temporaryDirectory.startsWith('/tmp/') || 667 } else if (!_temporaryDirectory.startsWith('/tmp/') ||
633 _temporaryDirectory.contains('/../')) { 668 _temporaryDirectory.contains('/../')) {
634 // Let's be extra careful, since rm -rf is so dangerous. 669 // Let's be extra careful, since rm -rf is so dangerous.
635 print('Temporary directory $_temporaryDirectory unsafe to delete!'); 670 print('Temporary directory $_temporaryDirectory unsafe to delete!');
636 _cleanupAndMarkDone(); 671 _cleanupAndMarkDone();
637 } else { 672 } else {
638 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is 673 // TODO(dart:1211): Use delete(recursive=true) in Dart when it is
639 // implemented, and add Windows support. 674 // implemented, and add Windows support.
(...skipping 16 matching lines...) Expand all
656 691
657 void _runTest(TestCase test) { 692 void _runTest(TestCase test) {
658 if (test.configuration['component'] == 'webdriver') { 693 if (test.configuration['component'] == 'webdriver') {
659 browserUsed = test.configuration['browser']; 694 browserUsed = test.configuration['browser'];
660 } 695 }
661 _progress.testAdded(); 696 _progress.testAdded();
662 _tests.add(test); 697 _tests.add(test);
663 _tryRunTest(); 698 _tryRunTest();
664 } 699 }
665 700
666 void _terminateDartcBatchRunners() { 701 void _terminateBatchRunners() {
667 _batchProcesses.forEach((runner) => runner.terminate()); 702 for (var runners in _batchProcesses.getValues()) {
668 } 703 for (var runner in runners) {
669 704 runner.terminate();
670 void _ensureDartcBatchRunnersStarted(String executable) {
671 if (_batchProcesses.length == 0) {
672 for (int i = 0; i < _maxProcesses; i++) {
673 _batchProcesses.add(new DartcBatchRunnerProcess(executable));
674 } 705 }
675 } 706 }
676 } 707 }
677 708
678 DartcBatchRunnerProcess _getDartcBatchRunnerProcess() { 709 BatchRunnerProcess _getBatchRunner(TestCase test) {
679 for (int i = 0; i < _batchProcesses.length; i++) { 710 // Start batch processes if needed
680 var runner = _batchProcesses[i]; 711 var component = test.configuration['component'];
712 var runners = _batchProcesses[component];
713 if (runners == null) {
714 runners = new List<BatchRunnerProcess>(_maxProcesses);
715 for (int i = 0; i < _maxProcesses; i++) {
716 runners[i] = new BatchRunnerProcess(test);
717 }
718 _batchProcesses[component] = runners;
719 }
720
721 for (var runner in runners) {
681 if (!runner.active) return runner; 722 if (!runner.active) return runner;
682 } 723 }
683 throw new Exception('Unable to find inactive batch runner.'); 724 throw new Exception('Unable to find inactive batch runner.');
684 } 725 }
685 726
686 void _tryRunTest() { 727 void _tryRunTest() {
687 _checkDone(); 728 _checkDone();
688 if (_numProcesses < _maxProcesses && !_tests.isEmpty()) { 729 if (_numProcesses < _maxProcesses && !_tests.isEmpty()) {
689 TestCase test = _tests.removeFirst(); 730 TestCase test = _tests.removeFirst();
690 if (_verbose) print(test.commandLine); 731 if (_verbose) print(test.commandLine);
691 if (_listTests) { 732 if (_listTests) {
692 final String tab = '\t'; 733 final String tab = '\t';
693 String outcomes = 734 String outcomes =
694 Strings.join(new List.from(test.expectedOutcomes), ','); 735 Strings.join(new List.from(test.expectedOutcomes), ',');
695 print(test.displayName + tab + outcomes + tab + test.isNegative + 736 print(test.displayName + tab + outcomes + tab + test.isNegative +
696 tab + Strings.join(test.arguments, tab)); 737 tab + Strings.join(test.arguments, tab));
697 return; 738 return;
698 } 739 }
699 _progress.start(test); 740 _progress.start(test);
700 Function oldCallback = test.completedHandler; 741 Function oldCallback = test.completedHandler;
701 Function wrapper = (TestCase test_arg) { 742 Function wrapper = (TestCase test_arg) {
702 _numProcesses--; 743 _numProcesses--;
703 _progress.done(test_arg); 744 _progress.done(test_arg);
704 _tryRunTest(); 745 _tryRunTest();
705 oldCallback(test_arg); 746 oldCallback(test_arg);
706 }; 747 };
707 test.completedHandler = wrapper; 748 test.completedHandler = wrapper;
708 if (test.configuration['component'] == 'dartc' && 749 if (test.configuration['component'] == 'dartc' &&
709 test.displayName != 'dartc/junit_tests') { 750 test.displayName != 'dartc/junit_tests') {
710 _ensureDartcBatchRunnersStarted(test.executablePath); 751 _getBatchRunner(test).startTest(test);
711 _getDartcBatchRunnerProcess().startTest(test);
712 } else { 752 } else {
713 // Once we've actually failed a test, technically, we wouldn't need to 753 // Once we've actually failed a test, technically, we wouldn't need to
714 // bother retrying any subsequent tests since the bot is already red. 754 // bother retrying any subsequent tests since the bot is already red.
715 // However, we continue to retry tests until we have actually failed 755 // However, we continue to retry tests until we have actually failed
716 // four tests (arbitrarily chosen) for more debugable output, so that 756 // four tests (arbitrarily chosen) for more debugable output, so that
717 // the developer doesn't waste his or her time trying to fix a bunch of 757 // the developer doesn't waste his or her time trying to fix a bunch of
718 // tests that appear to be broken but were actually just flakes that 758 // tests that appear to be broken but were actually just flakes that
719 // didn't get retried because there had already been one failure. 759 // didn't get retried because there had already been one failure.
720 new RunningProcess(test, 760 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests;
721 _MAX_FAILED_NO_RETRY > _progress.numFailedTests).start(); 761 new RunningProcess(test, allowRetry, this).start();
722 } 762 }
723 _numProcesses++; 763 _numProcesses++;
724 } 764 }
725 } 765 }
726 } 766 }
OLDNEW
« 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