mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-11 12:33:53 -06:00
RetroPie was the only platform with status: archived, which kept it out of verify --all, slots, the pipeline and list_platforms unless --include-archived was typed. release_pack already decides which packs a release publishes and the installer serves every platform, so the status set nothing apart. The field, its schema entry and the flag are gone, and RetroPie is covered by every full run like any other platform.
127 lines
4.6 KiB
Python
127 lines
4.6 KiB
Python
#!/usr/bin/env python3
|
|
"""End-to-end pack integrity test.
|
|
|
|
Thin unittest wrapper around generate_pack.py --verify-packs, which checks
|
|
every declared platform file and every in-repo core extra against the pack,
|
|
at the correct path and with the correct hash per the platform's native mode.
|
|
|
|
The assertion presupposes a pack built from the current profiles. The check
|
|
runs first and keeps its teeth: a failure is only downgraded to a skip when a
|
|
profile landed after the pack was built, which makes the pack incomplete by
|
|
construction and says nothing about pack generation. A failure on an up to
|
|
date pack stays a failure.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import glob
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import unittest
|
|
|
|
REPO_ROOT = os.path.join(os.path.dirname(__file__), "..")
|
|
DIST_DIR = os.path.join(REPO_ROOT, "dist")
|
|
PLATFORMS_DIR = os.path.join(REPO_ROOT, "platforms")
|
|
EMULATORS_DIR = os.path.join(REPO_ROOT, "emulators")
|
|
|
|
|
|
def _pack_path(platform_name: str) -> str | None:
|
|
"""Path of the platform's full pack, by the exact name the builder writes."""
|
|
if not os.path.isdir(DIST_DIR):
|
|
return None
|
|
sys.path.insert(0, os.path.join(REPO_ROOT, "scripts"))
|
|
from generate_pack import _expected_pack_names
|
|
|
|
names = _expected_pack_names([platform_name], PLATFORMS_DIR, [], None)
|
|
for entry in sorted(names[platform_name]):
|
|
path = os.path.join(DIST_DIR, entry)
|
|
if os.path.isfile(path):
|
|
return path
|
|
return None
|
|
|
|
|
|
def _registered_platforms() -> list[str]:
|
|
sys.path.insert(0, os.path.join(REPO_ROOT, "scripts"))
|
|
from common import list_registered_platforms
|
|
|
|
return list_registered_platforms(PLATFORMS_DIR)
|
|
|
|
|
|
def _profiles_newer_than(path: str, platform_name: str) -> list[str]:
|
|
"""Profiles of this platform's emulators modified after the pack was built.
|
|
|
|
A profile the platform never resolves cannot have changed its pack: a
|
|
comment edited in any of 500 profiles used to disarm the integrity
|
|
check of every pack on disk.
|
|
"""
|
|
sys.path.insert(0, os.path.join(REPO_ROOT, "scripts"))
|
|
from common import load_emulator_profiles, load_platform_config, resolve_platform_cores
|
|
|
|
built = os.path.getmtime(path)
|
|
config = load_platform_config(platform_name, PLATFORMS_DIR)
|
|
profiles = load_emulator_profiles(EMULATORS_DIR)
|
|
relevant = resolve_platform_cores(config, profiles)
|
|
return [
|
|
os.path.basename(p)
|
|
for p in glob.glob(os.path.join(EMULATORS_DIR, "*.yml"))
|
|
if os.path.splitext(os.path.basename(p))[0] in relevant
|
|
and os.path.getmtime(p) > built
|
|
]
|
|
|
|
|
|
class PackIntegrityTest(unittest.TestCase):
|
|
"""Verify each platform pack via generate_pack.py --verify-packs."""
|
|
|
|
def _verify_platform(self, platform_name: str) -> None:
|
|
pack = _pack_path(platform_name)
|
|
if pack is None:
|
|
self.skipTest(f"no pack found for {platform_name}")
|
|
result = subprocess.run(
|
|
[
|
|
sys.executable,
|
|
"scripts/generate_pack.py",
|
|
"--platform",
|
|
platform_name,
|
|
"--verify-packs",
|
|
"--output-dir",
|
|
"dist/",
|
|
],
|
|
capture_output=True,
|
|
text=True,
|
|
cwd=REPO_ROOT,
|
|
)
|
|
if result.returncode == 0:
|
|
return
|
|
# A build holding the exclusive lock means the packs on disk are
|
|
# half-written. Failing then reports a corrupt archive when the only
|
|
# fact established is that somebody else is building, and which test
|
|
# goes red depends on how far along that build is.
|
|
if "is in use by another run" in (result.stdout + result.stderr):
|
|
self.skipTest(f"dist/ is being written; {platform_name} not verifiable")
|
|
newer = _profiles_newer_than(pack, platform_name)
|
|
if newer:
|
|
self.skipTest(
|
|
f"{platform_name} pack predates {len(newer)} profile(s) "
|
|
f"({', '.join(sorted(newer)[:3])}): rebuild before verifying\n"
|
|
f"{result.stdout}"
|
|
)
|
|
self.fail(
|
|
f"{platform_name} pack integrity failed:\n"
|
|
f"{result.stdout}\n{result.stderr}"
|
|
)
|
|
|
|
def test_every_registered_platform(self):
|
|
"""Every platform the registry knows, not a list written by hand.
|
|
|
|
Eight names were written out and ROCKNIX and MiSTer FPGA, both
|
|
released, were never checked.
|
|
"""
|
|
for platform_name in _registered_platforms():
|
|
with self.subTest(platform=platform_name):
|
|
self._verify_platform(platform_name)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|