Files
TheRock/rocm-systems/shared/kpack/tests/test_database_handlers.py
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

959 lines
36 KiB
Python

"""Unit tests for database handlers."""
from pathlib import Path
import pytest
from rocm_kpack.database_handlers import (
RocBLASHandler,
HipBLASLtHandler,
HipSparseLtHandler,
AotritonHandler,
MIOpenHandler,
HipKernelProviderRockeHandler,
WHEEL_TYPE_PRESETS,
get_database_handlers,
list_available_handlers,
)
class TestRocBLASHandler:
"""Tests for RocBLASHandler detection logic."""
@pytest.fixture
def handler(self):
return RocBLASHandler()
@pytest.fixture
def prefix_root(self, tmp_path):
"""Create a temporary prefix root directory."""
root = tmp_path / "prefix"
root.mkdir()
return root
def test_name(self, handler):
"""Test handler name."""
assert handler.name() == "rocblas"
def test_detect_co_file(self, handler, prefix_root):
"""Test detection of .co file in rocblas/library."""
file_path = prefix_root / "lib/rocblas/library/TensileLibrary_gfx1100.co"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx1100"
def test_detect_hsaco_file(self, handler, prefix_root):
"""Test detection of .hsaco file in rocblas/library."""
file_path = prefix_root / "lib/rocblas/library/kernel_gfx1101.hsaco"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx1101"
def test_detect_dat_file(self, handler, prefix_root):
"""Test detection of .dat file in rocblas/library."""
file_path = prefix_root / "lib/rocblas/library/TensileLibrary_gfx1102.dat"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx1102"
def test_detect_various_architectures(self, handler, prefix_root):
"""Test detection of various gfx architecture formats."""
test_cases = [
("TensileLibrary_gfx90a.dat", "gfx90a"),
("TensileLibrary_gfx942.dat", "gfx942"),
("kernels_gfx1030.co", "gfx1030"),
("TensileLibrary_lazy_gfx90a-xnack+.hsaco", "gfx90a-xnack+"),
("Kernels.so-000-gfx942-xnack-.hsaco", "gfx942-xnack-"),
]
for filename, expected_arch in test_cases:
file_path = prefix_root / f"lib/rocblas/library/{filename}"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == expected_arch, f"Failed for {filename}"
def test_detect_xnack_plus(self, handler, prefix_root):
"""Test detection of xnack+ suffix in filename."""
file_path = (
prefix_root
/ "lib/rocblas/library/TensileLibrary_Type_HH_gfx90a-xnack+.hsaco"
)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx90a-xnack+"
def test_detect_xnack_minus(self, handler, prefix_root):
"""Test detection of xnack- suffix in filename."""
file_path = (
prefix_root / "lib/rocblas/library/Kernels.so-000-gfx942-xnack-.hsaco"
)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942-xnack-"
def test_detect_arch_subdir_co(self, handler, prefix_root):
"""Per-arch subdirectory layout: .co file under library/<arch>/."""
file_path = (
prefix_root / "lib/rocblas/library/gfx942/TensileLibrary_Type_HH_gfx942.co"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_arch_subdir_fallback_dat(self, handler, prefix_root):
"""Per-arch subdirectory layout: fallback .dat with no arch in filename."""
file_path = (
prefix_root
/ "lib/rocblas/library/gfx1100/TensileLibrary_Type_HH_fallback.dat"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx1100"
def test_detect_arch_subdir_manifest(self, handler, prefix_root):
"""Per-arch subdirectory layout: TensileManifest.txt under library/<arch>/."""
file_path = prefix_root / "lib/rocblas/library/gfx90a/TensileManifest.txt"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx90a"
def test_detect_arch_subdir_xnack(self, handler, prefix_root):
"""Per-arch subdirectory layout with xnack variant."""
file_path = prefix_root / "lib/rocblas/library/gfx942-xnack+/TensileLibrary.co"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942-xnack+"
def test_reject_wrong_directory(self, handler, prefix_root):
"""Test that files not in rocblas/library are rejected."""
file_path = prefix_root / "lib/other/library/TensileLibrary_gfx1100.dat"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_wrong_extension(self, handler, prefix_root):
"""Flat layout: unknown extensions without arch subdir are rejected."""
file_path = prefix_root / "lib/rocblas/library/TensileLibrary_gfx1100.txt"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_no_architecture(self, handler, prefix_root):
"""Test that files without architecture suffix are rejected."""
file_path = prefix_root / "lib/rocblas/library/TensileLibrary.dat"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_file_outside_prefix(self, handler, prefix_root):
"""Files outside prefix root are a caller bug — must raise."""
file_path = Path("/tmp/rocblas/library/TensileLibrary_gfx1100.dat")
with pytest.raises(ValueError, match="is not under prefix_root"):
handler.detect(file_path, prefix_root)
class TestHipBLASLtHandler:
"""Tests for HipBLASLtHandler detection logic."""
@pytest.fixture
def handler(self):
return HipBLASLtHandler()
@pytest.fixture
def prefix_root(self, tmp_path):
"""Create a temporary prefix root directory."""
root = tmp_path / "prefix"
root.mkdir()
return root
def test_name(self, handler):
"""Test handler name."""
assert handler.name() == "hipblaslt"
def test_detect_co_file(self, handler, prefix_root):
"""Test detection of .co file in hipblaslt/library."""
file_path = prefix_root / "lib/hipblaslt/library/TensileLibrary_gfx1100.co"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx1100"
def test_detect_hsaco_file(self, handler, prefix_root):
"""Test detection of .hsaco file in hipblaslt/library."""
file_path = prefix_root / "lib/hipblaslt/library/kernel_gfx1101.hsaco"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx1101"
def test_detect_dat_file(self, handler, prefix_root):
"""Test detection of .dat file in hipblaslt/library."""
file_path = prefix_root / "lib/hipblaslt/library/TensileLibrary_gfx1102.dat"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx1102"
def test_detect_various_architectures(self, handler, prefix_root):
"""Test detection of various gfx architecture formats."""
test_cases = [
("TensileLibrary_gfx90a.dat", "gfx90a"),
("TensileLibrary_gfx942.dat", "gfx942"),
("kernels_gfx1030.co", "gfx1030"),
("TensileLibrary_lazy_gfx90a-xnack+.hsaco", "gfx90a-xnack+"),
("Kernels.so-000-gfx942-xnack-.hsaco", "gfx942-xnack-"),
]
for filename, expected_arch in test_cases:
file_path = prefix_root / f"lib/hipblaslt/library/{filename}"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == expected_arch, f"Failed for {filename}"
def test_detect_xnack_plus(self, handler, prefix_root):
"""Test detection of xnack+ suffix in filename."""
file_path = (
prefix_root
/ "lib/hipblaslt/library/TensileLibrary_Type_HH_gfx90a-xnack+.hsaco"
)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx90a-xnack+"
def test_detect_xnack_minus(self, handler, prefix_root):
"""Test detection of xnack- suffix in filename."""
file_path = (
prefix_root / "lib/hipblaslt/library/Kernels.so-000-gfx942-xnack-.hsaco"
)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942-xnack-"
def test_detect_arch_subdir_fallback_dat(self, handler, prefix_root):
"""Per-arch subdirectory layout: fallback .dat with no arch in filename."""
file_path = (
prefix_root
/ "lib/hipblaslt/library/gfx942/TensileLibrary_Type_SS_fallback.dat"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_arch_subdir_manifest(self, handler, prefix_root):
"""Per-arch subdirectory layout: manifest .txt under library/<arch>/."""
file_path = prefix_root / "lib/hipblaslt/library/gfx1100/TensileManifest.txt"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx1100"
def test_reject_wrong_directory(self, handler, prefix_root):
"""Test that files not in hipblaslt/library are rejected."""
file_path = prefix_root / "lib/rocblas/library/TensileLibrary_gfx1100.dat"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_wrong_extension(self, handler, prefix_root):
"""Flat layout: unknown extensions without arch subdir are rejected."""
file_path = prefix_root / "lib/hipblaslt/library/TensileLibrary_gfx1100.json"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_no_architecture(self, handler, prefix_root):
"""Test that files without architecture suffix are rejected."""
file_path = prefix_root / "lib/hipblaslt/library/generic.dat"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_file_outside_prefix(self, handler, prefix_root):
"""Files outside prefix root are a caller bug — must raise."""
file_path = Path("/tmp/hipblaslt/library/TensileLibrary_gfx1100.dat")
with pytest.raises(ValueError, match="is not under prefix_root"):
handler.detect(file_path, prefix_root)
class TestHipSparseLtHandler:
"""Tests for HipSparseLtHandler detection logic."""
@pytest.fixture
def handler(self):
return HipSparseLtHandler()
@pytest.fixture
def prefix_root(self, tmp_path):
root = tmp_path / "prefix"
root.mkdir()
return root
def test_name(self, handler):
assert handler.name() == "hipsparselt"
def test_detect_co_file(self, handler, prefix_root):
file_path = prefix_root / "lib/hipsparselt/library/extop_gfx942.co"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_hsaco_file(self, handler, prefix_root):
file_path = prefix_root / "lib/hipsparselt/library/Kernels.so-000-gfx950.hsaco"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx950"
def test_detect_dat_file(self, handler, prefix_root):
file_path = (
prefix_root / "lib/hipsparselt/library/TensileLibrary_BB_BB_A_gfx942.dat"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_arch_subdir_dat(self, handler, prefix_root):
"""Per-arch subdirectory layout: .dat file under library/<arch>/."""
file_path = (
prefix_root
/ "lib/hipsparselt/library/gfx950/TensileLibrary_BB_BB_A_fallback.dat"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx950"
def test_reject_wrong_directory(self, handler, prefix_root):
file_path = prefix_root / "lib/rocblas/library/something_gfx942.co"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_wrong_extension(self, handler, prefix_root):
file_path = prefix_root / "lib/hipsparselt/library/something_gfx942.so"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
class TestAotritonHandler:
"""Tests for AotritonHandler detection logic."""
@pytest.fixture
def handler(self):
return AotritonHandler()
@pytest.fixture
def prefix_root(self, tmp_path):
"""Create a temporary prefix root directory."""
root = tmp_path / "prefix"
root.mkdir()
return root
def test_name(self, handler):
"""Test handler name."""
assert handler.name() == "aotriton"
def test_detect_aks2_file(self, handler, prefix_root):
"""Test detection of .aks2 file in aotriton.images layout."""
file_path = (
prefix_root / "lib/aotriton.images/amd-gfx942/flash/attn_fwd/kernel.aks2"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_family_arch(self, handler, prefix_root):
"""Test that family architecture names are mapped to bundle keys."""
file_path = (
prefix_root / "lib/aotriton.images/amd-gfx11xx/flash/attn_fwd/kernel.aks2"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx11"
def test_detect_various_architectures(self, handler, prefix_root):
"""Test detection of all real aotriton.images architecture directories.
Family/sub-family patterns are mapped to bundle keys:
gfx11xx → gfx11, gfx120x → gfx12_0.
gfx110x and gfx115x are already valid sub-family bundle keys.
Target names pass through unchanged.
"""
test_cases = [
("amd-gfx90a", "gfx90a"),
("amd-gfx942", "gfx942"),
("amd-gfx950", "gfx950"),
("amd-gfx11xx", "gfx11"),
("amd-gfx110x", "gfx110x"),
("amd-gfx115x", "gfx115x"),
("amd-gfx120x", "gfx12_0"),
]
for arch_dir, expected_bundle_key in test_cases:
file_path = (
prefix_root
/ f"lib/aotriton.images/{arch_dir}/flash/attn_fwd/kernel.aks2"
)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == expected_bundle_key, f"Failed for {arch_dir}"
def test_detect_signature_file(self, handler, prefix_root):
"""Test that __signature__ file under arch dir is detected."""
file_path = prefix_root / "lib/aotriton.images/amd-gfx942/__signature__"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_deeply_nested_file(self, handler, prefix_root):
"""Test detection of file nested deep under architecture directory."""
file_path = (
prefix_root
/ "lib/aotriton.images/amd-gfx950/flash/bwd_kernel_dk_dv/kernel.aks2"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx950"
def test_reject_no_amd_prefix(self, handler, prefix_root):
"""Test that directories without amd- prefix are rejected."""
file_path = prefix_root / "lib/aotriton.images/gfx942/flash/kernel.aks2"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_non_gfx_directory(self, handler, prefix_root):
"""Test that non-gfx directories under aotriton.images are rejected."""
file_path = prefix_root / "lib/aotriton.images/amd-common/flash/kernel.aks2"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_file_outside_prefix(self, handler, prefix_root):
"""Files outside prefix root are a caller bug — must raise."""
file_path = Path("/tmp/aotriton.images/amd-gfx942/kernel.aks2")
with pytest.raises(ValueError, match="is not under prefix_root"):
handler.detect(file_path, prefix_root)
def test_reject_wrong_parent_directory(self, handler, prefix_root):
"""Test that aotriton without .images suffix is rejected."""
file_path = prefix_root / "lib/aotriton/amd-gfx942/flash/kernel.aks2"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
class TestMIOpenHandler:
"""Tests for MIOpenHandler detection logic."""
@pytest.fixture
def handler(self):
return MIOpenHandler()
@pytest.fixture
def prefix_root(self, tmp_path):
"""Create a temporary prefix root directory."""
root = tmp_path / "prefix"
root.mkdir()
return root
def test_name(self, handler):
assert handler.name() == "miopen"
def test_detect_kdb(self, handler, prefix_root):
"""MIOpen .kdb files (SQLite compiled kernel databases)."""
file_path = prefix_root / "share/miopen/db/gfx942.kdb"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_kdb_various_arches(self, handler, prefix_root):
"""MIOpen .kdb files across multiple architectures."""
test_cases = [
("gfx90a.kdb", "gfx90a"),
("gfx908.kdb", "gfx908"),
("gfx1100.kdb", "gfx1100"),
("gfx950.kdb", "gfx950"),
]
for filename, expected_arch in test_cases:
file_path = prefix_root / f"share/miopen/db/{filename}"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == expected_arch, f"Failed for {filename}"
def test_detect_tn_model(self, handler, prefix_root):
file_path = prefix_root / "share/miopen/db/gfx908.tn.model"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx908"
def test_detect_ktn_model(self, handler, prefix_root):
file_path = (
prefix_root
/ "share/miopen/db/gfx942_ConvHipIgemmGroupFwdXdlops_decoder.ktn.model"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_metadata_model(self, handler, prefix_root):
file_path = prefix_root / "share/miopen/db/gfx90a_metadata.tn.model"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx90a"
def test_detect_3d_model(self, handler, prefix_root):
file_path = prefix_root / "share/miopen/db/gfx950_3d.tn.model"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx950"
def test_detect_db_txt(self, handler, prefix_root):
"""MIOpen .db.txt files with concatenated arch+CU count."""
file_path = prefix_root / "share/miopen/db/gfx90878.db.txt"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx908"
def test_detect_fdb_txt(self, handler, prefix_root):
"""MIOpen .HIP.fdb.txt files."""
file_path = prefix_root / "share/miopen/db/gfx942130.HIP.fdb.txt"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_opencl_fdb_txt(self, handler, prefix_root):
file_path = prefix_root / "share/miopen/db/gfx900_56.OpenCL.fdb.txt"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx900"
def test_detect_various_architectures(self, handler, prefix_root):
test_cases = [
("gfx908.tn.model", "gfx908"),
("gfx90a_ConvHipIgemmGroupXdlops_encoder.ktn.model", "gfx90a"),
("gfx942_3d_metadata.tn.model", "gfx942"),
("gfx950_ConvHipImplicitGemm3DGroupFwdXdlops_metadata.tn.model", "gfx950"),
("gfx90878.db.txt", "gfx908"),
("gfx90a68.db.txt", "gfx90a"),
("gfx942130.HIP.fdb.txt", "gfx942"),
("gfx1030_36.db.txt", "gfx1030"),
("gfx906_60.OpenCL.fdb.txt", "gfx906"),
("gfx90a6e.HIP.fdb.txt", "gfx90a"),
("gfx942e4.db.txt", "gfx942"),
]
for filename, expected_arch in test_cases:
file_path = prefix_root / f"share/miopen/db/{filename}"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == expected_arch, f"Failed for {filename}"
def test_reject_wrong_directory(self, handler, prefix_root):
file_path = prefix_root / "share/other/db/gfx908.tn.model"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_wrong_extension(self, handler, prefix_root):
file_path = prefix_root / "share/miopen/db/gfx908.json"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_no_architecture(self, handler, prefix_root):
file_path = prefix_root / "share/miopen/db/generic.tn.model"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_file_outside_prefix(self, handler, prefix_root):
"""Files outside prefix root are a caller bug — must raise."""
file_path = Path("/tmp/share/miopen/db/gfx908.tn.model")
with pytest.raises(ValueError, match="is not under prefix_root"):
handler.detect(file_path, prefix_root)
def test_detect_ck_so_gfx942(self, handler, prefix_root):
"""MIOpen CK per-arch shared library for gfx942."""
file_path = prefix_root / "lib/libMIOpenCKGroupedConv_gfx942.so"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_ck_so_gfx90a(self, handler, prefix_root):
"""MIOpen CK per-arch shared library for gfx90a."""
file_path = prefix_root / "lib/libMIOpenCKGroupedConv_gfx90a.so"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx90a"
def test_detect_ck_so_xnack(self, handler, prefix_root):
"""MIOpen CK per-arch shared library with xnack variant."""
file_path = prefix_root / "lib/libMIOpenCKGroupedConv_gfx942-xnack+.so"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942-xnack+"
def test_reject_libMIOpen_so(self, handler, prefix_root):
"""libMIOpen.so (the main library) should not match the CK pattern."""
file_path = prefix_root / "lib/libMIOpen.so"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_ck_so_no_arch(self, handler, prefix_root):
"""CK shared library without architecture suffix should be rejected."""
file_path = prefix_root / "lib/libMIOpenCKGroupedConv.so"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_detect_ck_dll_gfx942(self, handler, prefix_root):
"""Windows CK per-arch DLL (no lib prefix) should be detected."""
file_path = prefix_root / "lib/MIOpenCKGroupedConv_gfx942.dll"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_ck_dll_xnack(self, handler, prefix_root):
"""Windows CK per-arch DLL with xnack variant."""
file_path = prefix_root / "lib/MIOpenCKGroupedConv_gfx942-xnack+.dll"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942-xnack+"
def test_reject_MIOpen_dll(self, handler, prefix_root):
"""MIOpen.dll (the main library, no lib prefix) should not match the CK pattern."""
file_path = prefix_root / "lib/MIOpen.dll"
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
class TestHipKernelProviderRockeHandler:
"""Tests for HipKernelProviderRockeHandler detection logic."""
_ENGINE_DIR = "lib/hipdnn_plugins/engines/arch_content/rocke"
@pytest.fixture
def handler(self):
return HipKernelProviderRockeHandler()
@pytest.fixture
def prefix_root(self, tmp_path):
"""Create a temporary prefix root directory."""
root = tmp_path / "prefix"
root.mkdir()
return root
def test_name(self, handler):
assert handler.name() == "hipkernelprovider"
def test_detect_kpack(self, handler, prefix_root):
"""rocKE per-arch kpack archive routes to its arch."""
file_path = prefix_root / f"{self._ENGINE_DIR}/gfx942/rocke_client_gfx942.kpack"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_manifest_json(self, handler, prefix_root):
"""The bundle manifest beside the kpack routes to the same arch."""
file_path = prefix_root / f"{self._ENGINE_DIR}/gfx942/rocke_client_gfx942.json"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_deeply_nested_file(self, handler, prefix_root):
"""Any file nested below the arch dir routes to that arch."""
file_path = (
prefix_root / f"{self._ENGINE_DIR}/gfx942/sub/extra/blob.bin"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_detect_various_arches(self, handler, prefix_root):
test_cases = ["gfx90a", "gfx942", "gfx950", "gfx1151", "gfx1201"]
for arch in test_cases:
file_path = (
prefix_root / f"{self._ENGINE_DIR}/{arch}/rocke_client_{arch}.kpack"
)
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == arch, f"Failed for {arch}"
def test_detect_xnack(self, handler, prefix_root):
"""xnack arch variant is preserved as the bundle key."""
file_path = (
prefix_root
/ f"{self._ENGINE_DIR}/gfx942-xnack+/rocke_client_gfx942-xnack+.kpack"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942-xnack+"
def test_detect_second_engine(self, handler, prefix_root):
"""A different engine's per-arch content under arch_content/ routes with
no handler change (the anchor is the container, not the engine name)."""
file_path = (
prefix_root
/ "lib/hipdnn_plugins/engines/arch_content/aiter/gfx942/kernels.kpack"
)
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result == "gfx942"
def test_reject_no_arch_dir_under_arch_content(self, handler, prefix_root):
"""arch_content content with no arch directory stays generic (None)."""
file_path = prefix_root / f"{self._ENGINE_DIR}/config/settings.json"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_arch_dir_without_arch_content_parent(self, handler, prefix_root):
"""An <arch>/ path not under an arch_content/ container stays generic,
including the rocKE authoring SDK tree (bin/hip_kernel_provider/rocke/)."""
for rel in (
"lib/hipdnn_plugins/engines/other/gfx942/blob.bin",
"bin/hip_kernel_provider/rocke/instances/gfx942/wmma_gemm.py",
):
file_path = prefix_root / rel
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
assert handler.detect(file_path, prefix_root) is None, rel
def test_reject_arch_content_not_under_engines(self, handler, prefix_root):
"""An arch_content dir not directly under engines/ stays generic, so an
unrelated component's arch_content tree is never captured."""
for rel in (
"share/some_component/arch_content/gfx942/data.bin",
"lib/arch_content/gfx942/rocke_client_gfx942.kpack",
):
file_path = prefix_root / rel
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.touch()
assert handler.detect(file_path, prefix_root) is None, rel
def test_reject_non_arch_dir(self, handler, prefix_root):
"""A non-gfx directory name is not a bundle key."""
file_path = prefix_root / f"{self._ENGINE_DIR}/common/shared.json"
file_path.parent.mkdir(parents=True)
file_path.touch()
result = handler.detect(file_path, prefix_root)
assert result is None
def test_reject_arch_dir_itself(self, handler, prefix_root):
"""The arch directory with no file underneath does not match."""
dir_path = prefix_root / f"{self._ENGINE_DIR}/gfx942"
dir_path.mkdir(parents=True)
result = handler.detect(dir_path, prefix_root)
assert result is None
def test_reject_file_outside_prefix(self, handler, prefix_root):
"""Files outside prefix root are a caller bug -- must raise."""
file_path = Path(
"/tmp/lib/hip_kernel_provider/rocke/gfx942/rocke_client_gfx942.kpack"
)
with pytest.raises(ValueError, match="is not under prefix_root"):
handler.detect(file_path, prefix_root)
class TestDatabaseHandlerRegistry:
"""Tests for database handler registry functions."""
def test_list_available_handlers(self):
"""Test that list_available_handlers returns all registered handlers."""
handlers = list_available_handlers()
assert isinstance(handlers, list)
assert "rocblas" in handlers
assert "hipblaslt" in handlers
assert "hipsparselt" in handlers
assert "aotriton" in handlers
assert "miopen" in handlers
assert "hipkernelprovider" in handlers
assert len(handlers) == 6
def test_get_database_handlers_single(self):
"""Test getting a single handler by name."""
handlers = get_database_handlers(["rocblas"])
assert len(handlers) == 1
assert isinstance(handlers[0], RocBLASHandler)
def test_get_database_handlers_multiple(self):
"""Test getting multiple handlers by name."""
handlers = get_database_handlers(["rocblas", "hipblaslt"])
assert len(handlers) == 2
assert isinstance(handlers[0], RocBLASHandler)
assert isinstance(handlers[1], HipBLASLtHandler)
def test_get_database_handlers_all(self):
"""Test getting all handlers."""
handlers = get_database_handlers(
[
"rocblas",
"hipblaslt",
"hipsparselt",
"aotriton",
"miopen",
"hipkernelprovider",
]
)
assert len(handlers) == 6
assert isinstance(handlers[0], RocBLASHandler)
assert isinstance(handlers[1], HipBLASLtHandler)
assert isinstance(handlers[2], HipSparseLtHandler)
assert isinstance(handlers[3], AotritonHandler)
assert isinstance(handlers[4], MIOpenHandler)
assert isinstance(handlers[5], HipKernelProviderRockeHandler)
def test_wheel_type_preset(self):
"""Test that wheel type presets resolve to valid handlers."""
names = WHEEL_TYPE_PRESETS["torch-fat"]
handlers = get_database_handlers(names)
assert len(handlers) == 5
def test_get_database_handlers_unknown(self):
"""Test that unknown handler name raises ValueError."""
with pytest.raises(ValueError, match="Unknown database handler: unknown"):
get_database_handlers(["unknown"])
def test_get_database_handlers_mixed_valid_invalid(self):
"""Test that partially invalid handler list raises ValueError."""
with pytest.raises(ValueError, match="Unknown database handler: invalid"):
get_database_handlers(["rocblas", "invalid"])