Skip to content

Commit dad96a5

Browse files
cpcloudcursoragent
andcommitted
refactor(pathfinder): replace info_summary_append fixture with Python logging
Replace the custom `info_summary_append` pytest fixture and terminal summary with standard Python `logging`. Test diagnostic info now writes to a per- strictness log file (`test-info-summary-{strictness}.log`) via a `logging.FileHandler`, uploaded as a GHA run artifact. - Drop `custom_info` list, `pytest_terminal_summary`, and the `info_summary_append` fixture from conftest - Add session-scoped `_info_summary_handler` yield fixture (FileHandler lifecycle) and function-scoped `info_log` fixture (LoggerAdapter with test node name) - Update test call sites to use `info_log.info(...)` instead of `info_summary_append(...)` - Remove `tee` + `grep` verification from `ci/tools/run-tests` - Add `upload-artifact` step to both test-wheel workflows with `if-no-files-found: error` Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 62df918 commit dad96a5

7 files changed

Lines changed: 53 additions & 32 deletions

File tree

.github/workflows/test-wheel-linux.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,11 @@ jobs:
298298
CUDA_PATHFINDER_TEST_FIND_NVIDIA_HEADERS_STRICTNESS: all_must_work
299299
CUDA_PATHFINDER_TEST_FIND_NVIDIA_BITCODE_LIB_STRICTNESS: all_must_work
300300
run: run-tests pathfinder
301+
302+
- name: Upload cuda.pathfinder test info summary
303+
if: ${{ !cancelled() }}
304+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
305+
with:
306+
name: cuda-pathfinder-test-info-${{ inputs.host-platform }}-py${{ matrix.PY_VER }}-cuda${{ matrix.CUDA_VER }}-${{ matrix.LOCAL_CTK == '1' && 'local' || 'wheels' }}-${{ matrix.GPU }}
307+
path: cuda_pathfinder/test-info-summary-*.log
308+
if-no-files-found: error

.github/workflows/test-wheel-windows.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,11 @@ jobs:
275275
CUDA_PATHFINDER_TEST_FIND_NVIDIA_BITCODE_LIB_STRICTNESS: all_must_work
276276
shell: bash --noprofile --norc -xeuo pipefail {0}
277277
run: run-tests pathfinder
278+
279+
- name: Upload cuda.pathfinder test info summary
280+
if: ${{ !cancelled() }}
281+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
282+
with:
283+
name: cuda-pathfinder-test-info-${{ inputs.host-platform }}-py${{ matrix.PY_VER }}-cuda${{ matrix.CUDA_VER }}-${{ matrix.LOCAL_CTK == '1' && 'local' || 'wheels' }}-${{ matrix.GPU }}
284+
path: cuda_pathfinder/test-info-summary-*.log
285+
if-no-files-found: error

ci/tools/run-tests

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,7 @@ if [[ "${test_module}" == "pathfinder" ]]; then
3333
"LD:${CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS} " \
3434
"FH:${CUDA_PATHFINDER_TEST_FIND_NVIDIA_HEADERS_STRICTNESS} " \
3535
"BC:${CUDA_PATHFINDER_TEST_FIND_NVIDIA_BITCODE_LIB_STRICTNESS}"
36-
pytest -ra -s -v --durations=0 tests/ |& tee /tmp/pathfinder_test_log.txt
37-
# Report the number of "INFO test_" lines (including zero)
38-
# to support quick validations based on GHA log archives.
39-
line_count=$(awk '/^INFO test_/ {count++} END {print count+0}' /tmp/pathfinder_test_log.txt)
40-
echo "Number of \"INFO test_\" lines: $line_count"
36+
pytest -ra -s -v --durations=0 tests/
4137
popd
4238
elif [[ "${test_module}" == "bindings" ]]; then
4339
echo "Installing bindings wheel"

cuda_pathfinder/tests/conftest.py

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,42 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44

5+
import logging
6+
import os
7+
58
import pytest
69

10+
_LOGGER_NAME = "cuda_pathfinder.test_info"
711

8-
def pytest_configure(config):
9-
config.custom_info = []
1012

13+
def _info_summary_log_filename():
14+
strictness = os.environ.get("CUDA_PATHFINDER_TEST_LOAD_NVIDIA_DYNAMIC_LIB_STRICTNESS", "default")
15+
return f"test-info-summary-{strictness}.log"
1116

12-
def pytest_terminal_summary(terminalreporter, exitstatus, config):
13-
if not config.getoption("verbose"):
14-
return
15-
if hasattr(config.option, "iterations"): # pytest-freethreaded runs all tests at least twice
16-
return
17-
if getattr(config.option, "count", 1) > 1: # pytest-repeat
18-
return
1917

20-
if config.custom_info:
21-
terminalreporter.write_sep("=", "INFO summary")
22-
for msg in config.custom_info:
23-
terminalreporter.line(f"INFO {msg}")
18+
@pytest.fixture(scope="session")
19+
def _info_summary_handler(request):
20+
log_path = request.config.rootpath / _info_summary_log_filename()
21+
handler = logging.FileHandler(log_path, mode="w")
22+
handler.setFormatter(logging.Formatter("%(test_node)s: %(message)s"))
2423

24+
logger = logging.getLogger(_LOGGER_NAME)
25+
logger.addHandler(handler)
26+
logger.setLevel(logging.DEBUG)
27+
logger.propagate = False
2528

26-
@pytest.fixture
27-
def info_summary_append(request):
28-
def _append(message):
29-
request.config.custom_info.append(f"{request.node.name}: {message}")
29+
yield handler
30+
31+
logger.removeHandler(handler)
32+
handler.close()
3033

31-
return _append
34+
35+
@pytest.fixture
36+
def info_log(request, _info_summary_handler): # noqa: ARG001
37+
return logging.LoggerAdapter(
38+
logging.getLogger(_LOGGER_NAME),
39+
extra={"test_node": request.node.name},
40+
)
3241

3342

3443
def skip_if_missing_libnvcudla_so(libname: str, *, timeout: float) -> None:

cuda_pathfinder/tests/test_find_nvidia_binaries.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ def test_unknown_utility_name():
2121

2222

2323
@pytest.mark.parametrize("utility_name", SUPPORTED_BINARIES)
24-
def test_find_binary_utilities(info_summary_append, utility_name):
24+
def test_find_binary_utilities(info_log, utility_name):
2525
bin_path = find_nvidia_binary_utility(utility_name)
26-
info_summary_append(f"{bin_path=!r}")
26+
info_log.info(f"{bin_path=!r}")
2727

2828
assert bin_path is None or os.path.isfile(bin_path)
2929

cuda_pathfinder/tests/test_find_nvidia_headers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,12 @@ def _fake_cudart_canary_abs_path(ctk_root: Path) -> str:
113113

114114

115115
@pytest.mark.parametrize("libname", SUPPORTED_HEADERS_NON_CTK.keys())
116-
def test_locate_non_ctk_headers(info_summary_append, libname):
116+
def test_locate_non_ctk_headers(info_log, libname):
117117
hdr_dir = find_nvidia_header_directory(libname)
118118
located_hdr_dir = locate_nvidia_header_directory(libname)
119119
assert hdr_dir is None if not located_hdr_dir else hdr_dir == located_hdr_dir.abs_path
120120

121-
info_summary_append(f"{hdr_dir=!r}")
121+
info_log.info(f"{hdr_dir=!r}")
122122
if hdr_dir:
123123
_located_hdr_dir_asserts(located_hdr_dir)
124124
assert os.path.isdir(hdr_dir)
@@ -147,12 +147,12 @@ def test_supported_headers_site_packages_ctk_consistency():
147147

148148

149149
@pytest.mark.parametrize("libname", SUPPORTED_HEADERS_CTK.keys())
150-
def test_locate_ctk_headers(info_summary_append, libname):
150+
def test_locate_ctk_headers(info_log, libname):
151151
hdr_dir = find_nvidia_header_directory(libname)
152152
located_hdr_dir = locate_nvidia_header_directory(libname)
153153
assert hdr_dir is None if not located_hdr_dir else hdr_dir == located_hdr_dir.abs_path
154154

155-
info_summary_append(f"{hdr_dir=!r}")
155+
info_log.info(f"{hdr_dir=!r}")
156156
if hdr_dir:
157157
_located_hdr_dir_asserts(located_hdr_dir)
158158
assert os.path.isdir(hdr_dir)

cuda_pathfinder/tests/test_load_nvidia_dynamic_lib.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def _is_expected_load_nvidia_dynamic_lib_failure(libname):
111111
"libname",
112112
supported_nvidia_libs.SUPPORTED_WINDOWS_DLLS if IS_WINDOWS else supported_nvidia_libs.SUPPORTED_LINUX_SONAMES,
113113
)
114-
def test_load_nvidia_dynamic_lib(info_summary_append, libname):
114+
def test_load_nvidia_dynamic_lib(info_log, libname):
115115
# Use a fresh Python subprocess for each load to isolate global dynamic
116116
# loader state and keep the tests aligned with the canary probe model.
117117
timeout = 120 if IS_WINDOWS else 30
@@ -133,9 +133,9 @@ def raise_child_process_failed():
133133
skip_if_missing_libnvcudla_so(libname, timeout=timeout)
134134
if STRICTNESS == "all_must_work" and not _is_expected_load_nvidia_dynamic_lib_failure(libname):
135135
raise_child_process_failed()
136-
info_summary_append(f"Not found: {libname=!r}")
136+
info_log.info(f"Not found: {libname=!r}")
137137
else:
138138
abs_path = payload.abs_path
139139
assert abs_path is not None
140-
info_summary_append(f"abs_path={quote_for_shell(abs_path)}")
140+
info_log.info(f"abs_path={quote_for_shell(abs_path)}")
141141
assert os.path.isfile(abs_path) # double-check the abs_path

0 commit comments

Comments
 (0)