Files
TheRock/build_tools/tests/install_rocm_from_artifacts_test.py
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

421 lines
14 KiB
Python

#!/usr/bin/env python
# Copyright Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
"""Unit tests for install_rocm_from_artifacts.py."""
import argparse
import io
from datetime import datetime
from pathlib import Path
import os
import sys
import tempfile
import unittest
from unittest import mock
sys.path.insert(0, os.fspath(Path(__file__).parent.parent))
import install_rocm_from_artifacts as mod
class TestRetrieveArtifactsByRunId(unittest.TestCase):
"""Exercises how retrieve_artifacts_by_run_id() builds fetch_artifacts argv."""
def _run_main(self, extra_args):
"""Run main() with fetch_artifacts mocked, returning the captured argv."""
captured = {}
def fake_fetch(argv):
captured["argv"] = argv
with mock.patch.object(mod, "fetch_artifacts_main", fake_fetch):
mod.main(
[
"--run-id",
"12345",
"--artifact-group",
"gfx942",
"--amdgpu-targets",
"gfx942",
"--dry-run",
]
+ extra_args
)
return captured["argv"]
def test_core_arguments_forwarded(self):
argv = self._run_main([])
self.assertIn("--run-id", argv)
self.assertIn("12345", argv)
self.assertIn("--artifact-group", argv)
self.assertIn("gfx942", argv)
self.assertIn("--dry-run", argv)
def test_artifact_flag_adds_lib_pattern_without_test(self):
argv = self._run_main(["--blas"])
self.assertIn("blas_lib", argv)
self.assertNotIn("blas_test", argv)
def test_tests_flag_adds_test_pattern(self):
argv = self._run_main(["--blas", "--tests"])
self.assertIn("blas_lib", argv)
self.assertIn("blas_test", argv)
def test_unselected_artifact_is_excluded(self):
argv = self._run_main(["--blas"])
self.assertNotIn("mirage_run", argv)
def test_mirage_flag_includes_mirage_run(self):
argv = self._run_main(["--mirage"])
self.assertIn("mirage_run", argv)
def test_base_only_includes_rocjitsu_hotswap(self):
argv = self._run_main(["--base-only"])
self.assertIn("rocjitsu-hotswap_lib", argv)
def _tarball_name(platform: str, artifact_group: str, version: str) -> str:
"""Return a tarball name matching the platform under test."""
return f"therock-dist-{platform}-{artifact_group}-{version}.tar.gz"
def _s3_object(
platform: str,
artifact_group: str,
version: str,
*,
last_modified: datetime,
size: int = 0,
) -> dict:
"""Return a tarball object in the published multi-arch S3 layout."""
return {
"Key": mod._multiarch_tarball_s3_key(
_tarball_name(platform, artifact_group, version)
),
"LastModified": last_modified,
"Size": size,
}
class TestMultiarchTarballNamePattern(unittest.TestCase):
def test_extracts_named_filename_parts(self) -> None:
test_cases = [
("linux", "gfx94X-dcgpu", "7.15.0a20260722"),
("windows", "gfx110X-all", "7.15.0rc20260722"),
("linux", "gfx90a", "7.15.0.dev0+deadbeef"),
("windows", "multiarch", "7.15.0"),
]
for platform, artifact_group, version in test_cases:
with self.subTest(platform=platform, artifact_group=artifact_group):
match = mod.MULTIARCH_TARBALL_NAME_PATTERN.fullmatch(
_tarball_name(platform, artifact_group, version)
)
self.assertIsNotNone(match)
self.assertEqual(
match.groupdict(),
{
"platform": platform,
"artifact_group": artifact_group,
"version": version,
},
)
def test_rejects_unversioned_filename(self) -> None:
self.assertIsNone(
mod.MULTIARCH_TARBALL_NAME_PATTERN.fullmatch(
"therock-dist-linux-gfx94X-dcgpu-not-a-version.tar.gz"
)
)
class TestReleaseDiscovery(unittest.TestCase):
@staticmethod
def _paginator(*objects: dict) -> mock.Mock:
paginator = mock.Mock()
paginator.paginate.return_value = [{"Contents": objects}]
return paginator
def test_latest_release_dry_run_discovers_non_test_tarball(self) -> None:
platform = mod.PLATFORM
paginator = self._paginator(
_s3_object(
platform,
"gfx94X-dcgpu-tests",
"7.15.0a20260723",
last_modified=datetime(2026, 7, 23),
),
_s3_object(
platform,
"gfx94X-dcgpu",
"7.15.0a20260722",
last_modified=datetime(2026, 7, 22),
),
_s3_object(
platform,
"gfx110X-all",
"7.15.0a20260723",
last_modified=datetime(2026, 7, 23),
),
)
output = io.StringIO()
with (
mock.patch.object(
mod.s3_client, "get_paginator", return_value=paginator
) as get_paginator,
mock.patch("sys.stdout", output),
):
mod.main(
[
"--latest-release",
"--artifact-group",
"gfx94X-dcgpu",
"--dry-run",
]
)
asset_name = _tarball_name(platform, "gfx94X-dcgpu", "7.15.0a20260722")
self.assertIn("Found latest release: 7.15.0a20260722", output.getvalue())
self.assertIn(f"Would download: {asset_name}", output.getvalue())
get_paginator.assert_called_once_with("list_objects_v2")
paginator.paginate.assert_called_once_with(
Bucket=mod.NIGHTLY_TARBALL_BUCKET.name,
Prefix=mod._multiarch_tarball_s3_key(f"therock-dist-{platform}-"),
)
def test_discovery_supports_linux_and_windows_tarballs(self) -> None:
version = "7.15.0a20260722"
for platform in ("linux", "windows"):
asset_name = _tarball_name(platform, "gfx94X-dcgpu", version)
paginator = self._paginator(
_s3_object(
platform,
"gfx94X-dcgpu",
version,
last_modified=datetime(2026, 7, 22),
)
)
with mock.patch.object(
mod.s3_client, "get_paginator", return_value=paginator
):
result = mod.discover_latest_release("gfx94X-dcgpu", platform)
self.assertEqual(result, (version, asset_name))
def test_nightly_release_dry_run_reports_s3_location_and_asset(self) -> None:
version = "7.15.0a20260722"
asset_name = _tarball_name(mod.PLATFORM, "gfx94X-dcgpu", version)
expected_s3_uri = (
f"s3://{mod.NIGHTLY_TARBALL_BUCKET.name}/"
f"{mod._multiarch_tarball_s3_key(asset_name)}"
)
output = io.StringIO()
with mock.patch("sys.stdout", output):
mod.main(
[
"--release",
version,
"--artifact-group",
"gfx94X-dcgpu",
"--dry-run",
]
)
self.assertIn(f"Would download: {expected_s3_uri}", output.getvalue())
self.assertIn(f"asset {asset_name}", output.getvalue())
def test_multiarch_tarball_downloads_selected_s3_object(self) -> None:
asset_name = _tarball_name(mod.PLATFORM, "gfx94X-dcgpu", "7.15.0a20260722")
expected_key = mod._multiarch_tarball_s3_key(asset_name)
def write_tarball(_, __, file) -> None:
file.write(b"tarball contents")
with tempfile.TemporaryDirectory() as temp_dir:
output_dir = Path(temp_dir)
with (
mock.patch.object(
mod.s3_client, "download_fileobj", side_effect=write_tarball
) as download_fileobj,
mock.patch.object(mod, "_untar_files") as untar_files,
):
mod._retrieve_multiarch_tarball(
mod.NIGHTLY_TARBALL_BUCKET.name,
asset_name,
output_dir,
)
self.assertEqual(
(output_dir / asset_name).read_bytes(), b"tarball contents"
)
bucket, key, _ = download_fileobj.call_args.args
self.assertEqual(bucket, mod.NIGHTLY_TARBALL_BUCKET.name)
self.assertEqual(key, expected_key)
untar_files.assert_called_once_with(output_dir, output_dir / asset_name)
def test_dev_release_uses_dev_multiarch_tarball_bucket(self) -> None:
version = "7.15.0.dev0+deadbeef"
output_dir = Path("/tmp/therock-test")
asset_name = _tarball_name(mod.PLATFORM, "gfx94X-dcgpu", version)
args = argparse.Namespace(
artifact_group="gfx94X-dcgpu",
output_dir=output_dir,
release=version,
dry_run=False,
)
output = io.StringIO()
with (
mock.patch.object(mod, "_retrieve_multiarch_tarball") as retrieve_tarball,
mock.patch("sys.stdout", output),
):
mod.retrieve_artifacts_by_release(args)
retrieve_tarball.assert_called_once_with(
mod.DEV_TARBALL_BUCKET.name,
asset_name,
output_dir,
)
self.assertIn(
f"Retrieving dev multi-arch artifacts from "
f"s3://{mod.DEV_TARBALL_BUCKET.name}/{mod.MULTIARCH_TARBALL_S3_PREFIX}/",
output.getvalue(),
)
def test_extract_version_ignores_test_tarball(self) -> None:
self.assertIsNone(
mod.extract_version_from_asset_name(
_tarball_name(mod.PLATFORM, "gfx94X-dcgpu-tests", "7.15.0a20260723"),
"gfx94X-dcgpu-tests",
mod.PLATFORM,
)
)
def test_list_available_nightly_gpu_families_ignores_test_tarballs(
self,
) -> None:
for platform in ("linux", "windows"):
paginator = self._paginator(
_s3_object(
platform,
"gfx94X-dcgpu",
"7.15.0a20260723",
last_modified=datetime(2026, 7, 23),
),
_s3_object(
platform,
"gfx94X-dcgpu-tests",
"7.15.0a20260723",
last_modified=datetime(2026, 7, 23),
),
_s3_object(
platform,
"multiarch",
"7.15.0a20260723",
last_modified=datetime(2026, 7, 23),
),
)
with mock.patch.object(
mod.s3_client, "get_paginator", return_value=paginator
):
families = mod.list_available_nightly_gpu_families(platform)
self.assertEqual(families, {"gfx94X-dcgpu", "multiarch"})
def test_stable_release_uses_last_modified_for_ordering(self) -> None:
paginator = self._paginator(
_s3_object(
mod.PLATFORM,
"gfx94X-dcgpu",
"7.15.0",
last_modified=datetime(2026, 7, 22),
),
_s3_object(
mod.PLATFORM,
"gfx94X-dcgpu",
"7.16.0",
last_modified=datetime(2026, 7, 23),
),
)
with mock.patch.object(mod.s3_client, "get_paginator", return_value=paginator):
releases = mod._fetch_and_sort_nightly_releases("gfx94X-dcgpu")
self.assertEqual(
[release["version"] for release in releases],
["7.16.0", "7.15.0"],
)
self.assertEqual(releases[0]["last_modified"], datetime(2026, 7, 23))
def _make_run_id_args(**overrides) -> argparse.Namespace:
"""Return a minimal args namespace suitable for retrieve_artifacts_by_run_id."""
defaults = dict(
run_id="12345",
artifact_group="gfx110X-all",
output_dir=Path("/tmp/therock-test"),
# Non-empty amdgpu_targets skips the expand_families call.
amdgpu_targets="gfx1100",
dry_run=False,
run_github_repo=None,
base_only=False,
aqlprofile=False,
blas=False,
debug_tools=False,
fft=False,
hipdnn=False,
hipdnn_integration_tests=False,
hipdnn_samples=False,
hipfile=False,
miopen=False,
miopenprovider=False,
hipkernelprovider=False,
hiptensor=False,
hipblasltprovider=False,
prim=False,
rand=False,
rccl=False,
rocshmem=False,
mpi=False,
rocdecode=False,
rocjpeg=False,
rocjitsu=False,
mirage=False,
rocprofiler_compute=False,
rocprofiler_sdk=False,
rocprofiler_systems=False,
rocprofiler_systems_examples=False,
rocrtst=False,
rocalution=False,
rocwmma=False,
libhipcxx=False,
tests=False,
)
defaults.update(overrides)
return argparse.Namespace(**defaults)
def _captured_fetch_argv(args: argparse.Namespace) -> list[str]:
"""Run retrieve_artifacts_by_run_id and return the argv passed to fetch_artifacts_main."""
with mock.patch.object(mod, "fetch_artifacts_main") as mock_fetch:
mod.retrieve_artifacts_by_run_id(args)
(argv,), _ = mock_fetch.call_args
return argv
class TestDebugToolsAmdLlvmDev(unittest.TestCase):
"""Tests that --debug-tools pulls amd-llvm_dev (required for rocgdb testing)."""
def test_debug_tools_includes_amd_llvm_dev(self) -> None:
argv = _captured_fetch_argv(_make_run_id_args(debug_tools=True))
self.assertIn("amd-llvm_dev", argv)
if __name__ == "__main__":
unittest.main()