Files
libretro/tests/test_owner_resolution.py
T
Abdessamad Derraz ed610c7bf3 fix: hold the consumer guards on fixtures
The Dolphin-MMJR codehandler.bin and armsx2's game_controller_db.txt left
the collection, and the two guards that read them skipped on every run.
Both now build the trees they need, and the guards still reading the
repository fail instead of skipping when their data is gone.
2026-10-21 09:55:50 +02:00

114 lines
4.2 KiB
Python

"""Every reader of a profile entry names its owner, as the builder does.
The resolver prefers the owning profile's copy when a name has several. The
builder passes `source_profile`. The site's consumer index, the slot claims
and the agnostic scan did not, and resolved 95 entries to other files: the
site credited aethersx2's game_controller_db.txt to armsx2 and left the copy
armsx2's pack ships without a reader, and MAME's neogeo.zip without MAME.
"""
from __future__ import annotations
import hashlib
import os
import sys
import tempfile
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO_ROOT / "scripts"))
import cross_reference # noqa: E402
import slots # noqa: E402
from common import ( # noqa: E402
build_zip_contents_index,
load_database,
load_emulator_profiles,
)
class ReadersNameTheOwner(unittest.TestCase):
@classmethod
def setUpClass(cls):
db_path = REPO_ROOT / "database.json"
if not db_path.exists():
raise AssertionError("database.json is committed and missing")
cls.db = load_database(str(db_path))
cls.profiles = load_emulator_profiles(str(REPO_ROOT / "emulators"))
cls.sha1_by_path = {r["path"]: s for s, r in cls.db["files"].items()}
def test_the_site_credits_the_copy_the_pack_ships(self):
consumers = cross_reference.FileConsumers(
self.db, build_zip_contents_index(self.db)
)
consumers.add_emulators(self.profiles)
sha1 = self.sha1_by_path.get("bios/Arcade/MAME/neogeo.zip")
self.assertIsNotNone(sha1, "MAME's neogeo.zip is not collected")
self.assertIn("mame", consumers.emulators.get(sha1, set()))
def test_slot_claims_resolve_the_owners_tree(self):
claims = slots.profile_claims({"pcem": self.profiles["pcem"]}, self.db)
held = {
claim.destination.rsplit("/", 1)[-1]: claim.local_path for claim in claims
}
# pcem declares ide_xt.bin and the collection holds it: an unclaimed
# file here is a claiming defect, not missing data.
self.assertTrue(
any(e.get("path", "").endswith("/ide_xt.bin")
for e in self.db["files"].values()),
"ide_xt.bin is not collected",
)
local = held.get("ide_xt.bin")
self.assertIsNotNone(local, "pcem's ide_xt.bin is not claimed")
self.assertTrue(local.startswith("bios/Other/pcem/"), local)
class EachForkReadsItsOwnCopy(unittest.TestCase):
"""Two emulators ship a file under one name in their own trees. Without
the owner, the site credited aethersx2's game_controller_db.txt to
armsx2 and left the copy armsx2's pack ships without a reader."""
NAME = "game_controller_db.txt"
def setUp(self):
self._previous = os.getcwd()
self._tree = tempfile.TemporaryDirectory()
root = Path(self._tree.name)
files: dict[str, dict] = {}
self.sha1_of: dict[str, str] = {}
for owner in ("aethersx2", "armsx2"):
rel = f"bios/Other/{owner}/{self.NAME}"
payload = f"{owner} mappings".encode()
(root / rel).parent.mkdir(parents=True)
(root / rel).write_bytes(payload)
sha1 = hashlib.sha1(payload).hexdigest()
files[sha1] = {
"name": self.NAME, "sha1": sha1, "path": rel,
"md5": hashlib.md5(payload).hexdigest(), "size": len(payload),
}
self.sha1_of[owner] = sha1
self.db = {"files": files, "indexes": {
"by_name": {self.NAME: sorted(files)},
"by_md5": {}, "by_path_suffix": {},
}}
os.chdir(root)
def tearDown(self):
os.chdir(self._previous)
self._tree.cleanup()
def test_the_site_credits_each_owner_with_its_copy(self):
consumers = cross_reference.FileConsumers(self.db, data_dir_registry={})
consumers.add_emulators({
owner: {"type": "standalone", "files": [{"name": self.NAME}]}
for owner in self.sha1_of
})
for owner, sha1 in self.sha1_of.items():
with self.subTest(owner=owner):
self.assertEqual(consumers.emulators.get(sha1), {owner})
if __name__ == "__main__":
unittest.main()