mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-15 06:23:47 -06:00
chore: merge origin/main
This commit is contained in:
commit
6edb9fe691
72 files changed
+840
-52
No files matched your search
@@ -264,6 +264,78 @@ class CommittedData(unittest.TestCase):
|
||||
self.assertEqual(lcd.systems, [])
|
||||
|
||||
|
||||
# The cores the setups name that resolve to no profile, each with why. A
|
||||
# folder of one of these keeps the files of every core of its systems. ArkOS
|
||||
# ran the GBA with gpsp_ezode_mod, which resolved to nothing: the card got
|
||||
# the files of every GBA core, FBNeo's 3,472 data files among them.
|
||||
KNOWN_UNRESOLVED = {
|
||||
# Not an emulator: a frontend, a shell, a player, a launcher, a store.
|
||||
**dict.fromkeys(["crisp game lib", "exodos", "external", "ffplay", "flatpak", "gmloader",
|
||||
"heroic", "idtech", "libretro", "mplayer", "mreader landscape", "mugen",
|
||||
"native", "odcommander", "os-shell", "port", "portmaster", "ports",
|
||||
"powerbomberman", "quiverlauncher", "sh", "steam", "vaixterm", "wasabi",
|
||||
"windows", "wine", "wine-tkg"], "not an emulator"),
|
||||
# A launcher mode or an argument: the program depends on the folder.
|
||||
**dict.fromkeys(["standalone", "standalone-2021", "standalone-nobios",
|
||||
"standalone-pirry-nobios", "standalone-r7", "standalone-vulkan", "Normal",
|
||||
"coco3", "dragon32"], "launcher mode, the program depends on the folder"),
|
||||
# An emulator no profile documents yet.
|
||||
**dict.fromkeys(["exa", "gloopy", "gp32emu", "km_ludicrousn64_2k22_xtreme_amped",
|
||||
"libgametank", "ludicrousn64_xtreme32", "mametiger", "memu", "onscripter-sa",
|
||||
"ryubing", "zc250x"], "no profile yet"),
|
||||
# The program's profile declares no system of the folder, or the folder
|
||||
# has none: MAME documents no GameKing ROM.
|
||||
**dict.fromkeys(["gameking", "gamekin3", "ctvboy", "gaelco", "namco3xx"],
|
||||
"the program's profile lacks the system"),
|
||||
# Not settled: two builds by host, a binary the OS tree lacks, a fork
|
||||
# whose required files differ, a shell variable the scraper kept.
|
||||
**dict.fromkeys(["pcsx2-nogui", "zx81", "yabadabadoo", "reicast-audio-${backend}"],
|
||||
"not proven"),
|
||||
}
|
||||
|
||||
|
||||
class EveryCoreResolvesOrIsExplained(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
from common import load_emulator_profiles
|
||||
from romfolders import ProfileResolver
|
||||
|
||||
self.resolver = SystemResolver.from_repo(str(ROOT / "emulators"), str(ROOT / "platforms"))
|
||||
self.cores = ProfileResolver.from_repo(str(ROOT / "emulators"))
|
||||
self.profiles = gi.Profiles(load_emulator_profiles(str(ROOT / "emulators")), self.resolver)
|
||||
|
||||
def profile(self, row: dict, platform: str) -> str | None:
|
||||
return (self.cores.resolve(row.get("core"))
|
||||
or gi.emulator_profile(row, platform, self.cores, self.resolver, self.profiles))
|
||||
|
||||
def test_either_separator_resolves(self) -> None:
|
||||
self.assertEqual(self.cores.resolve("flycast_xtreme"), "flycast2021")
|
||||
|
||||
def test_a_mode_resolves_by_its_program_when_it_runs_the_system(self) -> None:
|
||||
hikaru = {"folder": "hikaru", "core": "hikaru", "emulator": "demul", "systems": ["sega-hikaru"]}
|
||||
self.assertEqual(self.profile(hikaru, "retrobat"), "demul")
|
||||
# MAME runs the GameKing, but its profile documents no GameKing ROM:
|
||||
# answering MAME would leave the ROM out.
|
||||
gameking = {"folder": "gameking", "core": "gameking", "emulator": "mame"}
|
||||
self.assertIsNone(self.profile(gameking, "amberelec"))
|
||||
launcher = {"folder": "doom", "core": "standalone", "emulator": "standalone"}
|
||||
self.assertIsNone(self.profile(launcher, "arkos"))
|
||||
|
||||
def test_no_core_is_left_unexplained(self) -> None:
|
||||
setups = load_setups(ROOT / "platforms" / "romfolders")
|
||||
if not setups:
|
||||
self.skipTest("no setup scraped")
|
||||
unexplained = sorted({
|
||||
str(row["core"]) for doc in setups.values() for row in doc["folders"]
|
||||
if row.get("core") and not self.profile(row, doc["platform"])
|
||||
and str(row["core"]) not in KNOWN_UNRESOLVED
|
||||
})
|
||||
self.assertEqual(unexplained, [], "map each to its profile (cores:) or record why it has none")
|
||||
# And no reason outlives its row: a core mapped since leaves the list.
|
||||
still = {str(row["core"]) for doc in setups.values() for row in doc["folders"]
|
||||
if row.get("core") and not self.profile(row, doc["platform"])}
|
||||
self.assertEqual(sorted(set(KNOWN_UNRESOLVED) - still), [])
|
||||
|
||||
|
||||
class OneNarrowingPerCoreList(unittest.TestCase):
|
||||
"""Each (platform, system, core) key narrowed the whole install list:
|
||||
2,357 narrowings for 1,289 distinct core lists."""
|
||||
|
||||
@@ -88,6 +88,46 @@ class TheSkillIsAnAgentSkill(unittest.TestCase):
|
||||
self.assertTrue(skill["url"].endswith(siteagents.SKILL_PATH))
|
||||
|
||||
|
||||
class EveryPageHasAMarkdownCopy(unittest.TestCase):
|
||||
"""An assistant reads a page's words, not its navigation: each page has
|
||||
its Markdown at <page>/index.md, which its head names."""
|
||||
|
||||
def test_the_head_names_the_copy_and_the_build_writes_it(self) -> None:
|
||||
config = CONFIG.read_text(encoding="utf-8")
|
||||
self.assertIn("rel: 'alternate', type: 'text/markdown', href: 'index.md'", config)
|
||||
self.assertIn("markdownCopies,", config)
|
||||
|
||||
def test_a_page_keeps_its_commands_under_their_system(self) -> None:
|
||||
import site_markdown # noqa: PLC0415
|
||||
|
||||
html = ('<html><body><main><h1 id="_top">Demo</h1><div class="sl-markdown-content">'
|
||||
'<p>Run it <a href="/retrobios/x/">here</a>.</p>'
|
||||
'<div role="tablist"><a role="tab" id="tab-0-0">Windows</a>'
|
||||
'<a role="tab" id="tab-0-1">Linux</a></div>'
|
||||
'<div role="tabpanel" aria-labelledby="tab-0-0"><pre><code>'
|
||||
'<div class="ec-line"><div class="code">irm x | iex</div></div></code></pre></div>'
|
||||
'<div role="tabpanel" aria-labelledby="tab-0-1"><pre><code>'
|
||||
'<div class="ec-line"><div class="code">curl x | sh</div></div></code></pre></div>'
|
||||
'<table><tr><th>File</th><th>MD5</th></tr><tr><td>a.bin</td><td>ff</td></tr></table>'
|
||||
'<button>Copy</button><span class="sr-only">hidden</span></div></main></body></html>')
|
||||
text = site_markdown.page_markdown(html, "https://abdess.github.io/retrobios/demo/")
|
||||
self.assertTrue(text.startswith("# Demo\n\nSource: https://abdess.github.io/retrobios/demo/"))
|
||||
self.assertIn("[here](https://abdess.github.io/retrobios/x/)", text)
|
||||
self.assertIn("**Windows:**\n\n```\nirm x | iex\n```", text)
|
||||
self.assertIn("**Linux:**\n\n```\ncurl x | sh\n```", text)
|
||||
self.assertIn("| File | MD5 |\n|---|---|\n| a.bin | ff |", text)
|
||||
self.assertNotIn("Copy", text)
|
||||
self.assertNotIn("hidden", text)
|
||||
|
||||
@unittest.skipUnless((DIST / "index.md").is_file(), "website/dist is not built")
|
||||
def test_the_built_site_has_them(self) -> None:
|
||||
pages = sorted(DIST.rglob("index.html"))
|
||||
missing = [p for p in pages if not (p.parent / "index.md").is_file()]
|
||||
self.assertEqual(missing, [])
|
||||
self.assertIn("# Get your files", (DIST / "which-pack" / "index.md").read_text(encoding="utf-8"))
|
||||
self.assertTrue((DIST / "llms-full.txt").is_file())
|
||||
|
||||
|
||||
class TheManifestIsAnArdManifest(unittest.TestCase):
|
||||
"""The terms ard-entry.schema.json requires (ards-project/ard-spec)."""
|
||||
|
||||
@@ -115,7 +155,7 @@ class TheToolsReadOnly(unittest.TestCase):
|
||||
self.assertIn("import '../scripts/agent-tools.ts';", FOOTER.read_text(encoding="utf-8"))
|
||||
names = re.findall(r"^\s*name: '([a-z_]+)'", self.source, re.M)
|
||||
self.assertEqual(names, ["lookup_bios_hash", "emulator_bios_files", "search_retrobios",
|
||||
"device_setup_command"])
|
||||
"setup_bios_files", "device_setup_command"])
|
||||
self.assertEqual(self.source.count("readOnlyHint: true"), len(names))
|
||||
|
||||
def test_the_setup_command_defaults_to_the_games(self) -> None:
|
||||
@@ -131,6 +171,10 @@ class TheToolsReadOnly(unittest.TestCase):
|
||||
self.assertIn("/^[a-z0-9_-]+$/.test(platform)", self.source)
|
||||
self.assertIn("`--dest=${quote(bios_folder as string)}`", self.source)
|
||||
|
||||
def test_setup_files_answer_from_the_picker_data(self) -> None:
|
||||
self.assertIn("json<PickerData>(`data/picker/${found.platform}.json`)", self.source)
|
||||
self.assertIn("Keep each name exactly as written.", self.source)
|
||||
|
||||
def test_they_reach_no_other_site(self) -> None:
|
||||
code = re.sub(r"^\s*//.*$", "", self.source, flags=re.M)
|
||||
self.assertEqual(set(re.findall(r"https://[\w.-]+", code)), {"https://abdess.github.io"})
|
||||
|
||||
@@ -73,12 +73,17 @@ class DeploySiteTriggers(unittest.TestCase):
|
||||
run = "\n".join(
|
||||
step.get("run", "") for job in workflow["jobs"].values() for step in job["steps"]
|
||||
)
|
||||
# The Astro build runs scripts of its own (site_markdown.py writes
|
||||
# each page's Markdown once the pages are built): they are the
|
||||
# build's entry points as much as a workflow step's.
|
||||
astro = (REPO_ROOT / "website" / "astro.config.mjs").read_text(encoding="utf-8")
|
||||
entry_points = sorted(
|
||||
{
|
||||
word.removeprefix("scripts/")
|
||||
for word in run.split()
|
||||
if word.startswith("scripts/") and word.endswith(".py")
|
||||
}
|
||||
| set(re.findall(r"\.\./scripts/([\w]+\.py)", astro))
|
||||
)
|
||||
self.assertIn("generate_site.py", entry_points)
|
||||
# The Starlight project is an input of its own build.
|
||||
|
||||
Reference in new issue
Block a user