Files
libretro/tests/test_manifest_entry.py
T
Abdessamad Derraz 057fd2d0f6 fix: isolate every test module however it runs
tests/__init__.py keeps a run offline, its scratch under tmp/ and its
installer cache its own, but only discover -s tests -t . imported it.
discover tests ran with RETROBIOS_OFFLINE unset, scratch on the /tmp
tmpfs and the user's real installer cache, the setting in which e2e
fixtures had written into the shared .cache/large. Every test module now
imports the package first, and a test fails on a module that does not.
test_verify_listing.py took its line with the previous commit.
2026-11-06 15:14:05 +01:00

118 lines
4.5 KiB
Python

"""A manifest entry always names somewhere to fetch it from.
The entry was built twice, once for the platform's files and once for the
core extras, and only the first copy turned a file with no repo path and no
release asset into an omission. An extra whose hash matched nothing in the
database (a copy not yet indexed, or a hash computed wrong) was written with
an empty repo_path, and the installer refused the whole manifest.
"""
from __future__ import annotations
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
import ast
import json
import sys
import unittest
from pathlib import Path
from unittest import mock
REPO_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO_ROOT / "scripts"))
import generate_pack as gp # noqa: E402
from manifestselect import SelectionIndex # noqa: E402
def _held_file(db: dict) -> tuple[str, dict] | None:
for sha1, record in db.get("files", {}).items():
path = REPO_ROOT / record.get("path", "")
if record.get("size", 0) < 4096 and path.is_file():
return sha1, record
return None
class AnEntryWithoutSourceIsAnOmission(unittest.TestCase):
def setUp(self):
db_path = REPO_ROOT / "database.json"
if not db_path.exists():
self.skipTest("database.json is not built")
self.db = json.loads(db_path.read_text(encoding="utf-8"))
held = _held_file(self.db)
if held is None:
self.skipTest("no small indexed file on disk")
self.sha1, self.record = held
# Every case hashes the file anew through its own compute_hashes: a
# result another test verified for the same path and scan is a valid
# cache hit, and it skipped the miscompute this class simulates.
saved = dict(gp._STABLE_HASHES)
gp._STABLE_HASHES.clear()
self.addCleanup(gp._STABLE_HASHES.update, saved)
def _run_core_entries(self, hashes: dict) -> tuple[list, dict, list]:
name = Path(self.record["path"]).name
extra = {
"name": name,
"sha1": self.sha1,
"destination": f"probe/{name}",
"source_emulator": "probe",
}
files: list = []
omitted: dict = {}
pack_only: list = []
def record(full_dest, entry, system, reason, cores):
omitted[full_dest] = reason
with mock.patch.object(gp, "compute_hashes", return_value=hashes):
gp._manifest_core_entries(
[extra], {}, self.db, str(REPO_ROOT / "bios"), "", str(REPO_ROOT),
{}, True, set(), False, set(), set(), set(), files, {},
record, pack_only, SelectionIndex.build({}, {}, {}, []),
)
return files, omitted, pack_only
def test_a_copy_the_database_lacks_is_omitted(self):
"""A copy the scan never indexed has no repo path: an omission."""
with mock.patch.object(gp, "_db_sha1_by_path", return_value={}):
files, omitted, pack_only = self._run_core_entries(
{"sha1": "0" * 40, "sha256": "0" * 64}
)
self.assertEqual(files, [])
self.assertEqual(list(omitted.values()), ["not_found"])
self.assertEqual(pack_only, [self.record["size"]])
def test_a_hash_the_scan_contradicts_is_refused(self):
"""The same path hashed otherwise by the scan is a miscompute: the
run stops instead of publishing a wrong entry."""
with self.assertRaises(RuntimeError):
self._run_core_entries({"sha1": "0" * 40, "sha256": "0" * 64})
def test_a_held_file_is_an_entry_with_its_repo_path(self):
files, omitted, _pack_only = self._run_core_entries(
{"sha1": self.sha1, "sha256": self.record.get("sha256", "")}
)
self.assertEqual(omitted, {})
self.assertEqual(len(files), 1)
self.assertTrue(files[0]["repo_path"])
class OneBuilderForEveryEntry(unittest.TestCase):
"""Two copies of the entry let one drift: the guard lived in one only."""
def test_the_download_record_is_built_in_one_place(self):
tree = ast.parse((REPO_ROOT / "scripts" / "generate_pack.py").read_text())
builders = [
node.lineno
for node in ast.walk(tree)
if isinstance(node, ast.Dict)
and {"repo_path", "sha256"}
<= {k.value for k in node.keys if isinstance(k, ast.Constant)}
]
self.assertEqual(len(builders), 1, f"entry dicts at lines {builders}")
if __name__ == "__main__":
unittest.main()