A picklable struct used to communicate test results across processes.
| 239 | |
| 240 | |
| 241 | class BufferedParallelTestResult(BufferingMixin, unittest.TestResult): |
| 242 | """A picklable struct used to communicate test results across processes.""" |
| 243 | |
| 244 | def __init__(self): |
| 245 | super().__init__() |
| 246 | self.test_duration = 0 |
| 247 | self.test_result = 'errored' |
| 248 | self.test_name = '' |
| 249 | self.test = None |
| 250 | |
| 251 | def test_short_name(self): |
| 252 | # Given a test name e.g. "test_atomic_cxx (test_core.core0.test_atomic_cxx)" |
| 253 | # returns a short form "test_atomic_cxx" of the test. |
| 254 | return self.test_name.split(' ', 1)[0] |
| 255 | |
| 256 | def addDuration(self, test, elapsed): |
| 257 | self.test_duration = elapsed |
| 258 | |
| 259 | def integrate_result(self, overall_results): |
| 260 | """Integrate buffered results from a worker process. |
| 261 | |
| 262 | This method gets called on the main thread once the buffered result is received. |
| 263 | It adds the buffered result to the overall result. |
| 264 | """ |
| 265 | |
| 266 | # Turns a <test, string> pair back into something that looks enough |
| 267 | # link a <test, exc_info> pair. The exc_info triple has the exception |
| 268 | # type as its first element. This is needed in particular in the |
| 269 | # XMLTestRunner. |
| 270 | def restore_exc_info(pair): |
| 271 | test, exn_string = pair |
| 272 | assert self.last_err_type, exn_string |
| 273 | return (test, (self.last_err_type, exn_string, None)) |
| 274 | |
| 275 | # Our fake exc_info triple keep the pre-serialized string in the |
| 276 | # second element of the triple so we override _exc_info_to_string |
| 277 | # _exc_info_to_string to simply return it. |
| 278 | overall_results._exc_info_to_string = lambda x, _y: x[1] |
| 279 | |
| 280 | overall_results.startTest(self.test) |
| 281 | if self.test_result == 'success': |
| 282 | overall_results.addSuccess(self.test) |
| 283 | elif self.test_result == 'failed': |
| 284 | overall_results.addFailure(*restore_exc_info(self.failures[0])) |
| 285 | elif self.test_result == 'errored': |
| 286 | overall_results.addError(*restore_exc_info(self.errors[0])) |
| 287 | elif self.test_result == 'skipped': |
| 288 | overall_results.addSkip(*self.skipped[0]) |
| 289 | elif self.test_result == 'unexpected success': |
| 290 | overall_results.addUnexpectedSuccess(self.unexpectedSuccesses[0]) |
| 291 | elif self.test_result == 'expected failure': |
| 292 | overall_results.addExpectedFailure(*restore_exc_info(self.expectedFailures[0])) |
| 293 | else: |
| 294 | assert False, f'unhandled test result {self.test_result}' |
| 295 | overall_results.stopTest(self.test) |
| 296 | overall_results.core_time += self.test_duration |
| 297 | |
| 298 | def log_test_run_for_visualization(self, flaky_tests): |