Skip to content

Commit 97b0ae5

Browse files
committed
test(pathfinder): cover native search precedence
Signed-off-by: Ralf W. Grosse-Kunstleve <[email protected]>
1 parent 30e625b commit 97b0ae5

2 files changed

Lines changed: 113 additions & 1 deletion

File tree

‎cuda_pathfinder/tests/test_load_dl_windows.py‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: Apache-2.0
33

4+
import json
5+
import os
6+
import shutil
7+
import subprocess
48
import sys
9+
import uuid
10+
from pathlib import Path
511

612
import pytest
713

@@ -12,6 +18,51 @@
1218
from cuda.pathfinder._dynamic_libs.lib_descriptor import LIB_DESCRIPTORS
1319

1420

21+
@pytest.mark.agent_authored(model="unknown")
22+
def test_system_search_finds_dll_exposed_only_through_path(tmp_path, info_summary_append):
23+
dll_name = f"cuda_pathfinder_probe_{uuid.uuid4().hex}.dll"
24+
dll_dir = tmp_path / "path_only"
25+
dll_dir.mkdir()
26+
dll_path = dll_dir / dll_name
27+
shutil.copyfile(Path(os.environ["SYSTEMROOT"], "System32", "version.dll"), dll_path)
28+
probe = """\
29+
import json
30+
import sys
31+
from dataclasses import replace
32+
33+
from cuda.pathfinder._dynamic_libs import load_dl_windows
34+
from cuda.pathfinder._dynamic_libs.lib_descriptor import LIB_DESCRIPTORS
35+
36+
desc = replace(LIB_DESCRIPTORS["cublasLt"], windows_dlls=(sys.argv[1],))
37+
loaded = load_dl_windows.load_with_system_search(desc)
38+
print(json.dumps(None if loaded is None else {
39+
"abs_path": loaded.abs_path,
40+
"found_via": loaded.found_via,
41+
}))
42+
"""
43+
44+
def run_probe(env):
45+
result = subprocess.run( # noqa: S603 - trusted interpreter, test-owned script and DLL filename
46+
[sys.executable, "-c", probe, dll_name],
47+
check=True,
48+
capture_output=True,
49+
text=True,
50+
env=env,
51+
cwd=tmp_path,
52+
timeout=30,
53+
)
54+
return json.loads(result.stdout)
55+
56+
env = os.environ.copy()
57+
assert run_probe(env) is None
58+
env["PATH"] = os.pathsep.join((str(dll_dir), env.get("PATH", "")))
59+
loaded = run_probe(env)
60+
61+
assert loaded["found_via"] == "system-search"
62+
assert os.path.samefile(loaded["abs_path"], dll_path)
63+
info_summary_append(f"PATH-only DLL: abs_path={loaded['abs_path']!r}")
64+
65+
1566
@pytest.mark.agent_authored(model="gpt-5.6-sol")
1667
def test_already_loaded_library_checks_known_dlls_in_preference_order(mocker):
1768
desc = LIB_DESCRIPTORS["cublasLt"]

‎cuda_pathfinder/tests/test_load_nvidia_dynamic_lib_using_mocker.py‎

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
# SPDX-License-Identifier: Apache-2.0
33

4+
from pathlib import Path
5+
46
import pytest
57

68
from cuda.pathfinder._dynamic_libs import load_nvidia_dynamic_lib as load_mod
@@ -163,10 +165,69 @@ def _run_find_steps_disabled(ctx, steps):
163165

164166

165167
# ---------------------------------------------------------------------------
166-
# Search order tests (Conda-specific, since Conda is not covered by real CI)
168+
# Search order tests
167169
# ---------------------------------------------------------------------------
168170

169171

172+
@pytest.mark.parametrize("preferred_source", ("site-packages", "conda", "system-search"))
173+
@pytest.mark.agent_authored(model="unknown")
174+
def test_cuda_path_is_a_fallback_to_environment_and_native_search(tmp_path, mocker, monkeypatch, preferred_source):
175+
desc = load_mod.LIB_DESCRIPTORS["cublasLt"]
176+
platform = steps_mod.PLATFORM
177+
filename = desc.windows_dlls[0] if IS_WINDOWS else desc.linux_sonames[0]
178+
179+
def create_library(root, relative_dir):
180+
path = root / relative_dir / filename
181+
path.parent.mkdir(parents=True, exist_ok=True)
182+
path.touch()
183+
return path
184+
185+
cuda_root = tmp_path / "toolkit"
186+
create_library(cuda_root, platform.anchor_rel_dirs(desc)[0])
187+
mocker.patch(f"{_STEPS_MODULE}.get_cuda_path_or_home", return_value=str(cuda_root))
188+
189+
conda_root = tmp_path / "conda"
190+
conda_anchor = Path(platform.conda_anchor_point(str(conda_root)))
191+
conda_path = create_library(conda_anchor, platform.anchor_rel_dirs(desc)[0])
192+
if preferred_source == "system-search":
193+
monkeypatch.delenv("CONDA_PREFIX", raising=False)
194+
else:
195+
monkeypatch.setenv("CONDA_PREFIX", str(conda_root))
196+
197+
wheel_root = tmp_path / "wheels"
198+
wheel_path = create_library(wheel_root, platform.site_packages_rel_dirs(desc)[0])
199+
200+
def find_wheel_dirs(sub_dirs):
201+
directory = wheel_root.joinpath(*sub_dirs)
202+
return [str(directory)] if preferred_source == "site-packages" and directory.is_dir() else []
203+
204+
mocker.patch(
205+
"cuda.pathfinder._dynamic_libs.search_platform.find_sub_dirs_all_sitepackages",
206+
side_effect=find_wheel_dirs,
207+
)
208+
mocker.patch.object(load_mod.LOADER, "check_if_already_loaded_from_elsewhere", return_value=None)
209+
mocker.patch(f"{_MODULE}.load_dependencies")
210+
native_path = tmp_path / "native" / filename
211+
native_search = mocker.patch.object(
212+
load_mod.LOADER,
213+
"load_with_system_search",
214+
return_value=_make_loaded_dl(str(native_path), "system-search"),
215+
)
216+
mocker.patch.object(
217+
load_mod.LOADER,
218+
"load_with_abs_path",
219+
side_effect=lambda _desc, path, via: _make_loaded_dl(path, via),
220+
)
221+
222+
loaded = _load_lib_no_cache("cublasLt")
223+
224+
expected_path = {"site-packages": wheel_path, "conda": conda_path, "system-search": native_path}[preferred_source]
225+
assert loaded.found_via == preferred_source
226+
assert loaded.abs_path == str(expected_path)
227+
if preferred_source != "system-search":
228+
native_search.assert_not_called()
229+
230+
170231
def test_cupti_search_order_conda_before_cuda_home(tmp_path, mocker, monkeypatch):
171232
"""Test that conda is searched before CUDA_HOME (CTK).
172233

0 commit comments

Comments
 (0)