mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
114 lines
5.1 KiB
Python
114 lines
5.1 KiB
Python
"""An archive declared once per member ships as the copy holding them all.
|
|
|
|
Batocera checks adam_fdc.zip through eight zipped_file declarations. The
|
|
first hash-exact answer was a one-member MAME set, so the pack shipped it and
|
|
seven of the eight members Batocera checks were missing.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
import zipfile
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
|
|
|
|
|
class PreferredArchive(unittest.TestCase):
|
|
def test_the_archive_most_declarations_accept_wins(self):
|
|
import generate_pack
|
|
|
|
roms = {f"r{i}.bin": bytes([i]) * 32 for i in range(3)}
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
previous = os.getcwd()
|
|
os.chdir(tmp)
|
|
self.addCleanup(os.chdir, previous)
|
|
Path("bios/a").mkdir(parents=True)
|
|
Path("bios/b").mkdir(parents=True)
|
|
with zipfile.ZipFile("bios/a/set.zip", "w") as zf:
|
|
zf.writestr("r0.bin", roms["r0.bin"])
|
|
with zipfile.ZipFile("bios/b/set.zip", "w") as zf:
|
|
for name, data in roms.items():
|
|
zf.writestr(name, data)
|
|
files, by_md5, by_name = {}, {}, {}
|
|
for path in ("bios/a/set.zip", "bios/b/set.zip"):
|
|
data = Path(path).read_bytes()
|
|
sha1, md5 = hashlib.sha1(data).hexdigest(), hashlib.md5(data).hexdigest()
|
|
files[sha1] = {"path": path, "name": "set.zip", "sha1": sha1, "md5": md5,
|
|
"size": len(data)}
|
|
by_md5[md5] = sha1
|
|
by_name.setdefault("set.zip", []).append(sha1)
|
|
db = {"files": files, "indexes": {"by_name": by_name, "by_md5": by_md5,
|
|
"by_path_suffix": {}, "by_crc32": {}}}
|
|
member_md5 = {n: hashlib.md5(d).hexdigest() for n, d in roms.items()}
|
|
one_member = files[by_name["set.zip"][0]]["md5"]
|
|
declarations = [{"name": "set.zip", "destination": "set.zip", "md5": one_member}]
|
|
declarations += [
|
|
{"name": "set.zip", "destination": "set.zip", "zipped_file": name, "md5": md5}
|
|
for name, md5 in member_md5.items()
|
|
]
|
|
systems = {"s": {"files": declarations}}
|
|
preferred = generate_pack._preferred_entries(
|
|
systems, db, "bios", "", False, {}, None, True)
|
|
chosen = next(fe for fe in declarations if id(fe) == preferred["set.zip"])
|
|
path, _status = generate_pack.resolve_file(chosen, db, "bios", {}, offline=True)
|
|
self.assertEqual(path, "bios/b/set.zip")
|
|
|
|
|
|
class IntegrityChecksEveryMember(unittest.TestCase):
|
|
"""A pack holding one ROM of an archive declared per ROM fails its check.
|
|
|
|
The check accepted the destination as soon as one declaration passed,
|
|
so a Batocera pack missing seven of adam_fdc.zip's eight ROMs verified.
|
|
"""
|
|
|
|
def test_a_missing_member_is_an_error_when_the_repository_holds_it(self):
|
|
import yaml
|
|
|
|
import packverify
|
|
|
|
roms = {f"r{i}.bin": bytes([i]) * 32 for i in range(3)}
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
previous = os.getcwd()
|
|
os.chdir(tmp)
|
|
self.addCleanup(os.chdir, previous)
|
|
Path("bios/b").mkdir(parents=True)
|
|
with zipfile.ZipFile("bios/b/set.zip", "w") as zf:
|
|
for name, data in roms.items():
|
|
zf.writestr(name, data)
|
|
data = Path("bios/b/set.zip").read_bytes()
|
|
sha1 = hashlib.sha1(data).hexdigest()
|
|
db = {"files": {sha1: {"path": "bios/b/set.zip", "name": "set.zip", "sha1": sha1,
|
|
"md5": hashlib.md5(data).hexdigest(), "size": len(data)}},
|
|
"indexes": {"by_name": {"set.zip": [sha1]}, "by_md5": {},
|
|
"by_path_suffix": {}, "by_crc32": {}}}
|
|
Path("platforms").mkdir()
|
|
config = {"platform": "P", "verification_mode": "md5", "base_destination": "bios",
|
|
"cores": [], "systems": {"s": {"files": [
|
|
{"name": "set.zip", "destination": "set.zip", "zipped_file": n,
|
|
"md5": hashlib.md5(d).hexdigest()} for n, d in roms.items()]}}}
|
|
Path("platforms/p.yml").write_text(yaml.safe_dump(config), encoding="utf-8")
|
|
Path("emulators").mkdir()
|
|
import io
|
|
|
|
inner = io.BytesIO()
|
|
with zipfile.ZipFile(inner, "w") as zf:
|
|
zf.writestr("r0.bin", roms["r0.bin"])
|
|
with zipfile.ZipFile("pack.zip", "w") as zf:
|
|
zf.writestr("bios/set.zip", inner.getvalue())
|
|
ok, *_rest, = packverify.verify_pack_against_platform(
|
|
"pack.zip", "p", "platforms", db, emulators_dir="emulators", emu_profiles={})
|
|
errors = _rest[2]
|
|
self.assertFalse(ok)
|
|
self.assertEqual(sorted(e.split(": ")[1] for e in errors),
|
|
["r1.bin not found inside ZIP", "r2.bin not found inside ZIP"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|