1515# specific language governing permissions and limitations
1616# under the License.
1717
18+ import multiprocessing
1819import os
19- from concurrent .futures import ThreadPoolExecutor
20+ from concurrent .futures import ProcessPoolExecutor , ThreadPoolExecutor
2021from typing import Dict , Optional
2122from unittest import mock
2223
2829VALID_ENV = {"PYICEBERG_MAX_WORKERS" : "5" }
2930INVALID_ENV = {"PYICEBERG_MAX_WORKERS" : "invalid" }
3031
32+ @pytest .fixture
33+ def fork_process ():
34+ original = multiprocessing .get_start_method ()
35+ allowed = multiprocessing .get_all_start_methods ()
36+
37+ assert "fork" in allowed
38+
39+ multiprocessing .set_start_method ("fork" , force = True )
40+
41+ yield
42+
43+ multiprocessing .set_start_method (original , force = True )
44+
45+
46+ @pytest .fixture
47+ def spawn_process ():
48+ original = multiprocessing .get_start_method ()
49+ allowed = multiprocessing .get_all_start_methods ()
50+
51+ assert "spawn" in allowed
52+
53+ multiprocessing .set_start_method ("spawn" , force = True )
54+
55+ yield
56+
57+ multiprocessing .set_start_method (original , force = True )
58+
59+
60+ def _use_executor_to_return (value ):
61+ executor = ExecutorFactory .get_or_create ()
62+ future = executor .submit (lambda : value )
63+ return future .result ()
64+
3165
3266def test_create_reused () -> None :
3367 first = ExecutorFactory .get_or_create ()
@@ -50,3 +84,40 @@ def test_max_workers() -> None:
5084def test_max_workers_invalid () -> None :
5185 with pytest .raises (ValueError ):
5286 ExecutorFactory .max_workers ()
87+
88+
89+ @pytest .mark .parametrize (
90+ "fixture" ,
91+ [
92+ pytest .param (
93+ "fork_process" ,
94+ marks = pytest .mark .skipif (
95+ "fork" not in multiprocessing .get_all_start_methods (), reason = "Fork start method is not available"
96+ ),
97+ ),
98+ pytest .param (
99+ "spawn_process" ,
100+ marks = pytest .mark .skipif (
101+ "spawn" not in multiprocessing .get_all_start_methods (), reason = "Spawn start method is not available"
102+ ),
103+ ),
104+ ],
105+ )
106+ def test_use_executor_in_different_process (fixture , request ):
107+ # Use the fixture
108+ request .getfixturevalue (fixture )
109+
110+ main_value = _use_executor_to_return (10 )
111+
112+ with ProcessPoolExecutor () as process_executor :
113+ future1 = process_executor .submit (_use_executor_to_return , 20 )
114+ with ProcessPoolExecutor () as process_executor :
115+ future2 = process_executor .submit (_use_executor_to_return , 30 )
116+
117+ assert main_value == 10
118+ assert future1 .result () == 20
119+ assert future2 .result () == 30
120+
121+
122+ if __name__ == "__main__" :
123+ pytest .main ([__file__ ])
0 commit comments