11import sys
2- from pathlib import Path
3- from unittest .mock import MagicMock , patch
4-
5- import pytest
2+ from unittest .mock import patch
63
74
85class TestGetCudaTargetDir :
@@ -117,46 +114,57 @@ class TestSetupLinuxCuda:
117114 def test_skips_when_no_cuda_target (self , monkeypatch ):
118115 monkeypatch .delenv ("SNAP_USER_DATA" , raising = False )
119116 monkeypatch .delenv ("FLATPAK_ID" , raising = False )
117+ monkeypatch .delenv ("BUZZ_CUDA_SETUP_DONE" , raising = False )
120118
121119 with patch ("buzz.cuda_setup._get_cuda_target_dir" , return_value = None ):
122- from buzz .cuda_setup import _setup_linux_cuda
123- _setup_linux_cuda () # should not raise
120+ with patch ("buzz.cuda_setup._collect_site_packages_cuda_lib_dirs" , return_value = []):
121+ with patch ("multiprocessing.parent_process" , return_value = None ):
122+ from buzz .cuda_setup import _setup_linux_cuda
123+ _setup_linux_cuda () # should not raise
124124
125125 def test_skips_when_cuda_target_does_not_exist (self , monkeypatch , tmp_path ):
126+ monkeypatch .delenv ("BUZZ_CUDA_SETUP_DONE" , raising = False )
126127 nonexistent = tmp_path / "nonexistent"
127128 with patch ("buzz.cuda_setup._get_cuda_target_dir" , return_value = nonexistent ):
128- from buzz .cuda_setup import _setup_linux_cuda
129- _setup_linux_cuda () # should not raise
129+ with patch ("buzz.cuda_setup._collect_site_packages_cuda_lib_dirs" , return_value = []):
130+ with patch ("multiprocessing.parent_process" , return_value = None ):
131+ from buzz .cuda_setup import _setup_linux_cuda
132+ _setup_linux_cuda () # should not raise
130133
131134 def test_skips_when_no_torch_lib (self , monkeypatch , tmp_path ):
135+ monkeypatch .delenv ("BUZZ_CUDA_SETUP_DONE" , raising = False )
132136 cuda_target = tmp_path / "cuda_packages"
133137 cuda_target .mkdir ()
134138 with patch ("buzz.cuda_setup._get_cuda_target_dir" , return_value = cuda_target ):
135- from buzz .cuda_setup import _setup_linux_cuda
136- _setup_linux_cuda () # should not raise
139+ with patch ("buzz.cuda_setup._collect_site_packages_cuda_lib_dirs" , return_value = []):
140+ with patch ("multiprocessing.parent_process" , return_value = None ):
141+ from buzz .cuda_setup import _setup_linux_cuda
142+ _setup_linux_cuda () # should not raise
137143
138- def test_reexecs_when_sentinel_not_in_ld_path (self , monkeypatch , tmp_path ):
144+ def test_reexecs_when_sentinel_not_set (self , monkeypatch , tmp_path ):
139145 cuda_target = tmp_path / "cuda_packages"
140146 torch_lib = cuda_target / "torch" / "lib"
141147 torch_lib .mkdir (parents = True )
142148
149+ monkeypatch .delenv ("BUZZ_CUDA_SETUP_DONE" , raising = False )
143150 monkeypatch .delenv ("LD_LIBRARY_PATH" , raising = False )
144151
145152 with patch ("buzz.cuda_setup._get_cuda_target_dir" , return_value = cuda_target ):
146153 with patch ("buzz.cuda_setup._collect_cuda_lib_dirs" , return_value = [str (torch_lib )]):
147- with patch ("os.execv" , side_effect = OSError ("test" )) as mock_execv :
148- with patch ("buzz.cuda_setup._preload_linux_libraries_fallback" ) as mock_fallback :
149- from buzz .cuda_setup import _setup_linux_cuda
150- _setup_linux_cuda ()
154+ with patch ("multiprocessing.parent_process" , return_value = None ):
155+ with patch ("os.execv" , side_effect = OSError ("test" )):
156+ with patch ("buzz.cuda_setup._preload_linux_libraries_fallback" ) as mock_fallback :
157+ from buzz .cuda_setup import _setup_linux_cuda
158+ _setup_linux_cuda ()
151159
152- mock_fallback .assert_called_once ()
160+ mock_fallback .assert_called_once ()
153161
154- def test_no_reexec_when_sentinel_already_in_ld_path (self , monkeypatch , tmp_path ):
162+ def test_no_reexec_when_sentinel_already_set (self , monkeypatch , tmp_path ):
155163 cuda_target = tmp_path / "cuda_packages"
156164 torch_lib = cuda_target / "torch" / "lib"
157165 torch_lib .mkdir (parents = True )
158166
159- monkeypatch .setenv ("LD_LIBRARY_PATH " , str ( torch_lib ) )
167+ monkeypatch .setenv ("BUZZ_CUDA_SETUP_DONE " , "1" )
160168
161169 with patch ("buzz.cuda_setup._get_cuda_target_dir" , return_value = cuda_target ):
162170 with patch ("os.execv" ) as mock_execv :
@@ -165,6 +173,21 @@ def test_no_reexec_when_sentinel_already_in_ld_path(self, monkeypatch, tmp_path)
165173
166174 mock_execv .assert_not_called ()
167175
176+ def test_no_reexec_in_worker_subprocess (self , monkeypatch , tmp_path ):
177+ cuda_target = tmp_path / "cuda_packages"
178+ torch_lib = cuda_target / "torch" / "lib"
179+ torch_lib .mkdir (parents = True )
180+
181+ monkeypatch .delenv ("BUZZ_CUDA_SETUP_DONE" , raising = False )
182+
183+ with patch ("buzz.cuda_setup._get_cuda_target_dir" , return_value = cuda_target ):
184+ with patch ("multiprocessing.parent_process" , return_value = object ()):
185+ with patch ("os.execv" ) as mock_execv :
186+ from buzz .cuda_setup import _setup_linux_cuda
187+ _setup_linux_cuda ()
188+
189+ mock_execv .assert_not_called ()
190+
168191
169192class TestSetupWindowsDllDirectories :
170193 def test_calls_add_dll_directory (self , tmp_path ):
0 commit comments