Skip to content

Commit c2d9e99

Browse files
committed
Fix the Windows test failures from the str-to-Path probe change
_is_executable_candidate now takes a Path, but the tests that drive it through _patch_exec_probe still built their expected paths with os.path.join. A str never compares equal to a Path, so the fake probe reported every candidate as missing and each lookup returned None. Only Windows ran these in CI, which is why it looked platform-specific. Converts the remaining tests to Path and asserts in the probe helper that 'existing' holds Paths, so the same mismatch fails loudly next time.
1 parent 2d5b704 commit c2d9e99

1 file changed

Lines changed: 54 additions & 48 deletions

File tree

cuda_pathfinder/tests/test_find_nvidia_binaries.py

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ def _patch_exec_probe(mocker, existing=()):
4848
candidate is treated as missing. Returns the list that accumulates probed
4949
candidates so tests can assert the deterministic search order.
5050
"""
51+
# Paths, not strings: _is_executable_candidate takes a Path, so a str here
52+
# would never compare equal and would silently turn every lookup into None.
5153
existing = set(existing)
54+
assert all(isinstance(candidate, Path) for candidate in existing)
5255
checked: list[Path] = []
5356

5457
def fake_is_executable_candidate(path):
@@ -132,13 +135,13 @@ def test_find_binary_windows_extension_and_search_dirs(monkeypatch, mocker):
132135
@pytest.mark.parametrize(
133136
("launcher_exists", "expected_rel", "checked_rels"),
134137
(
135-
(True, os.path.join("bin", "compute-sanitizer.bat"), (os.path.join("bin", "compute-sanitizer.bat"),)),
138+
(True, Path("bin", "compute-sanitizer.bat"), (Path("bin", "compute-sanitizer.bat"),)),
136139
(
137140
False,
138-
os.path.join("compute-sanitizer", "compute-sanitizer.exe"),
141+
Path("compute-sanitizer", "compute-sanitizer.exe"),
139142
(
140-
os.path.join("bin", "compute-sanitizer.bat"),
141-
os.path.join("compute-sanitizer", "compute-sanitizer.exe"),
143+
Path("bin", "compute-sanitizer.bat"),
144+
Path("compute-sanitizer", "compute-sanitizer.exe"),
142145
),
143146
),
144147
),
@@ -148,36 +151,36 @@ def test_find_binary_windows_extension_and_search_dirs(monkeypatch, mocker):
148151
def test_find_compute_sanitizer_prefers_ctk_launcher_with_executable_fallback(
149152
monkeypatch, mocker, launcher_exists, expected_rel, checked_rels
150153
):
151-
cuda_home = os.path.join(os.sep, "cuda")
152-
launcher = os.path.join(cuda_home, "bin", "compute-sanitizer.bat")
153-
executable = os.path.join(cuda_home, "compute-sanitizer", "compute-sanitizer.exe")
154+
cuda_home = Path(os.sep, "cuda")
155+
launcher = cuda_home / "bin" / "compute-sanitizer.bat"
156+
executable = cuda_home / "compute-sanitizer" / "compute-sanitizer.exe"
154157

155158
mocker.patch.object(binary_finder_module, "IS_WINDOWS", new=True)
156159
mocker.patch.object(binary_finder_module.supported_nvidia_binaries, "SITE_PACKAGES_BINDIRS", {})
157160
monkeypatch.delenv("CONDA_PREFIX", raising=False)
158-
mocker.patch.object(binary_finder_module, "get_cuda_path_or_home", return_value=cuda_home)
161+
mocker.patch.object(binary_finder_module, "get_cuda_path_or_home", return_value=str(cuda_home))
159162
canary_mock = mocker.patch.object(binary_finder_module, "_resolve_ctk_root_via_canary")
160163
existing = [executable]
161164
if launcher_exists:
162165
existing.append(launcher)
163166
checked = _patch_exec_probe(mocker, existing=existing)
164167

165-
assert find_nvidia_binary_utility("compute-sanitizer") == os.path.abspath(os.path.join(cuda_home, expected_rel))
166-
assert checked == [os.path.join(cuda_home, rel) for rel in checked_rels]
168+
assert find_nvidia_binary_utility("compute-sanitizer") == os.path.abspath(cuda_home / expected_rel)
169+
assert checked == [cuda_home / rel for rel in checked_rels]
167170
canary_mock.assert_not_called()
168171

169172

170173
@pytest.mark.usefixtures("clear_find_binary_cache")
171174
@pytest.mark.agent_authored(model="gpt-5.6")
172175
def test_find_compute_sanitizer_uses_canary_ctk_root(monkeypatch, mocker):
173-
ctk_root = os.path.join(os.sep, "cuda")
174-
launcher = os.path.join(ctk_root, "bin", "compute-sanitizer.bat")
176+
ctk_root = Path(os.sep, "cuda")
177+
launcher = ctk_root / "bin" / "compute-sanitizer.bat"
175178

176179
mocker.patch.object(binary_finder_module, "IS_WINDOWS", new=True)
177180
mocker.patch.object(binary_finder_module.supported_nvidia_binaries, "SITE_PACKAGES_BINDIRS", {})
178181
monkeypatch.delenv("CONDA_PREFIX", raising=False)
179182
mocker.patch.object(binary_finder_module, "get_cuda_path_or_home", return_value=None)
180-
canary = mocker.patch.object(binary_finder_module, "_resolve_ctk_root_via_canary", return_value=ctk_root)
183+
canary = mocker.patch.object(binary_finder_module, "_resolve_ctk_root_via_canary", return_value=str(ctk_root))
181184
checked = _patch_exec_probe(mocker, existing=[launcher])
182185

183186
assert find_nvidia_binary_utility("compute-sanitizer") == os.path.abspath(launcher)
@@ -195,23 +198,23 @@ def test_find_compute_sanitizer_uses_canary_ctk_root(monkeypatch, mocker):
195198
@pytest.mark.usefixtures("clear_find_binary_cache")
196199
@pytest.mark.agent_authored(model="gpt-5.6")
197200
def test_find_binary_windows_nsight_conda_precedes_registry(monkeypatch, mocker, utility_name, candidate_names):
198-
site_dir = os.path.join(os.sep, "site-packages", utility_name, "bin")
199-
conda_prefix = os.path.join(os.sep, "conda")
200-
conda_bin = os.path.join(conda_prefix, "Library", "bin")
201-
expected = os.path.join(conda_bin, candidate_names[0])
201+
site_dir = Path(os.sep, "site-packages", utility_name, "bin")
202+
conda_prefix = Path(os.sep, "conda")
203+
conda_bin = conda_prefix / "Library" / "bin"
204+
expected = conda_bin / candidate_names[0]
202205

203206
mocker.patch.object(binary_finder_module, "IS_WINDOWS", new=True)
204-
mocker.patch.object(binary_finder_module, "find_sub_dirs_all_sitepackages", return_value=[site_dir])
205-
monkeypatch.setenv("CONDA_PREFIX", conda_prefix)
207+
mocker.patch.object(binary_finder_module, "find_sub_dirs_all_sitepackages", return_value=[str(site_dir)])
208+
monkeypatch.setenv("CONDA_PREFIX", str(conda_prefix))
206209
candidate_paths = mocker.patch.object(binary_finder_module.windows_nsight, f"{utility_name}_candidate_paths")
207210
get_cuda_path = mocker.patch.object(binary_finder_module, "get_cuda_path_or_home")
208211
canary = mocker.patch.object(binary_finder_module, "_resolve_ctk_root_via_canary")
209212
checked = _patch_exec_probe(mocker, existing=[expected])
210213

211214
assert find_nvidia_binary_utility(utility_name) == os.path.abspath(expected)
212215
assert checked == [
213-
*(os.path.join(site_dir, name) for name in candidate_names),
214-
os.path.join(conda_bin, candidate_names[0]),
216+
*(site_dir / name for name in candidate_names),
217+
conda_bin / candidate_names[0],
215218
]
216219
candidate_paths.assert_not_called()
217220
get_cuda_path.assert_not_called()
@@ -244,17 +247,18 @@ def test_find_binary_windows_nsight_conda_precedes_registry(monkeypatch, mocker,
244247
def test_find_binary_windows_nsight_composes_registry_and_native_target(
245248
monkeypatch, mocker, utility_name, product, machine_arch, target_rel, candidate_names
246249
):
247-
site_dir = os.path.join(os.sep, "site-packages", utility_name, "bin")
248-
conda_prefix = os.path.join(os.sep, "conda")
249-
conda_bin = os.path.join(conda_prefix, "Library", "bin")
250-
install_root = os.path.join(os.sep, "Program Files", utility_name)
251-
expected = os.path.join(install_root, target_rel)
250+
site_dir = Path(os.sep, "site-packages", utility_name, "bin")
251+
conda_prefix = Path(os.sep, "conda")
252+
conda_bin = conda_prefix / "Library" / "bin"
253+
install_root = Path(os.sep, "Program Files", utility_name)
254+
expected = install_root / target_rel
252255

253256
mocker.patch.object(binary_finder_module, "IS_WINDOWS", new=True)
254-
mocker.patch.object(binary_finder_module, "find_sub_dirs_all_sitepackages", return_value=[site_dir])
255-
monkeypatch.setenv("CONDA_PREFIX", conda_prefix)
257+
mocker.patch.object(binary_finder_module, "find_sub_dirs_all_sitepackages", return_value=[str(site_dir)])
258+
monkeypatch.setenv("CONDA_PREFIX", str(conda_prefix))
259+
# windows_nsight still works in str; it is not part of this migration step.
256260
registry_root = mocker.patch.object(
257-
binary_finder_module.windows_nsight, "_installed_product_root", return_value=install_root
261+
binary_finder_module.windows_nsight, "_installed_product_root", return_value=str(install_root)
258262
)
259263
machine_arch_mock = mocker.patch.object(
260264
binary_finder_module.windows_nsight, "windows_machine_arch", return_value=machine_arch
@@ -265,8 +269,8 @@ def test_find_binary_windows_nsight_composes_registry_and_native_target(
265269

266270
assert find_nvidia_binary_utility(utility_name) == os.path.abspath(expected)
267271
assert checked == [
268-
*(os.path.join(directory, name) for directory in (site_dir, conda_bin) for name in candidate_names),
269-
*((os.path.join(install_root, "ncu.bat"),) if utility_name == "ncu" else ()),
272+
*(directory / name for directory in (site_dir, conda_bin) for name in candidate_names),
273+
*((install_root / "ncu.bat",) if utility_name == "ncu" else ()),
270274
expected,
271275
]
272276
registry_root.assert_called_once_with(product)
@@ -278,14 +282,14 @@ def test_find_binary_windows_nsight_composes_registry_and_native_target(
278282
@pytest.mark.usefixtures("clear_find_binary_cache")
279283
@pytest.mark.agent_authored(model="gpt-5.6")
280284
def test_find_binary_windows_ncu_launcher_hit_does_not_resolve_machine_arch(monkeypatch, mocker):
281-
install_root = os.path.join(os.sep, "Program Files", "Nsight Compute")
282-
launcher = os.path.join(install_root, "ncu.bat")
285+
install_root = Path(os.sep, "Program Files", "Nsight Compute")
286+
launcher = install_root / "ncu.bat"
283287

284288
mocker.patch.object(binary_finder_module, "IS_WINDOWS", new=True)
285289
mocker.patch.object(binary_finder_module.supported_nvidia_binaries, "SITE_PACKAGES_BINDIRS", {})
286290
monkeypatch.delenv("CONDA_PREFIX", raising=False)
287291
registry_root = mocker.patch.object(
288-
binary_finder_module.windows_nsight, "_installed_product_root", return_value=install_root
292+
binary_finder_module.windows_nsight, "_installed_product_root", return_value=str(install_root)
289293
)
290294
machine_arch = mocker.patch.object(binary_finder_module.windows_nsight, "windows_machine_arch")
291295
get_cuda_path = mocker.patch.object(binary_finder_module, "get_cuda_path_or_home")
@@ -325,28 +329,30 @@ def test_find_binary_windows_nsight_registry_miss_is_terminal(monkeypatch, mocke
325329
@pytest.mark.usefixtures("clear_find_binary_cache")
326330
@pytest.mark.agent_authored(model="gpt-5.6")
327331
def test_find_windows_nsight_legacy_names_remain_literal_in_early_search(monkeypatch, mocker, utility_name):
328-
site_key = os.path.join("nvidia", utility_name, "bin")
329-
site_dir = os.path.join(os.sep, "site-packages", utility_name, "bin")
330-
conda_prefix = os.path.join(os.sep, "conda")
331-
conda_bin = os.path.join(conda_prefix, "Library", "bin")
332-
expected = os.path.join(conda_bin, f"{utility_name}.exe")
332+
site_key = ("nvidia", utility_name, "bin")
333+
site_dir = Path(os.sep, "site-packages", utility_name, "bin")
334+
conda_prefix = Path(os.sep, "conda")
335+
conda_bin = conda_prefix / "Library" / "bin"
336+
expected = conda_bin / f"{utility_name}.exe"
333337

334338
mocker.patch.object(binary_finder_module, "IS_WINDOWS", new=True)
335339
mocker.patch.object(
336340
binary_finder_module.supported_nvidia_binaries,
337341
"SITE_PACKAGES_BINDIRS",
338342
{utility_name: (site_key,)},
339343
)
340-
find_sub_dirs = mocker.patch.object(binary_finder_module, "find_sub_dirs_all_sitepackages", return_value=[site_dir])
341-
monkeypatch.setenv("CONDA_PREFIX", conda_prefix)
344+
find_sub_dirs = mocker.patch.object(
345+
binary_finder_module, "find_sub_dirs_all_sitepackages", return_value=[str(site_dir)]
346+
)
347+
monkeypatch.setenv("CONDA_PREFIX", str(conda_prefix))
342348
get_cuda_path = mocker.patch.object(binary_finder_module, "get_cuda_path_or_home")
343349
nsys_candidates = mocker.patch.object(binary_finder_module.windows_nsight, "nsys_candidate_paths")
344350
ncu_candidates = mocker.patch.object(binary_finder_module.windows_nsight, "ncu_candidate_paths")
345351
checked = _patch_exec_probe(mocker, existing=[expected])
346352

347353
assert find_nvidia_binary_utility(utility_name) == os.path.abspath(expected)
348-
assert checked == [os.path.join(site_dir, f"{utility_name}.exe"), expected]
349-
find_sub_dirs.assert_called_once_with(site_key.split(os.sep))
354+
assert checked == [site_dir / f"{utility_name}.exe", expected]
355+
find_sub_dirs.assert_called_once_with(site_key)
350356
get_cuda_path.assert_not_called()
351357
nsys_candidates.assert_not_called()
352358
ncu_candidates.assert_not_called()
@@ -356,22 +362,22 @@ def test_find_windows_nsight_legacy_names_remain_literal_in_early_search(monkeyp
356362
@pytest.mark.usefixtures("clear_find_binary_cache")
357363
@pytest.mark.agent_authored(model="gpt-5.6")
358364
def test_find_windows_nsight_legacy_names_remain_literal_in_ctk(monkeypatch, mocker, utility_name):
359-
cuda_home = os.path.join(os.sep, "cuda")
360-
expected = os.path.join(cuda_home, "bin", f"{utility_name}.exe")
365+
cuda_home = Path(os.sep, "cuda")
366+
expected = cuda_home / "bin" / f"{utility_name}.exe"
361367

362368
mocker.patch.object(binary_finder_module, "IS_WINDOWS", new=True)
363369
mocker.patch.object(binary_finder_module.supported_nvidia_binaries, "SITE_PACKAGES_BINDIRS", {})
364370
monkeypatch.delenv("CONDA_PREFIX", raising=False)
365-
mocker.patch.object(binary_finder_module, "get_cuda_path_or_home", return_value=cuda_home)
371+
mocker.patch.object(binary_finder_module, "get_cuda_path_or_home", return_value=str(cuda_home))
366372
nsys_candidates = mocker.patch.object(binary_finder_module.windows_nsight, "nsys_candidate_paths")
367373
ncu_candidates = mocker.patch.object(binary_finder_module.windows_nsight, "ncu_candidate_paths")
368374
canary = mocker.patch.object(binary_finder_module, "_resolve_ctk_root_via_canary")
369375
checked = _patch_exec_probe(mocker, existing=[expected])
370376

371377
assert find_nvidia_binary_utility(utility_name) == os.path.abspath(expected)
372378
assert checked == [
373-
os.path.join(cuda_home, "bin", "x64", f"{utility_name}.exe"),
374-
os.path.join(cuda_home, "bin", "x86_64", f"{utility_name}.exe"),
379+
cuda_home / "bin" / "x64" / f"{utility_name}.exe",
380+
cuda_home / "bin" / "x86_64" / f"{utility_name}.exe",
375381
expected,
376382
]
377383
nsys_candidates.assert_not_called()

0 commit comments

Comments
 (0)