@@ -105,24 +105,37 @@ def test_multi_acquire_release_cross_module():
105
105
assert len (internals_ids ) == 2 if bits % 8 else 1
106
106
107
107
108
- def _python_to_cpp_to_python ():
109
- test_callback_py_obj ()
110
- test_callback_std_func ()
111
- test_callback_virtual_func ()
112
- test_callback_pure_virtual_func ()
113
- test_cross_module_gil_released ()
114
- test_cross_module_gil_acquired ()
115
- test_cross_module_gil_inner_custom_released ()
116
- test_cross_module_gil_inner_custom_acquired ()
117
- test_cross_module_gil_inner_pybind11_released ()
118
- test_cross_module_gil_inner_pybind11_acquired ()
119
- test_cross_module_gil_nested_custom_released ()
120
- test_cross_module_gil_nested_custom_acquired ()
121
- test_cross_module_gil_nested_pybind11_released ()
122
- test_cross_module_gil_nested_pybind11_acquired ()
123
- test_release_acquire ()
124
- test_nested_acquire ()
125
- test_multi_acquire_release_cross_module ()
108
+ # Intentionally putting human review in the loop here, to guard against accidents.
109
+ VARS_BEFORE_ALL_BASIC_TESTS = dict (vars ()) # Make a copy of the dict (critical).
110
+ ALL_BASIC_TESTS = (
111
+ test_callback_py_obj ,
112
+ test_callback_std_func ,
113
+ test_callback_virtual_func ,
114
+ test_callback_pure_virtual_func ,
115
+ test_cross_module_gil_released ,
116
+ test_cross_module_gil_acquired ,
117
+ test_cross_module_gil_inner_custom_released ,
118
+ test_cross_module_gil_inner_custom_acquired ,
119
+ test_cross_module_gil_inner_pybind11_released ,
120
+ test_cross_module_gil_inner_pybind11_acquired ,
121
+ test_cross_module_gil_nested_custom_released ,
122
+ test_cross_module_gil_nested_custom_acquired ,
123
+ test_cross_module_gil_nested_pybind11_released ,
124
+ test_cross_module_gil_nested_pybind11_acquired ,
125
+ test_release_acquire ,
126
+ test_nested_acquire ,
127
+ test_multi_acquire_release_cross_module ,
128
+ )
129
+
130
+
131
+ def test_all_basic_tests_completeness ():
132
+ num_found = 0
133
+ for key , value in VARS_BEFORE_ALL_BASIC_TESTS .items ():
134
+ if not key .startswith ("test_" ):
135
+ continue
136
+ assert value in ALL_BASIC_TESTS
137
+ num_found += 1
138
+ assert len (ALL_BASIC_TESTS ) == num_found
126
139
127
140
128
141
def _run_in_process (target , * args , ** kwargs ):
@@ -139,11 +152,10 @@ def _run_in_process(target, *args, **kwargs):
139
152
process .terminate ()
140
153
141
154
142
- def _python_to_cpp_to_python_from_threads (num_threads , parallel = False ):
143
- """Calls different C++ functions that come back to Python, from Python threads."""
155
+ def _run_in_threads (target , num_threads , parallel ):
144
156
threads = []
145
157
for _ in range (num_threads ):
146
- thread = threading .Thread (target = _python_to_cpp_to_python )
158
+ thread = threading .Thread (target = target )
147
159
thread .daemon = True
148
160
thread .start ()
149
161
if parallel :
@@ -155,44 +167,46 @@ def _python_to_cpp_to_python_from_threads(num_threads, parallel=False):
155
167
156
168
157
169
# TODO: FIXME, sometimes returns -11 (segfault) instead of 0 on macOS Python 3.9
158
- def test_python_to_cpp_to_python_from_thread ():
170
+ @pytest .mark .parametrize ("test_fn" , ALL_BASIC_TESTS )
171
+ def test_run_in_process_one_thread (test_fn ):
159
172
"""Makes sure there is no GIL deadlock when running in a thread.
160
173
161
174
It runs in a separate process to be able to stop and assert if it deadlocks.
162
175
"""
163
- assert _run_in_process (_python_to_cpp_to_python_from_threads , 1 ) == 0
176
+ assert _run_in_process (_run_in_threads , test_fn , num_threads = 1 , parallel = False ) == 0
164
177
165
178
166
179
# TODO: FIXME on macOS Python 3.9
167
- def test_python_to_cpp_to_python_from_thread_multiple_parallel ():
180
+ @pytest .mark .parametrize ("test_fn" , ALL_BASIC_TESTS )
181
+ def test_run_in_process_multiple_threads_parallel (test_fn ):
168
182
"""Makes sure there is no GIL deadlock when running in a thread multiple times in parallel.
169
183
170
184
It runs in a separate process to be able to stop and assert if it deadlocks.
171
185
"""
172
- exitcode = _run_in_process (_python_to_cpp_to_python_from_threads , 8 , parallel = True )
186
+ exitcode = _run_in_process (_run_in_threads , test_fn , num_threads = 8 , parallel = True )
173
187
if exitcode is None and env .PYPY and env .WIN : # Seems to be flaky.
174
188
pytest .skip ("Ignoring unexpected exitcode None (PYPY WIN)" )
175
189
assert exitcode == 0
176
190
177
191
178
192
# TODO: FIXME on macOS Python 3.9
179
- def test_python_to_cpp_to_python_from_thread_multiple_sequential ():
193
+ @pytest .mark .parametrize ("test_fn" , ALL_BASIC_TESTS )
194
+ def test_run_in_process_multiple_threads_sequential (test_fn ):
180
195
"""Makes sure there is no GIL deadlock when running in a thread multiple times sequentially.
181
196
182
197
It runs in a separate process to be able to stop and assert if it deadlocks.
183
198
"""
184
- assert (
185
- _run_in_process (_python_to_cpp_to_python_from_threads , 8 , parallel = False ) == 0
186
- )
199
+ assert _run_in_process (_run_in_threads , test_fn , num_threads = 8 , parallel = False ) == 0
187
200
188
201
189
202
# TODO: FIXME on macOS Python 3.9
190
- def test_python_to_cpp_to_python_from_process ():
203
+ @pytest .mark .parametrize ("test_fn" , ALL_BASIC_TESTS )
204
+ def test_run_in_process_direct (test_fn ):
191
205
"""Makes sure there is no GIL deadlock when using processes.
192
206
193
207
This test is for completion, but it was never an issue.
194
208
"""
195
- exitcode = _run_in_process (_python_to_cpp_to_python )
209
+ exitcode = _run_in_process (test_fn )
196
210
if exitcode is None and env .PYPY and env .WIN : # Seems to be flaky.
197
211
pytest .skip ("Ignoring unexpected exitcode None (PYPY WIN)" )
198
212
assert exitcode == 0
0 commit comments