Files
libretro/tests/test_verify_release_asset.py
T
Abdessamad Derraz 9a0501d9d3 fix: count an uncached release asset as fetched
verify resolved offline, so a release asset absent from bios/ and the
cache read as missing while an online build fetched and packed it. verify
now reads the database record of the registered path and counts such a
declaration present, listed as fetched at build time. --offline keeps the
old count, and the offline pipeline passes it to its verify step.
2026-10-21 10:50:03 +02:00

132 lines
4.9 KiB
Python

"""verify counts a release asset the cache lacks as an online build does.
verify never downloads. A declaration served by a release asset of the
large-files release, absent from bios/ and from .cache/large/, read as
missing there while an online build fetched it and packed it, so the two
disagreed on every checkout without the cache (CI among them). The
database record of the registered path says whether the asset answers the
declaration. Under --offline the builder fetches nothing, and verify then
counts the file missing as before.
"""
from __future__ import annotations
import hashlib
import os
import sys
import tempfile
import unittest
import zipfile
from pathlib import Path
from unittest import mock
import yaml
REPO_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO_ROOT / "scripts"))
import common # noqa: E402
import generate_db # noqa: E402
import generate_pack as builder # noqa: E402
import packresolve # noqa: E402
from verify import Status, verify_platform # noqa: E402
PAYLOAD = b"a firmware image the repository does not commit"
SHA1 = hashlib.sha1(PAYLOAD).hexdigest()
REGISTERED = ["bios/Big/big.bin"]
class ReleaseAssetNotCached(unittest.TestCase):
mode = "existence"
def setUp(self):
self._tmp = tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp")
self._cwd = os.getcwd()
os.chdir(self._tmp.name)
for d in ("emulators", "platforms", "bios/Big"):
Path(d).mkdir(parents=True)
# Indexed by the database, gitignored, so absent from a checkout.
files = {SHA1: {
"path": REGISTERED[0], "name": "big.bin", "size": len(PAYLOAD),
"sha1": SHA1, "md5": hashlib.md5(PAYLOAD).hexdigest(),
"sha256": hashlib.sha256(PAYLOAD).hexdigest(), "crc32": "00000001",
}}
self.db = {"files": files, "indexes": generate_db.build_indexes(files, {})}
self.config = {
"platform": "Big", "verification_mode": self.mode,
"systems": {"sys": {"files": [{
"name": "big.bin", "destination": "big.bin", "required": True,
"sha1": SHA1, "md5": hashlib.md5(PAYLOAD).hexdigest(),
}]}},
}
Path("platforms/big.yml").write_text(yaml.dump(self.config))
Path("platforms/_registry.yml").write_text(
yaml.dump({"platforms": {"big": {"status": "active"}}})
)
common._platform_config_cache.clear()
common._emulator_profiles_cache.clear()
patches = (
mock.patch("largefiles.load_registered_paths", return_value=REGISTERED),
mock.patch.dict(os.environ, {"RETROBIOS_OFFLINE": ""}),
)
for patch in patches:
patch.start()
self.addCleanup(patch.stop)
self.addCleanup(packresolve.set_offline, False)
packresolve.set_offline(False)
def tearDown(self):
common._platform_config_cache.clear()
os.chdir(self._cwd)
self._tmp.cleanup()
def _entry(self) -> dict:
report = verify_platform(self.config, self.db, "emulators", {})
return next(d for d in report["details"] if d["name"] == "big.bin")
def test_counted_as_fetched_when_the_pack_is_built(self):
entry = self._entry()
self.assertEqual(entry["status"], Status.OK)
self.assertEqual(entry["release_asset"], REGISTERED[0])
def test_offline_counts_it_missing(self):
packresolve.set_offline(True)
self.assertEqual(self._entry()["status"], Status.MISSING)
def test_an_asset_with_other_content_is_not_counted(self):
self.config["systems"]["sys"]["files"][0]["sha1"] = "0" * 40
self.assertEqual(self._entry()["status"], Status.MISSING)
def test_the_online_build_packs_it(self):
cache = Path("cache/big.bin")
cache.parent.mkdir()
cache.write_bytes(PAYLOAD)
with mock.patch.object(
packresolve, "fetch_large_file", return_value=str(cache)
):
zip_path = builder.generate_pack(
"big", "platforms", self.db, "bios", "out",
emulators_dir="emulators", emu_profiles={}, offline=False,
)
with zipfile.ZipFile(zip_path) as zf:
self.assertEqual(zf.read("big.bin"), PAYLOAD)
self.assertEqual(self._entry()["status"], Status.OK)
class ReleaseAssetNotCachedMd5(ReleaseAssetNotCached):
mode = "md5"
class OfflinePipelineVerifiesOffline(unittest.TestCase):
"""The offline pipeline builds packs without release assets: its verify
step has to count them the same way, or step 5 compares two answers."""
def test_verify_step_gets_offline(self):
source = (REPO_ROOT / "scripts" / "pipeline.py").read_text()
block = source[source.index("verify_cmd = ["):source.index("ok, verify_output = run(")]
self.assertIn('verify_cmd.append("--offline")', block)
if __name__ == "__main__":
unittest.main()