|
29 | 29 |
|
30 | 30 | from test.libregrtest.findtests import collect_cases |
31 | 31 | from test.libregrtest.filter import set_match_tests |
| 32 | +from test.libregrtest.parallel_case import ParallelTestCase |
32 | 33 | from test.libregrtest.run_workers import MultiprocessIterator |
33 | 34 | from test import support |
34 | 35 | from test.support import import_helper |
35 | 36 | from test.support import os_helper |
| 37 | +from test.support import threading_helper |
36 | 38 | from test.libregrtest import cmdline |
37 | 39 | from test.libregrtest import main |
38 | 40 | from test.libregrtest import setup |
@@ -2747,6 +2749,61 @@ def test_collect_cases_skiptest(self): |
2747 | 2749 | self.assertIn(testname, skipped) |
2748 | 2750 |
|
2749 | 2751 |
|
| 2752 | +@threading_helper.requires_working_threading() |
| 2753 | +class ParallelTestCaseTestCase(unittest.TestCase): |
| 2754 | + def test_cleanups_are_thread_local(self): |
| 2755 | + num_threads = 4 |
| 2756 | + barrier = threading.Barrier(num_threads) |
| 2757 | + cases = [] |
| 2758 | + lock = threading.Lock() |
| 2759 | + |
| 2760 | + class Test(unittest.TestCase): |
| 2761 | + def setUp(self): |
| 2762 | + self.cleanup_calls = [] |
| 2763 | + with lock: |
| 2764 | + cases.append(self) |
| 2765 | + thread = threading.get_ident() |
| 2766 | + self.addCleanup(self.cleanup, thread, 1) |
| 2767 | + self.addCleanup(self.cleanup, thread, 2) |
| 2768 | + |
| 2769 | + def cleanup(self, thread, value): |
| 2770 | + self.assertEqual(threading.get_ident(), thread) |
| 2771 | + self.cleanup_calls.append(value) |
| 2772 | + |
| 2773 | + def test(self): |
| 2774 | + # All workers must register their cleanups before any runs them. |
| 2775 | + barrier.wait(timeout=support.SHORT_TIMEOUT) |
| 2776 | + |
| 2777 | + case = Test('test') |
| 2778 | + result = unittest.TestResult() |
| 2779 | + ParallelTestCase(case, num_threads).run(result) |
| 2780 | + self.assertTrue(result.wasSuccessful(), (result.errors, result.failures)) |
| 2781 | + self.assertEqual(result.testsRun, 1) |
| 2782 | + self.assertEqual(len(cases), num_threads) |
| 2783 | + self.assertEqual(len({id(case._cleanups) for case in cases}), num_threads) |
| 2784 | + for worker_case in cases: |
| 2785 | + self.assertEqual(worker_case.cleanup_calls, [2, 1]) |
| 2786 | + self.assertEqual(worker_case._cleanups, []) |
| 2787 | + self.assertEqual(case._cleanups, []) |
| 2788 | + |
| 2789 | + def test_existing_cleanups_are_preserved(self): |
| 2790 | + num_threads = 4 |
| 2791 | + cleanup_calls = [] |
| 2792 | + case = unittest.FunctionTestCase(lambda: None) |
| 2793 | + case.addCleanup(cleanup_calls.append, 1) |
| 2794 | + case.addCleanup(cleanup_calls.append, 2) |
| 2795 | + cleanups = case._cleanups.copy() |
| 2796 | + |
| 2797 | + for _ in range(2): |
| 2798 | + cleanup_calls.clear() |
| 2799 | + result = unittest.TestResult() |
| 2800 | + ParallelTestCase(case, num_threads).run(result) |
| 2801 | + self.assertTrue(result.wasSuccessful(), |
| 2802 | + (result.errors, result.failures)) |
| 2803 | + self.assertCountEqual(cleanup_calls, [1, 2] * num_threads) |
| 2804 | + self.assertEqual(case._cleanups, cleanups) |
| 2805 | + |
| 2806 | + |
2750 | 2807 | class MultiprocessIteratorTestCase(unittest.TestCase): |
2751 | 2808 | def test_yields_all_groups_once(self): |
2752 | 2809 | groups = [("mod_a", ("mod_a.A.t1", "mod_a.A.t2")), |
|
0 commit comments