hilaus-arm's picture
Sync from arm/Optimized-Runtimes via hub-sync
9422383 verified
Raw History Blame Contribute Delete
4.1 kB
"""Helpers for invoking public commands and locating external test fixtures."""
from __future__ import annotations
import atexit
import json
import os
import subprocess
import sys
import tempfile
from functools import cache
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
_WORKSPACE = tempfile.TemporaryDirectory(prefix="yolo26n-tests-")
atexit.register(_WORKSPACE.cleanup)
WORKSPACE = Path(_WORKSPACE.name)
def run_module(module: str, *arguments: object) -> subprocess.CompletedProcess[str]:
"""Run a Python command exactly as a user invokes it from the repository."""
return subprocess.run(
[sys.executable, "-m", module, *(str(argument) for argument in arguments)],
cwd=ROOT,
text=True,
capture_output=True,
check=False,
)
@cache
def checkpoint() -> Path:
"""Return the checkpoint supplied to the converter functional-test target."""
# The Make target supplies this external input without making checkpoint
# discovery part of the converter API.
configured = os.environ.get("YOLO26N_CHECKPOINT")
if configured:
return Path(configured).resolve()
raise RuntimeError("YOLO26N_CHECKPOINT is required for converter functional tests")
def exported_model(resolution: int = 320) -> Path:
"""Convert the shared checkpoint through the supported command."""
return _exported_model(resolution)
@cache
def _exported_model(resolution: int) -> Path:
output = WORKSPACE / f"export-{resolution}"
completed = run_module(
"converter.export_yolo26n",
"--checkpoint",
checkpoint(),
"--resolution",
resolution,
"--output-dir",
output,
)
if completed.returncode != 0:
raise RuntimeError(completed.stderr)
return output
def read_json(path: Path) -> dict[str, object]:
"""Read a JSON object emitted by a public command."""
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise AssertionError(f"expected JSON object: {path}")
return value
@cache
def configured_runtime() -> Path:
"""Return the native library supplied to the end-to-end tests."""
value = os.environ.get("YOLO26N_E2E_RUNTIME")
if not value:
raise RuntimeError("YOLO26N_E2E_RUNTIME is required for end-to-end tests")
runtime = Path(value).resolve()
if not runtime.is_file():
raise RuntimeError(f"YOLO26N_E2E_RUNTIME is not a file: {runtime}")
return runtime
def configured_model() -> Path:
"""Return one converted model for example behavior tests."""
return configured_models()[0]
@cache
def configured_models() -> tuple[Path, ...]:
"""Return the six converted models required by the end-to-end tests."""
value = os.environ.get("YOLO26N_E2E_MODELS")
if not value:
raise RuntimeError("YOLO26N_E2E_MODELS is required for end-to-end tests")
models_by_resolution: dict[int, Path] = {}
for item in value.split(os.pathsep):
model_directory = Path(item).resolve()
if not model_directory.is_dir():
raise RuntimeError(f"YOLO26N_E2E_MODELS contains a non-directory: {model_directory}")
manifest = read_json(model_directory / "manifest.json")
model = manifest.get("model")
if not isinstance(model, dict):
raise RuntimeError(f"converted model has no model record: {model_directory}")
shape = model.get("input_shape")
if not isinstance(shape, list) or len(shape) != 4 or type(shape[2]) is not int:
raise RuntimeError(f"converted model has no supported input shape: {model_directory}")
models_by_resolution[shape[2]] = model_directory
expected = {320, 480, 640, 800, 960, 1280}
if set(models_by_resolution) != expected:
raise RuntimeError(
"YOLO26N_E2E_MODELS must contain exactly one model for each supported "
f"resolution; received {sorted(models_by_resolution)}"
)
return tuple(models_by_resolution[resolution] for resolution in sorted(models_by_resolution))