Chromium Code Reviews| 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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 // exceptions. | 193 // exceptions. |
| 194 return (!timedOut && ((exitCode < 0) || (exitCode == 253))); | 194 return (!timedOut && ((exitCode < 0) || (exitCode == 253))); |
| 195 } | 195 } |
| 196 | 196 |
| 197 bool get hasTimedOut() => timedOut; | 197 bool get hasTimedOut() => timedOut; |
| 198 | 198 |
| 199 bool get didFail() { | 199 bool get didFail() { |
| 200 if (testCase is !BrowserTestCase) return (exitCode != 0 && !hasCrashed); | 200 if (testCase is !BrowserTestCase) return (exitCode != 0 && !hasCrashed); |
| 201 | 201 |
| 202 // Browser case: | 202 // Browser case: |
| 203 // Browser tests fail unless stdout contains | |
| 204 // 'Content-Type: text/plain\nPASS'. | |
| 205 String previous_line = ''; | |
| 206 for (String line in stdout) { | |
| 207 if (line == 'PASS' && previous_line == 'Content-Type: text/plain') { | |
| 208 return (exitCode != 0 && !hasCrashed); | |
|
Emily Fortuna
2012/02/17 19:34:24
Sometimes when DRT crashes with a memory dump, and
Siggi Cherem (dart-lang)
2012/02/17 19:51:38
I thought in that case we wouldn't have PASS in th
Emily Fortuna
2012/02/17 21:03:03
Sometimes it does, and sometimes it doesn't when D
| |
| 209 } | |
| 210 previous_line = line; | |
| 211 } | |
| 212 | |
| 213 // If the browser test failed, it may have been because DumpRenderTree | 203 // If the browser test failed, it may have been because DumpRenderTree |
| 214 // and the virtual framebuffer X server didn't hook up, or DRT crashed with | 204 // and the virtual framebuffer X server didn't hook up, or DRT crashed with |
| 215 // a core dump. | 205 // a core dump. |
| 216 for (String line in stderr) { | 206 for (String line in stderr) { |
| 217 if (line.contains('Gtk-WARNING **: cannot open display: :99') || | 207 if (line.contains('Gtk-WARNING **: cannot open display: :99') || |
| 218 line.contains('Failed to run command. return code=1')) { | 208 line.contains('Failed to run command. return code=1')) { |
| 219 // If we get the X server error, or DRT crashes with a core dump, retry | 209 // If we get the X server error, or DRT crashes with a core dump, retry |
| 220 // the test. | 210 // the test. |
| 221 requestRetry = true; | 211 requestRetry = true; |
| 222 return true; | 212 return true; |
| 223 } | 213 } |
| 224 } | 214 } |
| 215 | |
| 216 // Browser tests fail unless stdout contains | |
| 217 // 'Content-Type: text/plain\nPASS'. | |
| 218 String previous_line = ''; | |
| 219 for (String line in stdout) { | |
| 220 if (line == 'PASS' && previous_line == 'Content-Type: text/plain') { | |
| 221 return (exitCode != 0 && !hasCrashed); | |
| 222 } | |
| 223 previous_line = line; | |
| 224 } | |
| 225 | |
| 225 return true; | 226 return true; |
| 226 } | 227 } |
| 227 | 228 |
| 228 // Reverse result of a negative test. | 229 // Reverse result of a negative test. |
| 229 bool get hasFailed() => (testCase.isNegative ? !didFail : didFail); | 230 bool get hasFailed() => (testCase.isNegative ? !didFail : didFail); |
| 230 } | 231 } |
| 231 | 232 |
| 232 /** | 233 /** |
| 233 * A RunningProcess actually runs a test, getting the command lines from | 234 * A RunningProcess actually runs a test, getting the command lines from |
| 234 * its [TestCase], starting the test process (and first, a compilation | 235 * its [TestCase], starting the test process (and first, a compilation |
| 235 * process if the TestCase is a [BrowserTestCase]), creating a timeout | 236 * process if the TestCase is a [BrowserTestCase]), creating a timeout |
| 236 * timer, and recording the results in a new [TestOutput] object, which it | 237 * timer, and recording the results in a new [TestOutput] object, which it |
| 237 * attaches to the TestCase. The lifetime of the RunningProcess is limited | 238 * attaches to the TestCase. The lifetime of the RunningProcess is limited |
| 238 * to the time it takes to start the process, run the process, and record | 239 * to the time it takes to start the process, run the process, and record |
| 239 * the result; there are no pointers to it, so it should be available to | 240 * the result; there are no pointers to it, so it should be available to |
| 240 * be garbage collected as soon as it is done. | 241 * be garbage collected as soon as it is done. |
| 241 */ | 242 */ |
| 242 class RunningProcess { | 243 class RunningProcess { |
| 243 Process process; | 244 Process process; |
| 244 TestCase testCase; | 245 TestCase testCase; |
| 245 bool timedOut = false; | 246 bool timedOut = false; |
| 246 Date startTime; | 247 Date startTime; |
| 247 Timer timeoutTimer; | 248 Timer timeoutTimer; |
| 248 List<String> stdout; | 249 List<String> stdout; |
| 249 List<String> stderr; | 250 List<String> stderr; |
| 250 List<Function> handlers; | 251 List<Function> handlers; |
| 252 bool allowRetries; | |
| 251 | 253 |
| 252 RunningProcess(TestCase this.testCase); | 254 RunningProcess(TestCase this.testCase, bool this.allowRetries); |
|
Siggi Cherem (dart-lang)
2012/02/17 19:51:38
I think when using this.xxx our style is to omit t
Emily Fortuna
2012/02/17 21:03:03
Done.
| |
| 253 | 255 |
| 254 void exitHandler(int exitCode) { | 256 void exitHandler(int exitCode) { |
| 255 new TestOutput(testCase, exitCode, timedOut, stdout, | 257 new TestOutput(testCase, exitCode, timedOut, stdout, |
| 256 stderr, new Date.now().difference(startTime)); | 258 stderr, new Date.now().difference(startTime)); |
| 257 process.close(); | 259 process.close(); |
| 258 timeoutTimer.cancel(); | 260 timeoutTimer.cancel(); |
| 259 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) { | 261 if (testCase.output.unexpectedOutput && testCase.configuration['verbose']) { |
| 260 print(testCase.displayName); | 262 print(testCase.displayName); |
| 261 for (var line in testCase.output.stderr) print(line); | 263 for (var line in testCase.output.stderr) print(line); |
| 262 for (var line in testCase.output.stdout) print(line); | 264 for (var line in testCase.output.stdout) print(line); |
| 263 } | 265 } |
| 264 if (testCase.configuration['component'] == 'webdriver' && | 266 if (allowRetries && testCase.configuration['component'] == 'webdriver' && |
| 265 testCase.output.unexpectedOutput && testCase.numRetries > 0) { | 267 testCase.output.unexpectedOutput && testCase.numRetries > 0) { |
| 266 // Selenium tests can be flaky. Try rerunning. | 268 // Selenium tests can be flaky. Try rerunning. |
| 267 testCase.output.requestRetry = true; | 269 testCase.output.requestRetry = true; |
| 268 } | 270 } |
| 269 if (testCase.output.requestRetry) { | 271 if (testCase.output.requestRetry) { |
| 270 testCase.output.requestRetry = false; | 272 testCase.output.requestRetry = false; |
| 271 this.timedOut = false; | 273 this.timedOut = false; |
| 272 testCase.dynamic.numRetries--; | 274 testCase.dynamic.numRetries--; |
| 273 print("Potential flake. Re-running " + testCase.displayName); | 275 print("Potential flake. Re-running " + testCase.displayName); |
| 274 this.start(); | 276 this.start(); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 697 _progress.done(test_arg); | 699 _progress.done(test_arg); |
| 698 _tryRunTest(); | 700 _tryRunTest(); |
| 699 oldCallback(test_arg); | 701 oldCallback(test_arg); |
| 700 }; | 702 }; |
| 701 test.completedHandler = wrapper; | 703 test.completedHandler = wrapper; |
| 702 if (test.configuration['component'] == 'dartc' && | 704 if (test.configuration['component'] == 'dartc' && |
| 703 test.displayName != 'dartc/junit_tests') { | 705 test.displayName != 'dartc/junit_tests') { |
| 704 _ensureDartcBatchRunnersStarted(test.executablePath); | 706 _ensureDartcBatchRunnersStarted(test.executablePath); |
| 705 _getDartcBatchRunnerProcess().startTest(test); | 707 _getDartcBatchRunnerProcess().startTest(test); |
| 706 } else { | 708 } else { |
| 707 new RunningProcess(test).start(); | 709 // If we've failed more than four tests, a lot of tests are likely |
|
Siggi Cherem (dart-lang)
2012/02/17 19:51:38
When is numFailedTest incremented?
I thought that
Emily Fortuna
2012/02/17 21:03:03
The progress counter keeps track of the *actual* f
Emily Fortuna
2012/02/17 21:04:45
*Edit to last paragraph:
Yes, numFailedTests is n
| |
| 710 // broken. Don't continue to retry running tests if our tree is already | |
| 711 // red. At this point rerunning to test for flakes takes more time than | |
| 712 // it's worth. | |
| 713 new RunningProcess(test, _progress.numFailedTests < 5).start(); | |
|
Emily Fortuna
2012/02/17 19:34:24
Magic number... no me gusta :-(
Siggi Cherem (dart-lang)
2012/02/17 19:51:38
maybe we can do != 0?
| |
| 708 } | 714 } |
| 709 _numProcesses++; | 715 _numProcesses++; |
| 710 } | 716 } |
| 711 } | 717 } |
| 712 } | 718 } |
| OLD | NEW |