chore: merge round 4 fixes (profiles)

This commit is contained in:
Abdessamad Derraz committed 2026-10-21 13:17:10 +02:00
commit 43fe5a7b15
15 files changed
+354 -29

No files matched your search

+38
View File
@@ -153,5 +153,43 @@ class AnUnreadableSourceStopsTheRun(unittest.TestCase):
self.assertIn("broken.yml", str(caught.exception))
class DrasticNamesTheDSDumps(unittest.TestCase):
"""DraStic opens nds_bios_arm9.bin, nds_bios_arm7.bin and nds_firmware.bin
and checks their size only. Its profile listed nine other names none of
its binaries contains, which were the only way the collection answered
its own three names."""
def _aliases(self, files: dict) -> dict:
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
previous = os.getcwd()
os.chdir(tmp)
try:
Path("emulators").mkdir()
return generate_db._collect_all_aliases(files)
finally:
os.chdir(previous)
def test_the_collection_answers_drastic_names(self):
files = {
"a9": {"name": "NDS_Bios9.bin", "path": "bios/Nintendo/DS/NDS_Bios9.bin", "md5": "m9"},
"a7": {"name": "NDS_Bios7.bin", "path": "bios/Nintendo/DS/NDS_Bios7.bin", "md5": "m7"},
"fw": {"name": "NDS_Lite_Firmware.bin",
"path": "bios/Nintendo/DS/NDS_Lite_Firmware.bin", "md5": "mf"},
}
aliases = self._aliases(files)
named = {sha: {a["name"] for a in entries} for sha, entries in aliases.items()}
self.assertIn("nds_bios_arm9.bin", named["a9"])
self.assertIn("nds_bios_arm7.bin", named["a7"])
self.assertIn("nds_firmware.bin", named["fw"])
def test_the_profile_carries_no_name_drastic_never_opens(self):
import yaml
profile = yaml.safe_load((REPO_ROOT / "emulators" / "drastic.yml").read_text())
self.assertEqual(
[e["name"] for e in profile["files"] if e.get("aliases")], [],
)
if __name__ == "__main__":
unittest.main()
+44
View File
@@ -250,6 +250,50 @@ class LauncherLayerTest(unittest.TestCase):
self.assertNotIn("core.bin", {u["name"] for u in self._report()})
self.assertNotIn("core.bin", self._pack_names())
def test_the_default_name_a_launcher_replaces_is_not_packed(self) -> None:
"""EmuDeck passes Complex_4627v1.03.bin to xemu, which then never
opens Complex_4627.bin: the pack carried both, one read by nobody."""
report = {u["path"]: u for u in self._report()}
self.assertIn("sub/fix.bin", report)
self.assertNotIn("core.bin", report)
self.assertNotIn("core.bin", self._pack_names())
def test_a_link_of_a_named_file_is_a_place(self) -> None:
"""ROCKNIX links /storage/roms/bios/nds_bios_arm9.bin into DraStic's
system folder (start_drastic.sh:37-41): the file goes where the
link reads it, not under the emulator's own folder."""
self.config["launchers"][2].update(
kind="links", names=["fix.bin"], search_dir="/storage/roms/bios",
)
places = [p for p in launcher_places(self.config) if p.kind == "links"]
self.assertEqual([p.paths for p in places], [("fix.bin",)])
self.assertTrue(places[0].stands_for_default)
report = {u["path"]: u for u in self._report()}
self.assertIn("fix.bin", report)
self.assertNotIn("core.bin", report)
def test_a_link_of_a_directory_is_no_place(self) -> None:
self.config["launchers"][2].update(
kind="links", names=[], search_dir="/userdata/bios/sub",
)
self.assertFalse([p for p in launcher_places(self.config) if p.kind == "links"])
def test_the_platform_spelling_of_the_bios_folder_is_a_root(self) -> None:
"""RetroPie names $biosdir, EmuDeck ${biosPath}, RetroDECK $bios_path:
read as no folder at all, every place of those platforms was dropped."""
for spelling in ("$biosdir", "${biosPath}", "$bios_path", "$HOME/RetroPie/bios"):
self.config["launchers"][2]["search_dir"] = f"{spelling}/sub"
with self.subTest(spelling=spelling):
self.assertEqual(launcher_places(self.config)[2].paths, ("sub/sub/fix.bin",))
def test_every_extractor_spelling_of_the_bios_folder_is_known(self) -> None:
import launchers
from scraper import emudeck_launchers, retrodeck_launchers, retropie_launchers
for token in (emudeck_launchers.BIOS, retrodeck_launchers.BIOS,
retropie_launchers.BIOSDIR):
self.assertIn(token, launchers.BIOS_ROOT_TOKENS)
def test_no_place_is_filled_twice(self) -> None:
added = [u["path"] for u in self._report() if u.get("launcher")]
self.assertEqual(sorted(added), ["e.bin", "sub/fix.bin"])
+41
View File
@@ -269,6 +269,47 @@ class CommandLines(unittest.TestCase):
rl.extract_launchers(files)
DRASTIC = module("drastic", """
function configure_drastic() {
mkRomDir "nds"
addEmulator 1 "$md_id" "nds" "$md_inst/drastic.sh %ROM%"
addSystem "nds"
[[ "$md_mode" == "remove" ]] && return
isPlatform "kms" && ! isPlatform "x11" && setBackend "$md_id" "x11"
cat > "$md_inst/drastic.sh" << _EOF_
#!/bin/bash
pushd "$md_conf_root/nds/drastic"
$md_inst/drastic "\\$1"
popd
_EOF_
chmod +x "$md_inst/drastic.sh"
}
""", 36)
class WorkingDirectory(unittest.TestCase):
def test_drastic_reads_below_the_folder_its_script_enters(self):
found = records({f"{EMULATORS}/drastic.sh": DRASTIC}, "drastic")
entered = [r for r in found if r["kind"] == "passes_path"]
self.assertEqual(
[(r["search_dir"], r["passes_to"], r["source_ref"]) for r in entered],
[(
"$md_conf_root/nds/drastic",
"working directory of $md_inst/drastic.sh",
f"{EMULATORS}/drastic.sh:48",
)],
)
def test_a_launch_script_that_no_longer_enters_a_folder_raises(self):
files = {f"{EMULATORS}/drastic.sh": DRASTIC.replace('pushd "', 'echo "')}
with self.assertRaises(rl.LauncherPatternMissing):
rl.extract_launchers(files)
class LaunchScripts(unittest.TestCase):
def test_fs_uae_refuses_to_start_without_kick13(self):
files = {f"{EMULATORS}/fs-uae.sh": FS_UAE, f"{EMULATORS}/fs-uae/fs-uae.sh": FS_UAE_LAUNCHER}
+32
View File
@@ -1347,5 +1347,37 @@ class ARefusedRegionalFileHoldsNoSlot(unittest.TestCase):
self.assertIn("rg_jp.bin", report["pack_destinations"])
class YmirLibretroRegions(unittest.TestCase):
"""ymir's libretro port gives sega_101.bin the Japan region and
mpr-17933.bin US_EU (apps/ymir-libretro/src/libretro.cpp:596-606) and
loads the candidate a region asks for (627-648, 1290-1306). One entry for
all three names put no region on any of them."""
def test_each_name_carries_the_region_the_port_gives_it(self):
import yaml
profile = yaml.safe_load(
(Path(__file__).resolve().parents[1] / "emulators" / "ymir.yml").read_text()
)
libretro = {
entry["name"]: entry for entry in profile["files"]
if entry.get("mode") == "libretro"
and entry["name"] in ("sega_101.bin", "mpr-17933.bin", "saturn_bios.bin")
}
self.assertEqual(sorted(libretro), ["mpr-17933.bin", "saturn_bios.bin", "sega_101.bin"])
self.assertEqual(libretro["sega_101.bin"]["region"], ["japan"])
self.assertTrue(
{"north-america", "europe"} <= set(libretro["mpr-17933.bin"]["region"])
)
self.assertNotIn("japan", libretro["mpr-17933.bin"]["region"])
self.assertNotIn("region", libretro["saturn_bios.bin"])
self.assertEqual(
[libretro[n]["priority"] for n in ("sega_101.bin", "mpr-17933.bin", "saturn_bios.bin")],
[1, 2, 3],
)
self.assertFalse(any(e.get("aliases") for e in profile["files"]
if e["name"] == "sega_101.bin"))
if __name__ == "__main__":
unittest.main()
+49
View File
@@ -0,0 +1,49 @@
"""Sega ROMs live under bios/Sega.
The SF-7000 disk unit ROM, which only the sega-sf7000 entries read, sat in
bios/Microsoft/MSX because blueMSX keeps its machine folders together. The
collection files a dump under the maker of the machine it belongs to, and
the blueMSX layout is a destination the pack writes, not a storage rule.
Reads the repository.
"""
from __future__ import annotations
import sys
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
class SegaFilesStayUnderSega(unittest.TestCase):
def test_no_sega_only_file_under_msx(self):
folder = REPO_ROOT / "bios" / "Microsoft" / "MSX"
if not folder.is_dir():
self.skipTest("bios/Microsoft/MSX is absent")
from common import load_emulator_profiles
systems: dict[str, set[str]] = {}
for profile in load_emulator_profiles(str(REPO_ROOT / "emulators")).values():
for entry in profile.get("files") or []:
if not isinstance(entry, dict) or not entry.get("system"):
continue
for name in [entry.get("name", ""), *(entry.get("aliases") or [])]:
key = Path(str(name)).name.lower()
systems.setdefault(key, set()).add(str(entry["system"]))
misfiled = sorted(
str(path.relative_to(folder))
for path in folder.rglob("*")
if path.is_file()
and systems.get(path.name.lower())
and all(s.startswith("sega-") for s in systems[path.name.lower()])
)
self.assertEqual(misfiled, [])
def test_sf7000_rom_is_filed_under_sega(self):
self.assertTrue((REPO_ROOT / "bios" / "Sega" / "SF-7000" / "sf7000.rom").is_file())
if __name__ == "__main__":
unittest.main()