85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Run all Phase 6 offline gates from any working directory."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
TESTS = [
|
|
ROOT / "patches/epg-stale-cleanup/tools/test_epg_retention.py",
|
|
ROOT / "patches/gel-workmanager/tools/verify_stock_callsite.py",
|
|
ROOT / "patches/gel-workmanager/tools/test_bounded_outbox.py",
|
|
ROOT / "patches/usb-freesize/tools/test_usb_size_policy.py",
|
|
ROOT / "patches/storage-monitor/tools/test_storage_state.py",
|
|
]
|
|
GOLDEN = {
|
|
"diagnostics/raw/storage/channels.apk": "3a44bc648624f0cc9cd9feb4cfc3fd33f41323597718e4fccfc25fe35504d34f",
|
|
"diagnostics/raw/storage/gel.apk": "29a68e6b09700ed4ccdf312c0b99eee0c3f67e329a537fe87ed4341a71d383d7",
|
|
"diagnostics/phase4/reference-binaries/tvfw.jar": "a0061795d87cf76c9b739e32022ab3d8c29f47ed01ddc1eee189dd815a8d11ad",
|
|
"diagnostics/raw/TPTvService.apk": "75f492ee89906c8c267d685d2b7d0ce02bb09f3a6b4cc8456f8b096b9e441ecd",
|
|
"diagnostics/phase4/epg-snapshot/EpgDatabase.db": "71403743206d5082aae56c4a947f3429f5c3d54b908c4abe2eb0ca66e06694ba",
|
|
}
|
|
ARTIFACTS = [
|
|
"patches/epg-stale-cleanup/PATCH.diff",
|
|
"patches/epg-stale-cleanup/tools/epg_retention.py",
|
|
"patches/gel-workmanager/PATCH.diff",
|
|
"patches/gel-workmanager/tools/verify_stock_callsite.py",
|
|
"patches/usb-freesize/PATCH.diff",
|
|
"patches/storage-monitor/POLICY.md",
|
|
"patches/storage/SELECTIVE-ADOPTED-DESIGN.md",
|
|
]
|
|
|
|
|
|
def digest(path: Path) -> str:
|
|
h = hashlib.sha256()
|
|
with path.open("rb") as f:
|
|
for chunk in iter(lambda: f.read(1024 * 1024), b""):
|
|
h.update(chunk)
|
|
return h.hexdigest()
|
|
|
|
|
|
def main() -> int:
|
|
omitted_baselines: list[str] = []
|
|
for rel, expected in GOLDEN.items():
|
|
path = ROOT / rel
|
|
if not path.exists():
|
|
omitted_baselines.append(rel)
|
|
print(f"SKIP unpublished golden binary: {rel}")
|
|
continue
|
|
got = digest(path)
|
|
if got != expected:
|
|
raise SystemExit(f"FAIL golden hash: {rel}: {got}")
|
|
print(f"PASS golden hash: {rel}")
|
|
|
|
for test in TESTS:
|
|
if test.name == "verify_stock_callsite.py" and not (
|
|
ROOT / "diagnostics/raw/storage/gel.apk"
|
|
).exists():
|
|
print("SKIP stock GEL callsite test: unpublished APK is required")
|
|
continue
|
|
print(f"RUN {test.relative_to(ROOT)}", flush=True)
|
|
subprocess.run([sys.executable, str(test)], cwd=test.parent, check=True)
|
|
|
|
lines = [f"{digest(ROOT / rel)} {rel}" for rel in ARTIFACTS]
|
|
if "--write-hashes" in sys.argv:
|
|
out = ROOT / "patches/artifacts/hashes.sha256"
|
|
out.write_text("\n".join(lines) + "\n", encoding="ascii")
|
|
print(f"WROTE {out.relative_to(ROOT)}")
|
|
else:
|
|
print("\n".join(lines))
|
|
if omitted_baselines:
|
|
print(
|
|
"NOTE: publication omits private/redistributable baselines; "
|
|
"their expected hashes remain documented"
|
|
)
|
|
print("PASS: all available Phase 6 offline gates")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|