Files
TheRock/rocm-libraries/projects/hipblaslt/utilities/geko/tests/test_cli_unit.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

440 lines
11 KiB
Python

# Copyright Advanced Micro Devices, Inc., or its affiliates.
# SPDX-License-Identifier: MIT
from __future__ import annotations
from pathlib import Path
import pytest
import yaml
from geko import cli
def test_parse_cli_args_defaults_with_bench_and_workload(tmp_path: Path) -> None:
workload = tmp_path / "wkld.yaml"
workload.write_text("[]\n")
args = cli.parse_cli_args(
[
"--bench",
"--workload-log",
str(workload),
"--devices",
"0,1",
]
)
assert args.bench is True
assert args.search is False
assert args.tune is False
assert args.workload == str(workload)
assert args.keep_thr == 0.0
assert sorted(args.devices) == [0, 1]
def test_parse_cli_args_search_default_keep_thr(tmp_path: Path) -> None:
workload = tmp_path / "wkld.yaml"
workload.write_text("[]\n")
args = cli.parse_cli_args(
[
"--search",
"--workload-log",
str(workload),
"--devices",
"0",
]
)
assert args.search is True
assert args.keep_thr == 0.1
def test_parse_cli_args_requires_arch_for_tune(tmp_path: Path) -> None:
workload = tmp_path / "wkld.yaml"
workload.write_text("[]\n")
with pytest.raises(SystemExit):
cli.parse_cli_args(
[
"--tune",
"--workload-log",
str(workload),
"--devices",
"0",
]
)
def test_parse_cli_args_inline_invalid_transpose(tmp_path: Path) -> None:
with pytest.raises(SystemExit):
cli.parse_cli_args(
[
"--bench",
"--inline",
"64",
"64",
"1",
"64",
"B",
"B",
"S",
"X",
"N",
"--devices",
"0",
]
)
def test_parse_cli_args_rejects_missing_workload_file() -> None:
with pytest.raises(SystemExit):
cli.parse_cli_args([
"--bench",
"--workload-log",
"missing.yaml",
"--devices",
"0",
])
def test_parse_cli_args_rejects_missing_list_file() -> None:
with pytest.raises(SystemExit):
cli.parse_cli_args([
"--search",
"--list",
"missing.yaml",
"--devices",
"0",
])
def test_parse_cli_args_inline_requires_integer_dimensions() -> None:
with pytest.raises(SystemExit):
cli.parse_cli_args([
"--bench",
"--inline",
"x",
"64",
"1",
"64",
"B",
"B",
"S",
"N",
"T",
"--devices",
"0",
])
def test_parse_cli_args_inline_normalizes_transpose_and_retry_flag() -> None:
args = cli.parse_cli_args([
"--bench",
"--inline",
"64",
"64",
"1",
"64",
" B ",
"B",
" S ",
" t ",
" n ",
"--devices",
"0",
"--no_retry",
])
assert args.inline == (64, 64, 1, 64, "B", "B", "S", "T", "N")
assert args.retry is False
def test_parse_cli_args_surfaces_device_parse_error(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
workload = tmp_path / "wkld.yaml"
workload.write_text("[]\n")
monkeypatch.setattr(cli, "parse_devices", lambda _s: (_ for _ in ()).throw(ValueError("bad devices")))
with pytest.raises(SystemExit):
cli.parse_cli_args([
"--bench",
"--workload-log",
str(workload),
"--devices",
"bad",
])
def test_dispatch_bench_workflow_calls_run_bench(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
workload = tmp_path / "wkld.yaml"
workload.write_text("[]\n")
called = {}
def _fake_resolve(*_args, **_kwargs):
return tmp_path
def _fake_run_bench(hip_path, log_path, run_root, **kwargs):
called["hip"] = hip_path
called["log"] = log_path
called["run_root"] = run_root
called["kwargs"] = kwargs
return 0
monkeypatch.setattr(cli, "resolve_hipblaslt_path", _fake_resolve)
monkeypatch.setattr(cli, "run_bench", _fake_run_bench)
args = cli.CliArgs(
tune=False,
bench=True,
search=False,
workload=str(workload),
gemm_config=None,
inline=None,
arch=None,
hipblaslt=str(tmp_path),
verbose=0,
devices=[0],
n_slots=1,
keep_thr=0.0,
backend="ductile",
workdir=str(tmp_path / "run"),
up_thr=1.03,
duration=0.04,
benchmark_duration=0.5,
retry=True,
bench_freq=False,
)
rc = cli.dispatch(args, anchor=str(tmp_path))
assert rc == 0
assert called["log"] == str(workload)
assert called["kwargs"]["devices"] == [0]
def test_dispatch_search_uses_generated_workload_from_list(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
cfg = tmp_path / "cfg.yaml"
cfg.write_text("dummy: true\n")
monkeypatch.setattr(cli, "resolve_hipblaslt_path", lambda **_kwargs: tmp_path)
monkeypatch.setattr(
cli,
"_rows_from_gemm_config_yaml",
lambda _path, _arch: [{"M": 16, "N": 16, "K": 16}],
)
captured = {}
def _fake_run_search(hip, workload, **kwargs):
captured["hip"] = hip
captured["workload"] = workload
captured["kwargs"] = kwargs
monkeypatch.setattr(cli, "run_search", _fake_run_search)
args = cli.CliArgs(
tune=False,
bench=False,
search=True,
workload=None,
gemm_config=str(cfg),
inline=None,
arch="gfx950",
hipblaslt=str(tmp_path),
verbose=0,
devices=[0],
n_slots=1,
keep_thr=0.1,
backend="ductile",
workdir=str(tmp_path / "run"),
up_thr=1.03,
duration=0.04,
benchmark_duration=0.5,
retry=True,
bench_freq=False,
)
rc = cli.dispatch(args, anchor=str(tmp_path))
assert rc == 0
generated = Path(captured["workload"])
assert generated.is_file()
with generated.open() as f:
data = yaml.safe_load(f)
assert data[0]["M"] == 16
def test_dispatch_tune_runs_configure_and_optimize(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
workload = tmp_path / "wkld.yaml"
workload.write_text("[]\n")
order: list[str] = []
monkeypatch.setattr(cli, "resolve_hipblaslt_path", lambda **_kwargs: tmp_path)
def _fake_cfg(*_args, **_kwargs):
order.append("configure")
def _fake_opt(*_args, **_kwargs):
order.append("optimize")
monkeypatch.setattr(cli, "run_configure", _fake_cfg)
monkeypatch.setattr(cli, "run_optimize", _fake_opt)
args = cli.CliArgs(
tune=True,
bench=False,
search=False,
workload=str(workload),
gemm_config=None,
inline=None,
arch="gfx950",
hipblaslt=str(tmp_path),
verbose=0,
devices=[0],
n_slots=1,
keep_thr=0.0,
backend="ductile",
workdir=str(tmp_path / "run"),
up_thr=1.03,
duration=0.04,
benchmark_duration=0.5,
retry=True,
bench_freq=False,
)
rc = cli.dispatch(args, anchor=str(tmp_path))
assert rc == 0
assert order == ["configure", "optimize"]
def test_main_maps_non_int_system_exit_to_one(monkeypatch: pytest.MonkeyPatch) -> None:
def _raise_non_int(_argv):
raise SystemExit("bad")
monkeypatch.setattr(cli, "parse_cli_args", _raise_non_int)
rc = cli.main(["--help"])
assert rc == 1
def test_dispatch_list_loader_error_returns_one(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
cfg = tmp_path / "cfg.yaml"
cfg.write_text("dummy: true\n")
monkeypatch.setattr(cli, "resolve_hipblaslt_path", lambda **_kwargs: tmp_path)
monkeypatch.setattr(cli, "_rows_from_gemm_config_yaml", lambda *_a, **_k: (_ for _ in ()).throw(ValueError("bad cfg")))
args = cli.CliArgs(
tune=False,
bench=False,
search=True,
workload=None,
gemm_config=str(cfg),
inline=None,
arch="gfx950",
hipblaslt=str(tmp_path),
verbose=0,
devices=[0],
n_slots=1,
keep_thr=0.1,
backend="ductile",
workdir=str(tmp_path / "run"),
up_thr=1.03,
duration=0.04,
benchmark_duration=0.5,
retry=True,
bench_freq=False,
)
assert cli.dispatch(args, anchor=str(tmp_path)) == 1
def test_dispatch_inline_value_error_returns_one(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
monkeypatch.setattr(cli, "resolve_hipblaslt_path", lambda **_kwargs: tmp_path)
monkeypatch.setattr(cli.GemmType, "from_tensile", lambda *_a, **_k: (_ for _ in ()).throw(ValueError("bad inline")))
args = cli.CliArgs(
tune=False,
bench=True,
search=False,
workload=None,
gemm_config=None,
inline=(64, 64, 1, 64, "B", "B", "S", "N", "N"),
arch=None,
hipblaslt=str(tmp_path),
verbose=0,
devices=[0],
n_slots=1,
keep_thr=0.0,
backend="ductile",
workdir=str(tmp_path / "run"),
up_thr=1.03,
duration=0.04,
benchmark_duration=0.5,
retry=True,
bench_freq=False,
)
assert cli.dispatch(args, anchor=str(tmp_path)) == 1
def test_dispatch_returns_one_for_missing_workload_source(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
monkeypatch.setattr(cli, "resolve_hipblaslt_path", lambda **_kwargs: tmp_path)
args = cli.CliArgs(
tune=False,
bench=True,
search=False,
workload=None,
gemm_config=None,
inline=None,
arch=None,
hipblaslt=str(tmp_path),
verbose=0,
devices=[0],
n_slots=1,
keep_thr=0.0,
backend="ductile",
workdir=str(tmp_path / "run"),
up_thr=1.03,
duration=0.04,
benchmark_duration=0.5,
retry=True,
bench_freq=False,
)
assert cli.dispatch(args, anchor=str(tmp_path)) == 1
def test_dispatch_raises_when_mode_is_missing(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
workload = tmp_path / "wkld.yaml"
workload.write_text("[]\n")
monkeypatch.setattr(cli, "resolve_hipblaslt_path", lambda **_kwargs: tmp_path)
args = cli.CliArgs(
tune=False,
bench=False,
search=False,
workload=str(workload),
gemm_config=None,
inline=None,
arch=None,
hipblaslt=str(tmp_path),
verbose=0,
devices=[0],
n_slots=1,
keep_thr=0.0,
backend="ductile",
workdir=str(tmp_path / "run"),
up_thr=1.03,
duration=0.04,
benchmark_duration=0.5,
retry=True,
bench_freq=False,
)
with pytest.raises(NotImplementedError, match="Expected --tune"):
cli.dispatch(args, anchor=str(tmp_path))