mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
feat: categorize missing platform entries
A platform list can name a game's data files or a file no core it runs opens. Verify gives each missing entry a category read from the profiles of the platform's cores: firmware, game data or unread. Only firmware gaps carry a severity and fail --strict; the others are counted on their own line, and the pack check no longer counts them as pack errors. Missing firmware stays a conformance error.
This commit is contained in:
1 parent
7e2f753c96
commit
f66adfdcbc
7 files changed
+269
-27
No files matched your search
@@ -4226,8 +4226,10 @@ class VerifyPacksSaysWhatItExcluded(unittest.TestCase):
|
||||
source = (ROOT / "scripts" / "generate_pack.py").read_text()
|
||||
body = source[source.index("def _run_verify_packs"):]
|
||||
body = body[:body.index("\ndef ")]
|
||||
self.assertIn("bl_excluded) = result", body)
|
||||
self.assertIn("unsafe excluded", body)
|
||||
self.assertIn("bl_excluded, bl_absent) = result", body)
|
||||
self.assertIn("_baseline_shortfall(bl_excluded, bl_absent)", body)
|
||||
shortfall = source[source.index("def _baseline_shortfall"):]
|
||||
self.assertIn("unsafe excluded", shortfall[:shortfall.index("\ndef ")])
|
||||
self.assertNotIn("errors[:5]", body)
|
||||
self.assertNotRegex(body, r"result\[\d\]")
|
||||
|
||||
|
||||
+22
-12
@@ -5268,13 +5268,17 @@ struct BurnDriver BurnDrvneogeo = {
|
||||
)
|
||||
self.assertEqual(result[3], [], f"unexpected errors: {result[3]}")
|
||||
|
||||
def test_213b_file_the_collection_lacks_is_no_pack_error(self):
|
||||
"""A declared file nothing resolves to is a data gap verify reports;
|
||||
a held file absent from the pack stays a pack error."""
|
||||
def test_213b_absent_game_data_is_counted_apart(self):
|
||||
"""Game data the collection lacks is counted apart from the pack's
|
||||
errors; firmware the collection lacks stays one."""
|
||||
import tempfile
|
||||
|
||||
from generate_pack import generate_pack, verify_pack_against_platform
|
||||
|
||||
profiles = {"eng": {"emulator": "Eng", "type": "game", "cores": ["eng"],
|
||||
"systems": ["arcade-sys"],
|
||||
"files": [{"name": "data.pak", "category": "game_data"},
|
||||
{"name": "firmware.bin"}]}}
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
plat_dir, bios_root, out_dir, db, _h, _hl = self._make_hash_zip_fixture(
|
||||
tmpdir, declare_md5=True
|
||||
@@ -5282,22 +5286,28 @@ struct BurnDriver BurnDrvneogeo = {
|
||||
config_path = os.path.join(plat_dir, "test_hashzip.yml")
|
||||
with open(config_path) as fh:
|
||||
config = yaml.safe_load(fh)
|
||||
config["cores"] = ["eng"]
|
||||
config["systems"]["arcade-sys"]["files"].append(
|
||||
{"name": "absent.bin", "destination": "dc/absent.bin"}
|
||||
{"name": "data.pak", "destination": "dc/data.pak"}
|
||||
)
|
||||
with open(config_path, "w") as fh:
|
||||
yaml.dump(config, fh)
|
||||
zip_path = generate_pack("test_hashzip", plat_dir, db, bios_root, out_dir)
|
||||
result = verify_pack_against_platform(zip_path, "test_hashzip", plat_dir, db=db)
|
||||
zip_path = generate_pack("test_hashzip", plat_dir, db, bios_root, out_dir,
|
||||
emu_profiles=profiles)
|
||||
result = verify_pack_against_platform(
|
||||
zip_path, "test_hashzip", plat_dir, db=db, emu_profiles=profiles)
|
||||
self.assertEqual(result[3], [])
|
||||
self.assertEqual((result[4], result[5], result[9]), (2, 1, 1))
|
||||
|
||||
empty = os.path.join(out_dir, "Empty.zip")
|
||||
with zipfile.ZipFile(empty, "w") as zf:
|
||||
zf.writestr("README.txt", "")
|
||||
result = verify_pack_against_platform(empty, "test_hashzip", plat_dir, db=db)
|
||||
self.assertEqual(result[3], ["baseline missing: dc/testbios.zip"])
|
||||
self.assertEqual(result[9], 1)
|
||||
config["systems"]["arcade-sys"]["files"][-1]["name"] = "firmware.bin"
|
||||
config["systems"]["arcade-sys"]["files"][-1]["destination"] = "dc/firmware.bin"
|
||||
with open(os.path.join(plat_dir, "test_hashzip_fw.yml"), "w") as fh:
|
||||
yaml.dump(config, fh)
|
||||
result = verify_pack_against_platform(
|
||||
zip_path, "test_hashzip_fw", plat_dir, db=db, emu_profiles=profiles)
|
||||
self.assertEqual([e.rsplit("/", 1)[-1] for e in result[3]], ["firmware.bin"])
|
||||
self.assertTrue(result[3][0].startswith("baseline missing: "))
|
||||
self.assertEqual(result[9], 0)
|
||||
|
||||
def test_214_hash_matches_truncated_and_multi(self):
|
||||
"""Declared-hash compare handles truncation, case, multi-values."""
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
"""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"}],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
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 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)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user