| 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. |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 _lastArguments.getRange(1, _lastArguments.length - 1); | 164 _lastArguments.getRange(1, _lastArguments.length - 1); |
| 165 } | 165 } |
| 166 | 166 |
| 167 | 167 |
| 168 /** | 168 /** |
| 169 * TestOutput records the output of a completed test: the process's exit code, | 169 * TestOutput records the output of a completed test: the process's exit code, |
| 170 * the standard output and standard error, whether the process timed out, and | 170 * the standard output and standard error, whether the process timed out, and |
| 171 * the time the process took to run. It also contains a pointer to the | 171 * the time the process took to run. It also contains a pointer to the |
| 172 * [TestCase] this is the output of. | 172 * [TestCase] this is the output of. |
| 173 */ | 173 */ |
| 174 interface TestOutput default TestOutputImpl { | 174 interface TestOutput default TestOutputImpl { |
| 175 TestOutput.fromCase(TestCase testCase, int exitCode, bool timedOut, | 175 TestOutput.fromCase(TestCase testCase, int exitCode, bool timedOut, |
| 176 List<String> stdout, List<String> stderr, Duration time); | 176 List<String> stdout, List<String> stderr, Duration time); |
| 177 | 177 |
| 178 String get result(); | 178 String get result(); |
| 179 | 179 |
| 180 bool get unexpectedOutput(); | 180 bool get unexpectedOutput(); |
| 181 | 181 |
| 182 bool get hasCrashed(); | 182 bool get hasCrashed(); |
| 183 | 183 |
| 184 bool get hasTimedOut(); | 184 bool get hasTimedOut(); |
| 185 | 185 |
| 186 bool get didFail(); | 186 bool get didFail(); |
| 187 | 187 |
| 188 List<String> get diagnostics(); | 188 List<String> get diagnostics(); |
| 189 } | 189 } |
| 190 | 190 |
| 191 class TestOutputImpl implements TestOutput { | 191 class TestOutputImpl implements TestOutput { |
| 192 TestCase testCase; | 192 TestCase testCase; |
| 193 int exitCode; | 193 int exitCode; |
| 194 bool timedOut; | 194 bool timedOut; |
| 195 bool failed = false; | 195 bool failed = false; |
| 196 List<String> stdout; | 196 List<String> stdout; |
| 197 List<String> stderr; | 197 List<String> stderr; |
| 198 Duration time; | 198 Duration time; |
| 199 List<String> diagnostics; | 199 List<String> diagnostics; |
| 200 | 200 |
| 201 /** | 201 /** |
| 202 * Set to true if we encounter a condition in the output that indicates we | 202 * Set to true if we encounter a condition in the output that indicates we |
| 203 * need to rerun this test. | 203 * need to rerun this test. |
| 204 */ | 204 */ |
| 205 bool requestRetry = false; | 205 bool requestRetry = false; |
| 206 | 206 |
| 207 // Don't call this constructor, call TestOutput.fromCase() to | 207 // Don't call this constructor, call TestOutput.fromCase() to |
| 208 // get anew TestOutput instance. | 208 // get anew TestOutput instance. |
| 209 TestOutputImpl(this.testCase, this.exitCode, this.timedOut, this.stdout, | 209 TestOutputImpl(this.testCase, this.exitCode, this.timedOut, this.stdout, |
| 210 this.stderr, this.time) { | 210 this.stderr, this.time) { |
| 211 testCase.output = this; | 211 testCase.output = this; |
| 212 diagnostics = []; | 212 diagnostics = []; |
| 213 } | 213 } |
| 214 | 214 |
| 215 factory TestOutputImpl.fromCase (testCase, exitCode, timedOut, stdout, stderr,
| 215 factory TestOutputImpl.fromCase (testCase, exitCode, timedOut, |
| 216 time) { | 216 stdout, stderr, time) { |
| 217 if (testCase is BrowserTestCase) { | 217 if (testCase is BrowserTestCase) { |
| 218 return new BrowserTestOutputImpl(testCase, exitCode, timedOut, | 218 return new BrowserTestOutputImpl(testCase, exitCode, timedOut, |
| 219 stdout, stderr, time); | 219 stdout, stderr, time); |
| 220 } else if (testCase.configuration['component'] == 'dartc') { | 220 } else if (testCase.configuration['component'] == 'dartc') { |
| 221 return new AnalysisTestOutputImpl(testCase, exitCode, timedOut, | 221 return new AnalysisTestOutputImpl(testCase, exitCode, timedOut, |
| 222 stdout, stderr, time); | 222 stdout, stderr, time); |
| 223 } | 223 } |
| 224 return new TestOutputImpl(testCase, exitCode, timedOut, | 224 return new TestOutputImpl(testCase, exitCode, timedOut, |
| 225 stdout, stderr, time); | 225 stdout, stderr, time); |
| 226 } | 226 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 249 bool get didFail() { | 249 bool get didFail() { |
| 250 return (exitCode != 0 && !hasCrashed); | 250 return (exitCode != 0 && !hasCrashed); |
| 251 } | 251 } |
| 252 | 252 |
| 253 // Reverse result of a negative test. | 253 // Reverse result of a negative test. |
| 254 bool get hasFailed() => (testCase.isNegative ? !didFail : didFail); | 254 bool get hasFailed() => (testCase.isNegative ? !didFail : didFail); |
| 255 | 255 |
| 256 } | 256 } |
| 257 | 257 |
| 258 class BrowserTestOutputImpl extends TestOutputImpl { | 258 class BrowserTestOutputImpl extends TestOutputImpl { |
| 259 BrowserTestOutputImpl(testCase, exitCode, timedOut, stdout, stderr, time) : | 259 BrowserTestOutputImpl(testCase, exitCode, timedOut, stdout, stderr, time) : |
| 260 super(testCase, exitCode, timedOut, stdout, stderr, time); | 260 super(testCase, exitCode, timedOut, stdout, stderr, time); |
| 261 | 261 |
| 262 bool get didFail() { | 262 bool get didFail() { |
| 263 // Browser case: | 263 // Browser case: |
| 264 // If the browser test failed, it may have been because DumpRenderTree | 264 // If the browser test failed, it may have been because DumpRenderTree |
| 265 // and the virtual framebuffer X server didn't hook up, or DRT crashed with | 265 // and the virtual framebuffer X server didn't hook up, or DRT crashed with |
| 266 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS, | 266 // a core dump. Sometimes DRT crashes after it has set the stdout to PASS, |
| 267 // so we have to do this check first. | 267 // so we have to do this check first. |
| 268 for (String line in stderr) { | 268 for (String line in stderr) { |
| 269 if (line.contains('Gtk-WARNING **: cannot open display: :99') || | 269 if (line.contains('Gtk-WARNING **: cannot open display: :99') || |
| (...skipping 13 matching lines...) Expand all Loading... |
| 283 for (String line in stdout) { | 283 for (String line in stdout) { |
| 284 if (line == 'PASS' && previous_line == 'Content-Type: text/plain') { | 284 if (line == 'PASS' && previous_line == 'Content-Type: text/plain') { |
| 285 return (exitCode != 0 && !hasCrashed); | 285 return (exitCode != 0 && !hasCrashed); |
| 286 } | 286 } |
| 287 previous_line = line; | 287 previous_line = line; |
| 288 } | 288 } |
| 289 return true; | 289 return true; |
| 290 } | 290 } |
| 291 } | 291 } |
| 292 | 292 |
| 293 // The static analyzer does not actaully execute code, so | 293 // The static analyzer does not actaully execute code, so |
| 294 // the criteria for success now depend on the text sent | 294 // the criteria for success now depend on the text sent |
| 295 // to stderr. | 295 // to stderr. |
| 296 class AnalysisTestOutputImpl extends TestOutputImpl { | 296 class AnalysisTestOutputImpl extends TestOutputImpl { |
| 297 boolean alreadyComputed = false; | 297 bool alreadyComputed = false; |
| 298 boolean failResult; | 298 bool failResult; |
| 299 AnalysisTestOutputImpl(testCase, exitCode, timedOut, stdout, stderr, time) : | 299 AnalysisTestOutputImpl(testCase, exitCode, timedOut, stdout, stderr, time) : |
| 300 super(testCase, exitCode, timedOut, stdout, stderr, time) { | 300 super(testCase, exitCode, timedOut, stdout, stderr, time) { |
| 301 } | 301 } |
| 302 | 302 |
| 303 bool get didFail() { | 303 bool get didFail() { |
| 304 if (!alreadyComputed) { | 304 if (!alreadyComputed) { |
| 305 failResult = _didFail(); | 305 failResult = _didFail(); |
| 306 alreadyComputed = true; | 306 alreadyComputed = true; |
| 307 } | 307 } |
| 308 return failResult; | 308 return failResult; |
| 309 } | 309 } |
| 310 | 310 |
| 311 bool _didFail() { | 311 bool _didFail() { |
| 312 if (hasCrashed) return false; | 312 if (hasCrashed) return false; |
| 313 | 313 |
| 314 List<String> errors = []; | 314 List<String> errors = []; |
| 315 List<String> staticWarnings = []; | 315 List<String> staticWarnings = []; |
| 316 | 316 |
| 317 // Read the returned list of errors and stuff them away. | 317 // Read the returned list of errors and stuff them away. |
| 318 for (String line in stderr) { | 318 for (String line in stderr) { |
| 319 if (line.length == 0) continue; | 319 if (line.length == 0) continue; |
| 320 List<String> fields = splitMachineError(line); | 320 List<String> fields = splitMachineError(line); |
| 321 if (fields[0] == 'ERROR') { | 321 if (fields[0] == 'ERROR') { |
| 322 errors.add(fields); | 322 errors.add(fields); |
| 323 } else if (fields[0] == 'WARNING') { | 323 } else if (fields[0] == 'WARNING') { |
| 324 // We only care about testing Static type warnings | 324 // We only care about testing Static type warnings |
| 325 // ignore all others | 325 // ignore all others |
| 326 if (fields[1] == 'STATIC_TYPE') { | 326 if (fields[1] == 'STATIC_TYPE') { |
| 327 staticWarnings.add(fields); | 327 staticWarnings.add(fields); |
| 328 } | 328 } |
| 329 } | 329 } |
| 330 // OK to Skip error output that doesn't match the machine format | 330 // OK to Skip error output that doesn't match the machine format |
| 331 } | 331 } |
| 332 if (testCase.info != null | 332 if (testCase.info != null |
| 333 && testCase.info.optionsFromFile['isMultitest']) { | 333 && testCase.info.optionsFromFile['isMultitest']) { |
| 334 return _didMultitestFail(errors, staticWarnings); | 334 return _didMultitestFail(errors, staticWarnings); |
| 335 } | 335 } |
| 336 return _didStandardTestFail(errors, staticWarnings); | 336 return _didStandardTestFail(errors, staticWarnings); |
| 337 } | 337 } |
| 338 | 338 |
| 339 bool _didMultitestFail(List errors, List staticWarnings) { | 339 bool _didMultitestFail(List errors, List staticWarnings) { |
| 340 String outcome = testCase.info.multitestOutcome; | 340 String outcome = testCase.info.multitestOutcome; |
| 341 if ((outcome == '' || outcome == 'compile-time error') && errors.length > 0)
{ | 341 if ((outcome == '' || outcome == 'compile-time error') && errors.length > 0)
{ |
| 342 return true; | 342 return true; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 if (numStaticTypeAnnotations > 0 && isStaticClean) { | 384 if (numStaticTypeAnnotations > 0 && isStaticClean) { |
| 385 diagnostics.add("Cannot have both @static-clean and /// static type warnin
g annotations."); | 385 diagnostics.add("Cannot have both @static-clean and /// static type warnin
g annotations."); |
| 386 return true; | 386 return true; |
| 387 } | 387 } |
| 388 | 388 |
| 389 if (isStaticClean && staticWarnings.length > 0) { | 389 if (isStaticClean && staticWarnings.length > 0) { |
| 390 diagnostics.add("@static-clean annotation found but analyzer returned warn
ings."); | 390 diagnostics.add("@static-clean annotation found but analyzer returned warn
ings."); |
| 391 return true; | 391 return true; |
| 392 } | 392 } |
| 393 | 393 |
| 394 if (numCompileTimeAnnotations > 0 | 394 if (numCompileTimeAnnotations > 0 |
| 395 && numCompileTimeAnnotations < errors.length) { | 395 && numCompileTimeAnnotations < errors.length) { |
| 396 | 396 |
| 397 // Expected compile-time errors were not returned. The test did not 'fail
' in the way | 397 // Expected compile-time errors were not returned. The test did not 'fail
' in the way |
| 398 // intended so don't return failed. | 398 // intended so don't return failed. |
| 399 diagnostics.add("Fewer compile time errors than annotated: ${numCompileTim
eAnnotations}"); | 399 diagnostics.add("Fewer compile time errors than annotated: ${numCompileTim
eAnnotations}"); |
| 400 return false; | 400 return false; |
| 401 } | 401 } |
| 402 | 402 |
| 403 if (numStaticTypeAnnotations > 0 || hasFatalTypeErrors) { | 403 if (numStaticTypeAnnotations > 0 || hasFatalTypeErrors) { |
| 404 // TODO(zundel): match up the annotation line numbers | 404 // TODO(zundel): match up the annotation line numbers |
| 405 // with the reported error line numbers | 405 // with the reported error line numbers |
| 406 if (staticWarnings.length < numStaticTypeAnnotations) { | 406 if (staticWarnings.length < numStaticTypeAnnotations) { |
| 407 diagnostics.add("Fewer static type warnings than annotated: ${numStaticT
ypeAnnotations}"); | 407 diagnostics.add("Fewer static type warnings than annotated: ${numStaticT
ypeAnnotations}"); |
| 408 return true; | 408 return true; |
| 409 } | 409 } |
| 410 return false; | 410 return false; |
| 411 } else if (errors.length != 0) { | 411 } else if (errors.length != 0) { |
| 412 return true; | 412 return true; |
| 413 } | 413 } |
| 414 return false; | 414 return false; |
| 415 } | 415 } |
| 416 | 416 |
| 417 // Parse a line delimited by the | character using \ as an escape charager | 417 // Parse a line delimited by the | character using \ as an escape charager |
| 418 // like: FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ | 418 // like: FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ |
| 419 List<String> splitMachineError(String line) { | 419 List<String> splitMachineError(String line) { |
| 420 StringBuffer field = new StringBuffer(); | 420 StringBuffer field = new StringBuffer(); |
| 421 List<String> result = []; | 421 List<String> result = []; |
| 422 bool escaped = false; | 422 bool escaped = false; |
| 423 for (var i = 0 ; i < line.length; i++) { | 423 for (var i = 0 ; i < line.length; i++) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 void testComplete(int exitCode) { | 475 void testComplete(int exitCode) { |
| 476 new TestOutput.fromCase(testCase, exitCode, timedOut, stdout, | 476 new TestOutput.fromCase(testCase, exitCode, timedOut, stdout, |
| 477 stderr, new Date.now().difference(startTime)); | 477 stderr, new Date.now().difference(startTime)); |
| 478 timeoutTimer.cancel(); | 478 timeoutTimer.cancel(); |
| 479 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) { | 479 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) { |
| 480 print(testCase.displayName); | 480 print(testCase.displayName); |
| 481 for (var line in testCase.output.stderr) print(line); | 481 for (var line in testCase.output.stderr) print(line); |
| 482 for (var line in testCase.output.stdout) print(line); | 482 for (var line in testCase.output.stdout) print(line); |
| 483 } | 483 } |
| 484 if (allowRetries != null && allowRetries | 484 if (allowRetries != null && allowRetries |
| 485 && testCase.usesWebDriver && testCase.output.unexpectedOutput | 485 && testCase.usesWebDriver && testCase.output.unexpectedOutput |
| 486 && testCase.numRetries > 0) { | 486 && testCase.numRetries > 0) { |
| 487 // Selenium tests can be flaky. Try rerunning. | 487 // Selenium tests can be flaky. Try rerunning. |
| 488 testCase.output.requestRetry = true; | 488 testCase.output.requestRetry = true; |
| 489 } | 489 } |
| 490 if (testCase.output.requestRetry) { | 490 if (testCase.output.requestRetry) { |
| 491 testCase.output.requestRetry = false; | 491 testCase.output.requestRetry = false; |
| 492 this.timedOut = false; | 492 this.timedOut = false; |
| 493 testCase.dynamic.numRetries--; | 493 testCase.dynamic.numRetries--; |
| 494 print("Potential flake. Re-running ${testCase.displayName} " + | 494 print("Potential flake. Re-running ${testCase.displayName} " + |
| 495 "(${testCase.dynamic.numRetries} attempt(s) remains)"); | 495 "(${testCase.dynamic.numRetries} attempt(s) remains)"); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 test.completed(); | 670 test.completed(); |
| 671 } | 671 } |
| 672 | 672 |
| 673 int _reportResult(String output) { | 673 int _reportResult(String output) { |
| 674 _stdoutDrained = true; | 674 _stdoutDrained = true; |
| 675 // output = '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' | 675 // output = '>>> TEST {PASS, FAIL, OK, CRASH, FAIL, TIMEOUT}' |
| 676 var outcome = output.split(" ")[2]; | 676 var outcome = output.split(" ")[2]; |
| 677 var exitCode = 0; | 677 var exitCode = 0; |
| 678 if (outcome == "CRASH") exitCode = -10; | 678 if (outcome == "CRASH") exitCode = -10; |
| 679 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; | 679 if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1; |
| 680 new TestOutput.fromCase(_currentTest, exitCode, outcome == "TIMEOUT", | 680 new TestOutput.fromCase(_currentTest, exitCode, outcome == "TIMEOUT", |
| 681 _testStdout, _testStderr, new Date.now().difference(_startTim
e)); | 681 _testStdout, _testStderr, new Date.now().difference(_startTim
e)); |
| 682 // Move on when both stdout and stderr has been drained. If the test | 682 // Move on when both stdout and stderr has been drained. If the test |
| 683 // crashed, we restarted the process and therefore do not attempt to | 683 // crashed, we restarted the process and therefore do not attempt to |
| 684 // drain stderr. | 684 // drain stderr. |
| 685 if (_stderrDrained || (_currentTest.output.hasCrashed)) _testCompleted(); | 685 if (_stderrDrained || (_currentTest.output.hasCrashed)) _testCompleted(); |
| 686 } | 686 } |
| 687 | 687 |
| 688 void _stderrDone() { | 688 void _stderrDone() { |
| 689 _stderrDrained = true; | 689 _stderrDrained = true; |
| 690 // Move on when both stdout and stderr has been drained. | 690 // Move on when both stdout and stderr has been drained. |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 } | 952 } |
| 953 | 953 |
| 954 /** | 954 /** |
| 955 * True if we are using a browser + platform combination that needs the | 955 * True if we are using a browser + platform combination that needs the |
| 956 * Selenium server jar. | 956 * Selenium server jar. |
| 957 */ | 957 */ |
| 958 bool get _needsSelenium() => new Platform().operatingSystem() == 'macos' && | 958 bool get _needsSelenium() => new Platform().operatingSystem() == 'macos' && |
| 959 browserUsed == 'safari'; | 959 browserUsed == 'safari'; |
| 960 | 960 |
| 961 /** True if the Selenium Server is ready to be used. */ | 961 /** True if the Selenium Server is ready to be used. */ |
| 962 bool get _isSeleniumAvailable() => _seleniumServer != null || | 962 bool get _isSeleniumAvailable() => _seleniumServer != null || |
| 963 _seleniumAlreadyRunning; | 963 _seleniumAlreadyRunning; |
| 964 | 964 |
| 965 /** | 965 /** |
| 966 * Restart all the processes that have been waiting/stopped for the server to | 966 * Restart all the processes that have been waiting/stopped for the server to |
| 967 * start up. If we just call this once we end up with a single-"threaded" run. | 967 * start up. If we just call this once we end up with a single-"threaded" run. |
| 968 */ | 968 */ |
| 969 void resumeTesting() { | 969 void resumeTesting() { |
| 970 for (int i = 0; i < _maxProcesses; i++) _tryRunTest(); | 970 for (int i = 0; i < _maxProcesses; i++) _tryRunTest(); |
| 971 } | 971 } |
| 972 | 972 |
| 973 /** Start the Selenium Server jar, if appropriate for this platform. */ | 973 /** Start the Selenium Server jar, if appropriate for this platform. */ |
| 974 void _ensureSeleniumServerRunning() { | 974 void _ensureSeleniumServerRunning() { |
| 975 if (!_isSeleniumAvailable && !_startingServer) { | 975 if (!_isSeleniumAvailable && !_startingServer) { |
| 976 _startingServer = true; | 976 _startingServer = true; |
| 977 | 977 |
| 978 // Check to see if the jar was already running before the program started. | 978 // Check to see if the jar was already running before the program started. |
| 979 String cmd = 'ps'; | 979 String cmd = 'ps'; |
| 980 var arg = ['aux']; | 980 var arg = ['aux']; |
| 981 if (new Platform().operatingSystem() == 'windows') { | 981 if (new Platform().operatingSystem() == 'windows') { |
| 982 cmd = 'tasklist'; | 982 cmd = 'tasklist'; |
| 983 arg.add('/v'); | 983 arg.add('/v'); |
| 984 } | 984 } |
| 985 Process p = new Process.start(cmd, arg); | 985 Process p = new Process.start(cmd, arg); |
| 986 final StringInputStream stdoutStringStream = | 986 final StringInputStream stdoutStringStream = |
| 987 new StringInputStream(p.stdout); | 987 new StringInputStream(p.stdout); |
| 988 stdoutStringStream.onLine = () { | 988 stdoutStringStream.onLine = () { |
| 989 var line = stdoutStringStream.readLine(); | 989 var line = stdoutStringStream.readLine(); |
| 990 while (null != line) { | 990 while (null != line) { |
| 991 if (const RegExp(@".*selenium-server-standalone.*").hasMatch(line)) { | 991 if (const RegExp(@".*selenium-server-standalone.*").hasMatch(line)) { |
| 992 _seleniumAlreadyRunning = true; | 992 _seleniumAlreadyRunning = true; |
| 993 resumeTesting(); | 993 resumeTesting(); |
| 994 } | 994 } |
| 995 line = stdoutStringStream.readLine(); | 995 line = stdoutStringStream.readLine(); |
| 996 } | 996 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 int index = filePath.lastIndexOf(pathSep); | 1042 int index = filePath.lastIndexOf(pathSep); |
| 1043 filePath = filePath.substring(0, index) + '${pathSep}testing${pathSep}'; | 1043 filePath = filePath.substring(0, index) + '${pathSep}testing${pathSep}'; |
| 1044 var dir = new Directory(filePath); | 1044 var dir = new Directory(filePath); |
| 1045 dir.onFile = (String file) { | 1045 dir.onFile = (String file) { |
| 1046 if (const RegExp(@"selenium-server-standalone-.*\.jar").hasMatch(file) | 1046 if (const RegExp(@"selenium-server-standalone-.*\.jar").hasMatch(file) |
| 1047 && _seleniumServer == null) { | 1047 && _seleniumServer == null) { |
| 1048 _seleniumServer = new Process.start('java', ['-jar', file]); | 1048 _seleniumServer = new Process.start('java', ['-jar', file]); |
| 1049 // Heads up: there seems to an obscure data race of some form in | 1049 // Heads up: there seems to an obscure data race of some form in |
| 1050 // the VM between launching the server process and launching the test | 1050 // the VM between launching the server process and launching the test |
| 1051 // tasks that disappears when you read IO (which is convenient, since | 1051 // tasks that disappears when you read IO (which is convenient, since |
| 1052 // that is our condition for knowing that the server is ready). | 1052 // that is our condition for knowing that the server is ready). |
| 1053 StringInputStream stdoutStringStream = | 1053 StringInputStream stdoutStringStream = |
| 1054 new StringInputStream(_seleniumServer.stdout); | 1054 new StringInputStream(_seleniumServer.stdout); |
| 1055 StringInputStream stderrStringStream = | 1055 StringInputStream stderrStringStream = |
| 1056 new StringInputStream(_seleniumServer.stderr); | 1056 new StringInputStream(_seleniumServer.stderr); |
| 1057 stdoutStringStream.onLine = | 1057 stdoutStringStream.onLine = |
| 1058 makeSeleniumServerHandler(stdoutStringStream); | 1058 makeSeleniumServerHandler(stdoutStringStream); |
| 1059 stderrStringStream.onLine = | 1059 stderrStringStream.onLine = |
| 1060 makeSeleniumServerHandler(stderrStringStream); | 1060 makeSeleniumServerHandler(stderrStringStream); |
| 1061 } | 1061 } |
| 1062 }; | 1062 }; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1128 // the developer doesn't waste his or her time trying to fix a bunch of | 1128 // the developer doesn't waste his or her time trying to fix a bunch of |
| 1129 // tests that appear to be broken but were actually just flakes that | 1129 // tests that appear to be broken but were actually just flakes that |
| 1130 // didn't get retried because there had already been one failure. | 1130 // didn't get retried because there had already been one failure. |
| 1131 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; | 1131 bool allowRetry = _MAX_FAILED_NO_RETRY > _progress.numFailedTests; |
| 1132 new RunningProcess(test, allowRetry, this).start(); | 1132 new RunningProcess(test, allowRetry, this).start(); |
| 1133 } | 1133 } |
| 1134 _numProcesses++; | 1134 _numProcesses++; |
| 1135 } | 1135 } |
| 1136 } | 1136 } |
| 1137 } | 1137 } |
| OLD | NEW |