mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-11 12:33:53 -06:00
The manifest names the cores that read a tree no platform system declares, every reader of a shared tree included. An install for the games of a card keeps such a tree only when its plan runs one of them: a SNES game on ArkOS (snes9x) no longer takes FBNeo's cheats and samples. A system no setup names a core for keeps every core's tree.
215 lines
9.0 KiB
Python
215 lines
9.0 KiB
Python
"""A data directory a core reads reaches every platform that runs the core.
|
|
|
|
The registry entries of the buildbot trees named RetroArch, Lakka and
|
|
RetroPie only, and a platform pack carried only the trees its own systems
|
|
declared. AmberELEC and EmuELEC run the blueMSX core, whose package copies
|
|
the .so alone: their packs filled the machine configs by name from the
|
|
cache, and the install lists left 192 of them out. A platform that runs a
|
|
reader now gets the tree, or the profile says its package installs it.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
|
|
|
|
import os
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
|
|
|
import common # noqa: E402
|
|
import generate_pack as builder # noqa: E402
|
|
from validation import deliverable, read_from_system_dir # noqa: E402
|
|
|
|
PROFILES = {
|
|
"demo": {
|
|
"emulator": "Demo",
|
|
"type": "libretro",
|
|
"systems": ["demo-system"],
|
|
"cores": ["demo"],
|
|
"pack_structure": {"libretro": "Demo"},
|
|
"data_directories": [
|
|
{"ref": "shared", "destination": "Sys"},
|
|
{"ref": "restricted"},
|
|
{"ref": "installed", "installed_on": ["plat"]},
|
|
{"ref": "beside", "load_from": "content_dir"},
|
|
],
|
|
},
|
|
"solo": {
|
|
"emulator": "Solo",
|
|
"type": "standalone",
|
|
"systems": ["demo-system"],
|
|
"cores": ["solo"],
|
|
"data_directories": [{"ref": "shared"}],
|
|
},
|
|
}
|
|
|
|
REGISTRY = {
|
|
"shared": {"local_cache": "data/shared"},
|
|
"restricted": {"local_cache": "data/restricted", "for_platforms": ["other"]},
|
|
"installed": {"local_cache": "data/installed"},
|
|
"beside": {"local_cache": "data/beside"},
|
|
}
|
|
|
|
CONFIG = {
|
|
"platform": "Plat",
|
|
"cores": ["demo", "solo"],
|
|
"standalone_cores": ["solo"],
|
|
"systems": {"demo-system": {"files": []}},
|
|
}
|
|
|
|
|
|
class CoreDataTreesTest(unittest.TestCase):
|
|
def trees(self, platform: str = "plat", registry: dict | None = None) -> list[dict]:
|
|
return builder.core_data_trees(
|
|
CONFIG, PROFILES, platform, REGISTRY if registry is None else registry
|
|
)
|
|
|
|
def test_tree_below_the_build_folder(self) -> None:
|
|
shared = [t for t in self.trees() if t["ref"] == "shared"]
|
|
self.assertEqual([(t["core"], t["destination"]) for t in shared], [("demo", "Demo/Sys")])
|
|
self.assertEqual(shared[0]["source_systems"], ["demo-system"])
|
|
|
|
def test_for_platforms_names_who_gets_it(self) -> None:
|
|
self.assertNotIn("restricted", {t["ref"] for t in self.trees()})
|
|
self.assertIn("restricted", {t["ref"] for t in self.trees("other")})
|
|
|
|
def test_installed_tree_stays_out(self) -> None:
|
|
self.assertNotIn("installed", {t["ref"] for t in self.trees()})
|
|
self.assertIn("installed", {t["ref"] for t in self.trees("other")})
|
|
|
|
def test_tree_read_beside_the_content_stays_out(self) -> None:
|
|
self.assertNotIn("beside", {t["ref"] for t in self.trees("other")})
|
|
|
|
def test_standalone_build_brings_no_tree(self) -> None:
|
|
self.assertNotIn("solo", {t["core"] for t in self.trees("other")})
|
|
|
|
def test_every_reader_of_a_shared_tree_is_recorded(self) -> None:
|
|
"""The second core reading a tree was dropped with the duplicate, and an
|
|
install for its games would have lost the tree."""
|
|
twin = {**PROFILES["demo"], "emulator": "Twin", "cores": ["twin"]}
|
|
profiles = {**PROFILES, "twin": twin}
|
|
config = {**CONFIG, "cores": ["demo", "solo", "twin"]}
|
|
trees = builder.core_data_trees(config, profiles, "plat", REGISTRY)
|
|
shared = [t for t in trees if t["ref"] == "shared"]
|
|
self.assertEqual(len(shared), 1)
|
|
self.assertEqual(shared[0]["readers"], ["demo", "twin"])
|
|
self.assertEqual(builder.tree_readers({}, trees)["shared"], ["demo", "twin"])
|
|
|
|
def test_a_tree_a_system_declares_names_no_core(self) -> None:
|
|
trees = self.trees()
|
|
declared = {"demo-system": {"data_directories": [{"ref": "shared"}]}}
|
|
self.assertNotIn("shared", builder.tree_readers(declared, trees))
|
|
self.assertIn("shared", builder.tree_readers({}, trees))
|
|
|
|
def test_tree_below_the_declared_bios_folder(self) -> None:
|
|
config = {
|
|
**CONFIG,
|
|
"base_destination": "",
|
|
"systems": {"demo-system": {"files": [{"name": "a.bin", "destination": "bios/a.bin"}]}},
|
|
}
|
|
trees = builder.core_data_trees(config, PROFILES, "plat", REGISTRY)
|
|
self.assertEqual(
|
|
[t["destination"] for t in trees if t["ref"] == "shared"], ["bios/Demo/Sys"]
|
|
)
|
|
|
|
def test_no_registry_no_tree(self) -> None:
|
|
self.assertEqual(builder.core_data_trees(CONFIG, PROFILES, "plat", None), [])
|
|
|
|
|
|
class EveryReaderHasTheTreeOrAReason(unittest.TestCase):
|
|
"""Reads the repository: platforms/_data_dirs.yml against the profiles."""
|
|
|
|
def test_for_platforms_leaves_no_reader_without_a_reason(self) -> None:
|
|
platforms_dir = str(REPO_ROOT / "platforms")
|
|
registry = common.load_data_dir_registry(platforms_dir)
|
|
profiles = common.load_emulator_profiles(str(REPO_ROOT / "emulators"))
|
|
unexplained = []
|
|
for platform in common.list_registered_platforms(platforms_dir):
|
|
config = common.load_platform_config(platform, platforms_dir)
|
|
handed = common.standalone_set(config)
|
|
for core in sorted(common.resolve_platform_cores(config, profiles)):
|
|
profile = profiles[core]
|
|
if all(standalone for _view, standalone
|
|
in common.platform_layouts(core, profile, handed)):
|
|
continue
|
|
trees = [t for t in profile.get("data_directories") or [] if isinstance(t, dict)]
|
|
installed = common.installed_data_refs(platform)
|
|
for tree in deliverable(trees, False, platform):
|
|
allowed = registry.get(tree.get("ref"), {}).get("for_platforms")
|
|
if tree.get("ref") in installed or not read_from_system_dir(tree):
|
|
continue
|
|
if allowed and platform not in allowed:
|
|
unexplained.append(f"{tree['ref']} on {platform} ({core})")
|
|
self.assertEqual(
|
|
unexplained, [],
|
|
"these platforms run a core that reads the tree, are not in its "
|
|
"for_platforms, and no profile says their package installs it "
|
|
"(installed_on) or that they never open it (unread_on)",
|
|
)
|
|
|
|
|
|
@unittest.skipUnless(
|
|
os.path.isdir(REPO_ROOT / "data" / "bluemsx"), "data/bluemsx is not cached"
|
|
)
|
|
class AmberelecCarriesTheMachines(unittest.TestCase):
|
|
"""AmberELEC's blueMSX package installs the core alone, so the pack and
|
|
the install list bring the Machines tree its BIOS list names."""
|
|
|
|
def test_machine_configs_come_with_the_tree(self) -> None:
|
|
platforms_dir = str(REPO_ROOT / "platforms")
|
|
cwd = os.getcwd()
|
|
os.chdir(REPO_ROOT)
|
|
try:
|
|
config = common.load_platform_config("amberelec", platforms_dir)
|
|
registry = common.load_data_dir_registry(platforms_dir)
|
|
profiles = common.load_emulator_profiles(str(REPO_ROOT / "emulators"))
|
|
trees = builder.core_data_trees(config, profiles, "amberelec", registry)
|
|
refs: dict = {}
|
|
members = dict(
|
|
(full, src) for src, full in builder._data_directory_members(
|
|
config.get("systems", {}), registry, "amberelec",
|
|
config.get("base_destination", ""), False, set(), set(), set(),
|
|
refs, core_trees=trees,
|
|
)
|
|
)
|
|
finally:
|
|
os.chdir(cwd)
|
|
# Below bios/, where the platform writes every destination.
|
|
self.assertIn("bios/Machines/COL - ColecoVision/config.ini", members)
|
|
self.assertEqual(
|
|
refs["bios/Machines/COL - ColecoVision/config.ini"][0], "bluemsx"
|
|
)
|
|
|
|
|
|
class TheCountLineKeepsTreesOutOfTheBaseline(unittest.TestCase):
|
|
"""MyMinUI declares no file, and its pack line read "6944 baseline": the
|
|
fbneo trees its cores read were counted as the platform's list."""
|
|
|
|
def test_a_platform_declaring_nothing_has_no_baseline(self) -> None:
|
|
import contextlib
|
|
import io
|
|
|
|
previous = os.getcwd()
|
|
os.chdir(REPO_ROOT)
|
|
self.addCleanup(os.chdir, previous)
|
|
db = common.load_database("database.json")
|
|
record = builder.PackRecord()
|
|
out = io.StringIO()
|
|
with contextlib.redirect_stdout(out):
|
|
builder.generate_pack(
|
|
"myminui", "platforms", db, "bios", "tmp", offline=True, record=record,
|
|
data_registry=common.load_data_dir_registry("platforms"),
|
|
)
|
|
line = next(l for l in out.getvalue().splitlines() if "files packed" in l)
|
|
self.assertIn("(0 baseline + ", line)
|
|
if record.trees:
|
|
self.assertIn(f"+ {len(record.trees)} in core data trees + ", line)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|