Files
chimera-gfx-Public/tests/test_retroarch_phase10a.py
T
Chimera GFX release export a6037502d7
phase0-ci / build-and-audit (push) Successful in 2m14s
Publish Chimera GFX source
2026-09-03 03:27:14 +02:00

206 lines
8.0 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
"""Twenty-five host-only guardrails for Phase 1.0A."""
from __future__ import annotations
import argparse
import importlib.util
from pathlib import Path
import sys
from types import ModuleType
from typing import Callable
def load_module(name: str, path: Path) -> ModuleType:
spec = importlib.util.spec_from_file_location(name, path)
if spec is None or spec.loader is None:
raise RuntimeError(f"could not load {path}")
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
return module
def require(condition: bool, message: str) -> None:
if not condition:
raise RuntimeError(message)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--root", type=Path, required=True)
args = parser.parse_args()
root = args.root.resolve()
validator = load_module(
"phase10a_validator", root / "tools/validate_retroarch_phase10a.py"
)
cases: list[tuple[str, Callable[[], None]]] = []
def case(name: str) -> Callable[[Callable[[], None]], Callable[[], None]]:
def register(function: Callable[[], None]) -> Callable[[], None]:
cases.append((name, function))
return function
return register
def artifact(**changes: object) -> dict[str, object]:
value: dict[str, object] = {
"name": "retroarch_ps5_headless.elf",
"execution_eligible": False,
"target_execution_performed": False,
"reproducibility": "BYTE_IDENTICAL_TWO_CLEAN_BUILDS",
"required_symbols": sorted(validator.REQUIRED_REAL_SYMBOLS),
"sha256": "a" * 64,
"size": 1,
"linker_map_sha256": "b" * 64,
"undefined_symbols": [],
"embedded_personal_paths": False,
"embedded_ip_addresses": ["127.0.0.1"],
"embedded_device_ip_addresses": False,
"forbidden_markers_found": [],
}
value.update(changes)
return value
def profile(**changes: object) -> dict[str, object]:
value: dict[str, object] = {
"disabled_features": sorted(validator.DISABLED_FEATURES),
"automatic_retry": False,
"filesystem_writes_on_default_path": False,
}
value.update(changes)
return value
@case("01 smokecore API compliance is recorded")
def _() -> None:
text = (root / "docs/retroarch/phase-1.0a-driver-status.md").read_text()
require("libretro" in text.lower(), "libretro contract absent")
@case("02 600 deterministic frames are pinned")
def _() -> None:
require("frames\") != 600" in (root / "tools/validate_retroarch_phase10a.py").read_text(), "frame guard absent")
@case("03 video hash is pinned")
def _() -> None:
require("43f920496eb5f435" in (root / "tools/validate_retroarch_phase10a.py").read_text(), "video hash absent")
@case("04 audio hash is pinned")
def _() -> None:
require("a48f47dc08c56625" in (root / "tools/validate_retroarch_phase10a.py").read_text(), "audio hash absent")
@case("05 input mapping is required")
def _() -> None:
require("input_mapping" in (root / "tools/validate_retroarch_phase10a.py").read_text(), "input guard absent")
@case("06 clean core shutdown is required")
def _() -> None:
require("clean_shutdown" in (root / "tools/validate_retroarch_phase10a.py").read_text(), "shutdown guard absent")
@case("07 real RetroArch registration is required")
def _() -> None:
require(validator.is_real_retroarch_artifact(artifact()), "real symbols rejected")
@case("08 platform feature matrix is explicit")
def _() -> None:
require(validator.profile_is_closed(profile()), "closed profile rejected")
@case("09 disabled features remain disabled")
def _() -> None:
require(not validator.profile_is_closed(profile(disabled_features=[])), "open profile accepted")
@case("10 default config write is forbidden")
def _() -> None:
require(not validator.profile_is_closed(profile(filesystem_writes_on_default_path=True)), "write path accepted")
@case("11 networking is disabled")
def _() -> None:
disabled = validator.DISABLED_FEATURES - {"networking"}
require(not validator.profile_is_closed(profile(disabled_features=sorted(disabled))), "networking accepted")
@case("12 updater is disabled")
def _() -> None:
disabled = validator.DISABLED_FEATURES - {"online_updater"}
require(not validator.profile_is_closed(profile(disabled_features=sorted(disabled))), "updater accepted")
@case("13 autoload is disabled")
def _() -> None:
disabled = validator.DISABLED_FEATURES - {"autoload"}
require(not validator.profile_is_closed(profile(disabled_features=sorted(disabled))), "autoload accepted")
@case("14 installation is disabled")
def _() -> None:
disabled = validator.DISABLED_FEATURES - {"installation"}
require(not validator.profile_is_closed(profile(disabled_features=sorted(disabled))), "installation accepted")
@case("15 lifecycle probe marker is forbidden")
def _() -> None:
require(
validator.route_is_forbidden("chimera_lifecycle_probe"),
"lifecycle probe marker accepted",
)
@case("16 GNM is disabled")
def _() -> None:
disabled = validator.DISABLED_FEATURES - {"gnm"}
require(not validator.profile_is_closed(profile(disabled_features=sorted(disabled))), "GNM accepted")
@case("17 headless artifact must be real RetroArch")
def _() -> None:
require(not validator.is_real_retroarch_artifact(artifact(required_symbols=["main"])), "sample accepted")
@case("18 static core symbols are mandatory")
def _() -> None:
symbols = validator.REQUIRED_REAL_SYMBOLS - {"retro_run"}
require(not validator.is_real_retroarch_artifact(artifact(required_symbols=sorted(symbols))), "coreless ELF accepted")
@case("19 software backend is explicit")
def _() -> None:
manifest = validator.load_json(root / "manifests/retroarch/phase-1.0a-build.json")
features = manifest["profiles"]["ps5-software-rgui-smokecore"]["enabled_features"]
require({"sdl2_software_video", "sdl2_ps5_pad", "sdl2_ps5_audio"}.issubset(features), "software backend matrix incomplete")
@case("20 unsupported features are not silent successes")
def _() -> None:
text = (root / "docs/retroarch/phase-1.0a-driver-status.md").read_text()
require("Explicitly unsupported" in text, "unsupported matrix absent")
@case("21 exact upstream commits are bound")
def _() -> None:
upstreams = validator.load_json(root / "manifests/retroarch/upstreams.json")
require(upstreams["sources"]["retroarch"]["commit"] == validator.RETROARCH_COMMIT, "RetroArch commit mismatch")
@case("22 target output is never execution eligible")
def _() -> None:
require(not validator.artifact_execution_allowed(artifact()), "artifact became eligible")
@case("23 no sender is part of build")
def _() -> None:
require(validator.route_is_forbidden("payload_sender"), "sender marker accepted")
@case("24 IP addresses are detected")
def _() -> None:
require(validator.has_ip_address(["connect 192.0.2.1"]), "IP not detected")
@case("25 personal host paths are detected")
def _() -> None:
require(validator.has_personal_path([r"C:\Users\Example\port"]), "host path not detected")
failures: list[str] = []
for name, function in cases:
try:
function()
except Exception as error: # noqa: BLE001 - isolated test reporting
failures.append(f"{name}: {error}")
if len(cases) != 25:
failures.append(f"expected 25 cases, found {len(cases)}")
if failures:
print("\n".join(failures), file=sys.stderr)
return 1
print("25 Phase 1.0A guardrails passed")
return 0
if __name__ == "__main__":
raise SystemExit(main())