|
20 | 20 | seen_class = set() |
21 | 21 |
|
22 | 22 |
|
| 23 | +# Older Python versions have a bug with multiprocessing shared data |
| 24 | +# structures. https://github.com/emscripten-core/emscripten/issues/25103 |
| 25 | +# and https://github.com/python/cpython/issues/71936 |
| 26 | +def python_multiprocessing_structures_are_buggy(): |
| 27 | + v = sys.version_info |
| 28 | + return (v.major, v.minor, v.micro) <= (3, 12, 7) or (v.major, v.minor, v.micro) == (3, 13, 0) |
| 29 | + |
| 30 | + |
23 | 31 | def run_test(test, failfast_event, lock, progress_counter, num_tests): |
24 | 32 | # If failfast mode is in effect and any of the tests have failed, |
25 | 33 | # and then we should abort executing further tests immediately. |
@@ -84,9 +92,12 @@ def run(self, result): |
84 | 92 | print('Using %s parallel test processes' % use_cores, file=sys.stderr) |
85 | 93 | with multiprocessing.Manager() as manager: |
86 | 94 | pool = multiprocessing.Pool(use_cores) |
87 | | - failfast_event = manager.Event() if self.failfast else None |
88 | | - progress_counter = manager.Value('i', 0) |
89 | | - lock = manager.Lock() |
| 95 | + if python_multiprocessing_structures_are_buggy(): |
| 96 | + failfast_event = progress_counter = lock = None |
| 97 | + else: |
| 98 | + failfast_event = manager.Event() if self.failfast else None |
| 99 | + progress_counter = manager.Value('i', 0) |
| 100 | + lock = manager.Lock() |
90 | 101 | results = [pool.apply_async(run_test, (t, failfast_event, lock, progress_counter, len(tests))) for t in tests] |
91 | 102 | results = [r.get() for r in results] |
92 | 103 | results = [r for r in results if r is not None] |
@@ -182,38 +193,40 @@ def stopTest(self, test): |
182 | 193 | self.buffered_result.duration = self.test_duration |
183 | 194 |
|
184 | 195 | def compute_progress(self): |
| 196 | + if not self.lock: |
| 197 | + return '' |
185 | 198 | with self.lock: |
186 | | - val = f'[{int(self.progress_counter.value * 100 / self.num_tests)}%]' |
| 199 | + val = f'[{int(self.progress_counter.value * 100 / self.num_tests)}%] ' |
187 | 200 | self.progress_counter.value += 1 |
188 | 201 | return val |
189 | 202 |
|
190 | 203 | def addSuccess(self, test): |
191 | | - print(self.compute_progress(), test, '... ok (%.2fs)' % (self.calculateElapsed()), file=sys.stderr) |
| 204 | + print(f'{self.compute_progress()}{test} ... ok ({self.calculateElapsed():.2f}s)', file=sys.stderr) |
192 | 205 | self.buffered_result = BufferedTestSuccess(test) |
193 | 206 | self.test_result = 'success' |
194 | 207 |
|
195 | 208 | def addExpectedFailure(self, test, err): |
196 | | - print(self.compute_progress(), test, '... expected failure (%.2fs)' % (self.calculateElapsed()), file=sys.stderr) |
| 209 | + print(f'{self.compute_progress()}{test} ... expected failure ({self.calculateElapsed():.2f}s)', file=sys.stderr) |
197 | 210 | self.buffered_result = BufferedTestExpectedFailure(test, err) |
198 | 211 | self.test_result = 'expected failure' |
199 | 212 |
|
200 | 213 | def addUnexpectedSuccess(self, test): |
201 | | - print(self.compute_progress(), test, '... unexpected success (%.2fs)' % (self.calculateElapsed()), file=sys.stderr) |
| 214 | + print(f'{self.compute_progress()}{test} ... unexpected success ({self.calculateElapsed():.2f}s)', file=sys.stderr) |
202 | 215 | self.buffered_result = BufferedTestUnexpectedSuccess(test) |
203 | 216 | self.test_result = 'unexpected success' |
204 | 217 |
|
205 | 218 | def addSkip(self, test, reason): |
206 | | - print(self.compute_progress(), test, "... skipped '%s'" % reason, file=sys.stderr) |
| 219 | + print(f"{self.compute_progress()}{test} ... skipped '{reason}'", file=sys.stderr) |
207 | 220 | self.buffered_result = BufferedTestSkip(test, reason) |
208 | 221 | self.test_result = 'skipped' |
209 | 222 |
|
210 | 223 | def addFailure(self, test, err): |
211 | | - print(self.compute_progress(), test, '... FAIL', file=sys.stderr) |
| 224 | + print(f'{self.compute_progress()}{test} ... FAIL', file=sys.stderr) |
212 | 225 | self.buffered_result = BufferedTestFailure(test, err) |
213 | 226 | self.test_result = 'failed' |
214 | 227 |
|
215 | 228 | def addError(self, test, err): |
216 | | - print(self.compute_progress(), test, '... ERROR', file=sys.stderr) |
| 229 | + print(f'{self.compute_progress()}{test} ... ERROR', file=sys.stderr) |
217 | 230 | self.buffered_result = BufferedTestError(test, err) |
218 | 231 | self.test_result = 'errored' |
219 | 232 |
|
|
0 commit comments