Files
libretro/tests/test_mame_ref_audit.py

129 lines
4.9 KiB
Python

"""A MAME romset ref must name the line declaring its own set.
profile_sync follows content, so a drifted ref still anchors wherever the
cited text went. That is drift detection working, and it cannot answer the
only question a MAME ref asks: does this line declare this set. Asking it
found nineteen stale refs in one driver where profile_sync had flagged five.
"""
from __future__ import annotations
import sys
import tempfile
import unittest
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "scripts"))
import mame_ref_audit
from mame_ref_audit import declares
DRIVER = [
"// a driver file",
"CONS( 2000, ekara, 0, 0, m, i, s, init, \"Takara\", \"e-kara\", F )",
"CONS( 2002, ekarag, ekara, 0, m, i, s, init, \"Takara\", \"e-kara DE\", F )",
"/* Naomi */ GAME( 1998, naomi, 0, n, n, s, init, ROT0, \"Sega\", \"Naomi\", F )",
"ROM_START( soundbox )",
]
PROFILE = """emulator: Test
source: "https://github.com/libretro/mame"
source_commit: "pinsha"
files:
- name: ekara.zip
category: bios_zip
source_ref: "src/mame/tvgames/xavix.cpp:99"
- name: ekarag.zip
category: bios_zip
source_ref: "src/mame/tvgames/xavix.cpp:3"
- name: soundbox.zip
category: bios_zip
source_ref: "src/mame/sega/segaai.cpp:1"
"""
class TestDeclares(unittest.TestCase):
def test_the_set_name_is_argument_one(self):
self.assertTrue(declares(DRIVER[1], "ekara"))
def test_a_clone_naming_it_as_parent_is_not_a_declaration(self):
"""ekara is the parent field of ekarag; most of a driver looks so."""
self.assertFalse(declares(DRIVER[2], "ekara"))
self.assertTrue(declares(DRIVER[2], "ekarag"))
def test_a_declaration_behind_a_comment_still_counts(self):
self.assertTrue(declares(DRIVER[3], "naomi"))
def test_a_rom_start_is_not_a_machine_declaration(self):
self.assertFalse(declares(DRIVER[4], "soundbox"))
class TestAudit(unittest.TestCase):
def setUp(self):
self.tmp = tempfile.TemporaryDirectory()
self.dir = self.tmp.name
Path(self.dir, "p.yml").write_text(PROFILE, encoding="utf-8")
self._fetch = mame_ref_audit.upstream.fetch_file
mame_ref_audit.upstream.fetch_file = (
lambda repo, sha, path, cache, offline=False:
DRIVER if path.endswith("xavix.cpp") else ["ROM_START( soundbox )"]
)
def tearDown(self):
mame_ref_audit.upstream.fetch_file = self._fetch
self.tmp.cleanup()
def test_a_ref_pointing_elsewhere_is_reported_with_its_declaration(self):
findings, agreed, unjudged = mame_ref_audit.audit("p", self.dir, ".c", False)
self.assertEqual(agreed, 1, "ekarag cites its own line")
self.assertEqual([f.set_name for f in findings], ["ekara"])
self.assertEqual(findings[0].cited, 99)
self.assertEqual(findings[0].declared, 2)
def test_a_set_no_machine_declares_is_left_unjudged(self):
"""A device archive takes its DEFINE_DEVICE_TYPE shortname."""
_, _, unjudged = mame_ref_audit.audit("p", self.dir, ".c", False)
self.assertEqual(unjudged, 1)
def test_rewrite_moves_only_the_entry_that_owns_the_ref(self):
findings, _, _ = mame_ref_audit.audit("p", self.dir, ".c", False)
self.assertEqual(mame_ref_audit.rewrite("p", self.dir, findings), 1)
text = Path(self.dir, "p.yml").read_text(encoding="utf-8")
self.assertIn('source_ref: "src/mame/tvgames/xavix.cpp:2"', text)
self.assertIn(
'source_ref: "src/mame/tvgames/xavix.cpp:3"', text,
"ekarag's own ref must be untouched",
)
def test_a_corrected_profile_reports_nothing(self):
findings, _, _ = mame_ref_audit.audit("p", self.dir, ".c", False)
mame_ref_audit.rewrite("p", self.dir, findings)
again, agreed, _ = mame_ref_audit.audit("p", self.dir, ".c", False)
self.assertEqual(again, [])
self.assertEqual(agreed, 2)
class TestCorpusStaysCorrect(unittest.TestCase):
"""The committed profiles agree with their pinned drivers.
Offline, so it reads the fetch cache: skipped where that is cold rather
than turning a network absence into a failure.
"""
def test_every_mame_family_ref_names_its_own_set(self):
cache = ROOT / mame_ref_audit.upstream.CACHE_DIR
if not cache.is_dir():
self.skipTest("no upstream cache")
for name in ("mame", "mamearcade", "mamemess", "groovymame"):
with self.subTest(emulator=name):
findings, agreed, _ = mame_ref_audit.audit(
name, str(ROOT / "emulators"), str(cache), True
)
if not agreed and not findings:
self.skipTest(f"{name}: driver sources not cached")
self.assertEqual(
[f.set_name for f in findings], [],
f"{name} has refs that do not declare their own set",
)