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
267 lines
9.1 KiB
Python
267 lines
9.1 KiB
Python
"""Tests to verify generated bundled binary test assets.
|
|
|
|
This test suite introspects the generated test assets to verify they contain
|
|
the expected bundled architectures and formats.
|
|
"""
|
|
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from rocm_kpack.binutils import BundledBinary, Toolchain
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def bundled_assets_dir(test_assets_dir: Path) -> Path:
|
|
"""Path to bundled binaries test assets."""
|
|
assets_dir = test_assets_dir / "bundled_binaries" / "linux" / "cov5"
|
|
if not assets_dir.exists():
|
|
pytest.skip(f"Bundled assets not found at {assets_dir}")
|
|
return assets_dir
|
|
|
|
|
|
def get_bundle_info(file_path: Path, toolchain: Toolchain) -> dict:
|
|
"""Extract bundle information from a binary.
|
|
|
|
For fully linked binaries (executables and shared libraries), we check for
|
|
.hip_fatbin sections and extract architecture information from strings.
|
|
|
|
Returns:
|
|
Dictionary with keys:
|
|
- targets: List of gfx architecture identifiers found
|
|
- has_device_code: Boolean indicating if device code is present
|
|
- has_hip_fatbin_section: Boolean indicating if .hip_fatbin section exists
|
|
"""
|
|
try:
|
|
# Check for .hip_fatbin section using readelf
|
|
has_hip_section = False
|
|
try:
|
|
result = subprocess.run(
|
|
["readelf", "-S", str(file_path)],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
has_hip_section = ".hip_fatbin" in result.stdout
|
|
except:
|
|
pass
|
|
|
|
# Extract architecture targets using strings
|
|
targets = []
|
|
try:
|
|
result = subprocess.run(
|
|
["strings", str(file_path)],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
|
|
# Look for gfx architecture identifiers
|
|
import re
|
|
|
|
gfx_pattern = re.compile(r"gfx\d+")
|
|
|
|
for line in result.stdout.splitlines():
|
|
matches = gfx_pattern.findall(line)
|
|
for match in matches:
|
|
if match not in targets:
|
|
targets.append(match)
|
|
except:
|
|
pass
|
|
|
|
return {
|
|
"targets": targets,
|
|
"has_device_code": has_hip_section and len(targets) > 0,
|
|
"has_hip_fatbin_section": has_hip_section,
|
|
}
|
|
|
|
except Exception as e:
|
|
pytest.fail(f"Failed to get bundle info for {file_path}: {e}")
|
|
|
|
|
|
def test_bundled_assets_exist(bundled_assets_dir: Path):
|
|
"""Verify all expected test assets exist."""
|
|
expected_executables = [
|
|
"test_kernel_single.exe",
|
|
"test_kernel_multi.exe",
|
|
"test_kernel_compressed.exe",
|
|
"test_kernel_wide.exe",
|
|
]
|
|
|
|
expected_libraries = [
|
|
"libtest_kernel_single.so",
|
|
"libtest_kernel_multi.so",
|
|
]
|
|
|
|
for exe in expected_executables:
|
|
assert (bundled_assets_dir / exe).exists(), f"Missing executable: {exe}"
|
|
|
|
for lib in expected_libraries:
|
|
assert (bundled_assets_dir / lib).exists(), f"Missing shared library: {lib}"
|
|
|
|
|
|
def test_single_arch_executable(bundled_assets_dir: Path, toolchain: Toolchain):
|
|
"""Verify test_kernel_single contains single architecture."""
|
|
exe_path = bundled_assets_dir / "test_kernel_single.exe"
|
|
info = get_bundle_info(exe_path, toolchain)
|
|
|
|
assert info["has_device_code"], "Single arch executable should have device code"
|
|
|
|
# Should have exactly one device code target (gfx1100)
|
|
gfx_targets = [t for t in info["targets"] if "gfx" in t]
|
|
assert len(gfx_targets) >= 1, "Should have at least one gfx target"
|
|
|
|
# Verify gfx1100 is present
|
|
assert any("gfx1100" in t for t in info["targets"]), "Should contain gfx1100 target"
|
|
|
|
|
|
def test_multi_arch_executable(bundled_assets_dir: Path, toolchain: Toolchain):
|
|
"""Verify test_kernel_multi contains multiple architectures."""
|
|
exe_path = bundled_assets_dir / "test_kernel_multi.exe"
|
|
info = get_bundle_info(exe_path, toolchain)
|
|
|
|
assert info["has_device_code"], "Multi arch executable should have device code"
|
|
|
|
# Should have multiple gfx targets (gfx1100 and gfx1101)
|
|
gfx_targets = [t for t in info["targets"] if "gfx" in t]
|
|
assert len(gfx_targets) >= 2, "Should have at least two gfx targets"
|
|
|
|
# Verify expected architectures
|
|
targets_str = " ".join(info["targets"])
|
|
assert "gfx1100" in targets_str, "Should contain gfx1100 target"
|
|
assert "gfx1101" in targets_str, "Should contain gfx1101 target"
|
|
|
|
|
|
def test_compressed_executable(bundled_assets_dir: Path, toolchain: Toolchain):
|
|
"""Verify test_kernel_compressed has expected architecture coverage.
|
|
|
|
Note: Actual compression may not be supported by the compiler, so we verify
|
|
architecture coverage rather than compression status.
|
|
"""
|
|
exe_path = bundled_assets_dir / "test_kernel_compressed.exe"
|
|
info = get_bundle_info(exe_path, toolchain)
|
|
|
|
assert info["has_device_code"], "Compressed executable should have device code"
|
|
|
|
# Should have gfx1100 and gfx1101
|
|
targets_str = " ".join(info["targets"])
|
|
assert "gfx1100" in targets_str, "Should contain gfx1100 target"
|
|
assert "gfx1101" in targets_str, "Should contain gfx1101 target"
|
|
|
|
# Note: We don't assert is_compressed because the compiler may not support it
|
|
# and falls back to uncompressed bundles
|
|
|
|
|
|
def test_wide_arch_executable(bundled_assets_dir: Path, toolchain: Toolchain):
|
|
"""Verify test_kernel_wide contains wide architecture coverage."""
|
|
exe_path = bundled_assets_dir / "test_kernel_wide.exe"
|
|
info = get_bundle_info(exe_path, toolchain)
|
|
|
|
assert info["has_device_code"], "Wide arch executable should have device code"
|
|
|
|
# Should have multiple CDNA and RDNA targets
|
|
targets_str = " ".join(info["targets"])
|
|
|
|
# Verify expected architectures (at least some of them should be present)
|
|
expected_archs = ["gfx900", "gfx906", "gfx908", "gfx90a", "gfx1100"]
|
|
found_archs = [arch for arch in expected_archs if arch in targets_str]
|
|
|
|
assert (
|
|
len(found_archs) >= 3
|
|
), f"Should contain at least 3 of {expected_archs}, found: {found_archs}"
|
|
|
|
|
|
def test_single_arch_library(bundled_assets_dir: Path, toolchain: Toolchain):
|
|
"""Verify libtest_kernel_single.so contains single architecture."""
|
|
lib_path = bundled_assets_dir / "libtest_kernel_single.so"
|
|
info = get_bundle_info(lib_path, toolchain)
|
|
|
|
assert info["has_device_code"], "Single arch library should have device code"
|
|
|
|
# Verify gfx1100 is present
|
|
assert any("gfx1100" in t for t in info["targets"]), "Should contain gfx1100 target"
|
|
|
|
|
|
def test_multi_arch_library(bundled_assets_dir: Path, toolchain: Toolchain):
|
|
"""Verify libtest_kernel_multi.so contains multiple architectures."""
|
|
lib_path = bundled_assets_dir / "libtest_kernel_multi.so"
|
|
info = get_bundle_info(lib_path, toolchain)
|
|
|
|
assert info["has_device_code"], "Multi arch library should have device code"
|
|
|
|
# Should have multiple gfx targets
|
|
gfx_targets = [t for t in info["targets"] if "gfx" in t]
|
|
assert len(gfx_targets) >= 2, "Should have at least two gfx targets"
|
|
|
|
# Verify expected architectures
|
|
targets_str = " ".join(info["targets"])
|
|
assert "gfx1100" in targets_str, "Should contain gfx1100 target"
|
|
assert "gfx1101" in targets_str, "Should contain gfx1101 target"
|
|
|
|
|
|
def test_executables_are_executable(bundled_assets_dir: Path):
|
|
"""Verify executables have executable permission bit set."""
|
|
import stat
|
|
|
|
executables = [
|
|
"test_kernel_single.exe",
|
|
"test_kernel_multi.exe",
|
|
"test_kernel_compressed.exe",
|
|
"test_kernel_wide.exe",
|
|
]
|
|
|
|
for exe_name in executables:
|
|
exe_path = bundled_assets_dir / exe_name
|
|
st = exe_path.stat()
|
|
assert st.st_mode & stat.S_IXUSR, f"{exe_name} should be executable"
|
|
|
|
|
|
def test_libraries_are_shared_objects(bundled_assets_dir: Path):
|
|
"""Verify shared libraries have correct ELF type."""
|
|
import subprocess
|
|
|
|
libraries = [
|
|
"libtest_kernel_single.so",
|
|
"libtest_kernel_multi.so",
|
|
]
|
|
|
|
for lib_name in libraries:
|
|
lib_path = bundled_assets_dir / lib_name
|
|
|
|
# Use 'file' command to check type
|
|
result = subprocess.run(
|
|
["file", str(lib_path)], capture_output=True, text=True, check=True
|
|
)
|
|
|
|
assert (
|
|
"shared object" in result.stdout.lower()
|
|
), f"{lib_name} should be a shared object, got: {result.stdout}"
|
|
|
|
|
|
def test_hip_fatbin_sections_present(bundled_assets_dir: Path):
|
|
"""Verify all bundled binaries have .hip_fatbin sections."""
|
|
all_binaries = [
|
|
"test_kernel_single.exe",
|
|
"test_kernel_multi.exe",
|
|
"test_kernel_compressed.exe",
|
|
"test_kernel_wide.exe",
|
|
"libtest_kernel_single.so",
|
|
"libtest_kernel_multi.so",
|
|
]
|
|
|
|
for binary_name in all_binaries:
|
|
binary_path = bundled_assets_dir / binary_name
|
|
|
|
# Check for .hip_fatbin section
|
|
result = subprocess.run(
|
|
["readelf", "-S", str(binary_path)],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
|
|
assert (
|
|
".hip_fatbin" in result.stdout
|
|
), f"{binary_name} should have .hip_fatbin section"
|