Files
libretro/tests/test_entry_categories.py
T
Abdessamad Derraz cd7d993cac feat: settle entries by their system's cores
A system that lists the cores it runs is settled by those cores alone, so an unprofiled core of another system no longer leaves its entries open. Readers whose core runs the entry's system are named first, and cores that only share the file name are listed as such.
2026-10-22 06:30:56 +02:00

149 lines
7.2 KiB
Python

"""What a platform entry is: firmware, a game's data, or unread.
Strict verification fails on firmware gaps only, so the category has to come
from what the cores the platform runs open, never from the entry's name.
"""
from __future__ import annotations
import sys
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts"))
import verify # noqa: E402
from exporter.candidates import BIOS, GAME_DATA, UNREAD, EntryCategories # noqa: E402
PROFILES = {
"bluemsx": {
"emulator": "blueMSX", "type": "libretro", "cores": ["bluemsx"],
"systems": ["microsoft-msx"],
"files": [{"name": "MSX.ROM", "path": "Machines/Shared Roms/MSX.ROM"}],
},
"devilutionx": {
"emulator": "DevilutionX", "type": "game", "cores": ["devilutionx"],
"systems": ["diablo"],
"files": [{"name": "diabdat.mpq", "category": "game_data",
"source_ref": "Source/init.cpp:120"}],
},
}
def _config(cores: list[str], files: list[dict], system: str = "s") -> dict:
return {"platform": "P", "verification_mode": "md5", "cores": cores,
"systems": {system: {"files": files}}}
class Category(unittest.TestCase):
def test_each_category(self):
cats = EntryCategories(_config(["bluemsx", "devilutionx"], []), PROFILES)
self.assertEqual(cats.category({"name": "MSX.ROM"}, "bios/Machines/MSX/MSX.ROM", "microsoft-msx"), BIOS)
self.assertEqual(cats.category({"name": "diabdat.mpq"}, "ports/diablo/diabdat.mpq", "diablo"),
GAME_DATA)
self.assertEqual(
cats.category({"name": "hardwareconfig.xml"}, "bios/Machines/MSX/hardwareconfig.xml", "microsoft-msx"),
UNREAD)
def test_a_core_without_profile_leaves_unread_open(self):
cats = EntryCategories(_config(["bluemsx", "devilutionx", "mystery"], []), PROFILES)
self.assertEqual(
cats.category({"name": "hardwareconfig.xml"}, "bios/Machines/MSX/hardwareconfig.xml", "microsoft-msx"),
BIOS)
self.assertEqual(cats.category({"name": "diabdat.mpq"}, "ports/diablo/diabdat.mpq", "diablo"),
GAME_DATA)
def test_a_system_no_examined_core_emulates_stays_firmware(self):
cats = EntryCategories(_config(["bluemsx", "devilutionx"], []), PROFILES)
self.assertEqual(cats.category({"name": "syscard3.pce"}, "syscard3.pce", "nec-pc-engine"),
BIOS)
def test_cores_guessed_from_system_ids_prove_nothing(self):
config = _config([], [])
del config["cores"]
cats = EntryCategories(config, PROFILES)
self.assertEqual(
cats.category({"name": "hardwareconfig.xml"}, "bios/Machines/MSX/hardwareconfig.xml",
"microsoft-msx"),
BIOS)
def test_a_platform_with_no_core_is_all_firmware(self):
cats = EntryCategories(_config([], []), PROFILES)
self.assertEqual(cats.category({"name": "anything.bin"}, "anything.bin", "s"), BIOS)
class Evidence(unittest.TestCase):
"""Each category says what establishes it, so the report documents it."""
def setUp(self):
self.cats = EntryCategories(_config(["bluemsx", "devilutionx"], []), PROFILES)
def test_game_data_names_its_reader_and_reference(self):
found = self.cats.explain({"name": "diabdat.mpq"}, "ports/diablo/diabdat.mpq", "diablo")
self.assertEqual(found["category"], GAME_DATA)
self.assertEqual(found["read_by"], [{
"emulator": "devilutionx", "proof": "name", "runs_system": True,
"entries": [{"name": "diabdat.mpq", "source_ref": "Source/init.cpp:120"}]}])
self.assertEqual(verify.category_evidence_text(found),
"read by devilutionx (diabdat.mpq at Source/init.cpp:120)")
def test_unread_names_the_cores_examined(self):
found = self.cats.explain({"name": "hardwareconfig.xml"},
"bios/Machines/MSX/hardwareconfig.xml", "microsoft-msx")
self.assertEqual(found, {"category": UNREAD, "cores_examined": ["bluemsx"]})
def test_the_system_s_own_core_reads_first(self):
profiles = {**PROFILES, "other": {
"emulator": "Other", "type": "game", "cores": ["other"], "systems": ["elsewhere"],
"files": [{"name": "diabdat.mpq", "category": "game_data"}]}}
cats = EntryCategories(_config(["bluemsx", "devilutionx", "other"], []), profiles)
found = cats.explain({"name": "diabdat.mpq"}, "ports/diablo/diabdat.mpq", "diablo")
self.assertEqual([r["emulator"] for r in found["read_by"]], ["devilutionx", "other"])
self.assertEqual(verify.category_evidence_text(found),
"read by devilutionx (diabdat.mpq at Source/init.cpp:120), "
"also named by other (diabdat.mpq)")
def test_a_system_s_own_cores_settle_it(self):
config = _config(["bluemsx", "devilutionx", "mystery"], [], system="microsoft-msx")
config["systems"]["microsoft-msx"]["cores"] = ["bluemsx"]
found = EntryCategories(config, PROFILES).explain(
{"name": "hardwareconfig.xml"}, "bios/Machines/MSX/hardwareconfig.xml",
"microsoft-msx")
self.assertEqual(found, {"category": UNREAD, "cores_examined": ["bluemsx"]})
self.assertEqual(verify.category_evidence_text(found),
"no reader found (cores examined: bluemsx)")
def test_an_unsettled_entry_says_why(self):
cats = EntryCategories(_config(["bluemsx", "devilutionx", "mystery"], []), PROFILES)
found = cats.explain({"name": "hardwareconfig.xml"},
"bios/Machines/MSX/hardwareconfig.xml", "microsoft-msx")
self.assertEqual(found["category"], BIOS)
self.assertIn("mystery", found["unsettled"])
self.assertIn("not settled", verify.category_evidence_text(found))
class StrictCountsFirmwareOnly(unittest.TestCase):
def test_missing_game_data_and_unread_carry_no_severity(self):
config = _config(["bluemsx", "devilutionx"], [
{"name": "diabdat.mpq", "destination": "ports/diablo/diabdat.mpq", "required": True},
{"name": "hardwareconfig.xml",
"destination": "bios/Machines/MSX/hardwareconfig.xml", "required": True},
{"name": "MSX.ROM", "destination": "bios/Machines/MSX/MSX.ROM", "required": True},
], system="microsoft-msx")
db = {"files": {}, "indexes": {"by_md5": {}, "by_name": {}, "by_crc32": {},
"by_path_suffix": {}}}
result = verify.verify_platform(config, db, emu_profiles=PROFILES)
self.assertEqual(result["severity_counts"][verify.Severity.CRITICAL], 1)
self.assertEqual(result["missing_not_firmware"], {
"game_data": ["ports/diablo/diabdat.mpq"],
"unread": ["bios/Machines/MSX/hardwareconfig.xml"],
})
self.assertEqual(result["status_counts"][verify.Status.MISSING], 3)
evidence = {d["name"]: d.get("category_evidence") for d in result["details"]}
self.assertEqual(evidence["hardwareconfig.xml"]["cores_examined"], ["bluemsx"])
self.assertEqual(evidence["diabdat.mpq"]["read_by"][0]["emulator"], "devilutionx")
if __name__ == "__main__":
unittest.main()