mirror of
https://github.com/NVIDIA/nvbench.git
synced 2026-07-13 02:27:22 +00:00
169 lines
5.6 KiB
Python
169 lines
5.6 KiB
Python
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION.
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
import importlib
|
|
import shutil
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.fixture
|
|
def tooling_deps(monkeypatch):
|
|
scripts_dir = Path(__file__).resolve().parents[1] / "scripts"
|
|
monkeypatch.syspath_prepend(str(scripts_dir))
|
|
sys.modules.pop("nvbench_tooling_deps", None)
|
|
return importlib.import_module("nvbench_tooling_deps")
|
|
|
|
|
|
def make_packaged_scripts_tree(tmp_path: Path) -> Path:
|
|
scripts_dir = Path(__file__).resolve().parents[1] / "scripts"
|
|
package_dir = tmp_path / "cuda" / "bench" / "scripts"
|
|
results_dir = tmp_path / "cuda" / "bench" / "results"
|
|
package_dir.mkdir(parents=True)
|
|
results_dir.mkdir()
|
|
for package in [
|
|
tmp_path / "cuda",
|
|
tmp_path / "cuda" / "bench",
|
|
package_dir,
|
|
results_dir,
|
|
]:
|
|
(package / "__init__.py").write_text("", encoding="utf-8")
|
|
for filename in [
|
|
"nvbench_compare.py",
|
|
"nvbench_histogram.py",
|
|
"nvbench_json_summary.py",
|
|
"nvbench_plot_bwutil.py",
|
|
"nvbench_tooling_deps.py",
|
|
"nvbench_walltime.py",
|
|
]:
|
|
shutil.copy(scripts_dir / filename, package_dir / filename)
|
|
shutil.copytree(
|
|
scripts_dir / "nvbench_json",
|
|
package_dir / "nvbench_json",
|
|
ignore=shutil.ignore_patterns("__pycache__"),
|
|
)
|
|
(results_dir / "__init__.py").write_text(
|
|
"class BenchmarkResult:\n"
|
|
" pass\n"
|
|
"class BenchmarkResultSummary:\n"
|
|
" pass\n"
|
|
"class SubBenchmarkResult:\n"
|
|
" pass\n"
|
|
"class SubBenchmarkState:\n"
|
|
" pass\n",
|
|
encoding="utf-8",
|
|
)
|
|
return package_dir
|
|
|
|
|
|
def clear_packaged_cuda_modules(monkeypatch):
|
|
for module_name in list(sys.modules):
|
|
if module_name == "cuda" or module_name.startswith("cuda."):
|
|
monkeypatch.delitem(sys.modules, module_name, raising=False)
|
|
|
|
|
|
def test_tooling_deps_imports_from_packaged_script_path(tmp_path, monkeypatch):
|
|
package_dir = make_packaged_scripts_tree(tmp_path)
|
|
|
|
monkeypatch.syspath_prepend(str(tmp_path))
|
|
clear_packaged_cuda_modules(monkeypatch)
|
|
|
|
module = importlib.import_module("cuda.bench.scripts.nvbench_tooling_deps")
|
|
|
|
assert Path(module.__file__) == package_dir / "nvbench_tooling_deps.py"
|
|
assert module.ToolingDependency("math", "math", "testing").extra == "tools"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("module_name", "expected_entry"),
|
|
[
|
|
("cuda.bench.scripts.nvbench_compare", "main"),
|
|
("cuda.bench.scripts.nvbench_histogram", "main"),
|
|
("cuda.bench.scripts.nvbench_json_summary", "main"),
|
|
("cuda.bench.scripts.nvbench_plot_bwutil", "main"),
|
|
("cuda.bench.scripts.nvbench_walltime", "main"),
|
|
],
|
|
)
|
|
def test_console_script_modules_import_from_packaged_paths(
|
|
tmp_path, monkeypatch, module_name, expected_entry
|
|
):
|
|
package_dir = make_packaged_scripts_tree(tmp_path)
|
|
leaf_module = module_name.rsplit(".", 1)[-1]
|
|
|
|
monkeypatch.syspath_prepend(str(tmp_path))
|
|
clear_packaged_cuda_modules(monkeypatch)
|
|
|
|
module = importlib.import_module(module_name)
|
|
|
|
assert Path(module.__file__) == package_dir / f"{leaf_module}.py"
|
|
assert callable(getattr(module, expected_entry))
|
|
|
|
|
|
def test_require_tooling_dependency_returns_loaded_module(tooling_deps):
|
|
module = tooling_deps.require_tooling_dependency(
|
|
tooling_deps.ToolingDependency("math", "math", "testing"),
|
|
tool_name="test-tool",
|
|
)
|
|
|
|
assert module.sqrt(9.0) == pytest.approx(3.0)
|
|
|
|
|
|
def test_require_tooling_dependency_reports_install_recipe(tooling_deps):
|
|
missing_name = "nvbench_missing_tooling_dependency_for_test"
|
|
with pytest.raises(tooling_deps.MissingToolingDependencyError) as exc_info:
|
|
tooling_deps.require_tooling_dependency(
|
|
tooling_deps.ToolingDependency(
|
|
missing_name, missing_name, "testing graceful failures"
|
|
),
|
|
tool_name="test-tool",
|
|
)
|
|
|
|
message = str(exc_info.value)
|
|
assert "test-tool requires" in message
|
|
assert "testing graceful failures" in message
|
|
assert "python -m pip install 'cuda-bench[tools]'" in message
|
|
assert missing_name in message
|
|
|
|
|
|
def test_require_tooling_dependency_reraises_broken_package_import_error(
|
|
tmp_path, monkeypatch, tooling_deps
|
|
):
|
|
package_dir = tmp_path / "nvbench_broken_tooling_dependency_for_test"
|
|
package_dir.mkdir()
|
|
(package_dir / "__init__.py").write_text(
|
|
"raise ImportError('broken package')\n", encoding="utf-8"
|
|
)
|
|
monkeypatch.syspath_prepend(str(tmp_path))
|
|
|
|
with pytest.raises(ImportError, match="broken package"):
|
|
tooling_deps.require_tooling_dependency(
|
|
tooling_deps.ToolingDependency(
|
|
package_dir.name, package_dir.name, "testing broken imports"
|
|
),
|
|
tool_name="test-tool",
|
|
)
|
|
|
|
|
|
def test_require_tooling_dependency_reraises_transitive_module_not_found(
|
|
tmp_path, monkeypatch, tooling_deps
|
|
):
|
|
package_dir = tmp_path / "nvbench_transitive_missing_dependency_for_test"
|
|
package_dir.mkdir()
|
|
(package_dir / "__init__.py").write_text(
|
|
"import nvbench_missing_transitive_dependency_for_test\n",
|
|
encoding="utf-8",
|
|
)
|
|
monkeypatch.syspath_prepend(str(tmp_path))
|
|
|
|
with pytest.raises(ModuleNotFoundError) as exc_info:
|
|
tooling_deps.require_tooling_dependency(
|
|
tooling_deps.ToolingDependency(
|
|
package_dir.name, package_dir.name, "testing transitive imports"
|
|
),
|
|
tool_name="test-tool",
|
|
)
|
|
|
|
assert exc_info.value.name == "nvbench_missing_transitive_dependency_for_test"
|