refactor: hoist test imports, rank pairs at module level

This commit is contained in:
Abdessamad Derraz committed 2026-10-06 06:38:35 +02:00
1 parent a5f3a5db25
commit 226a5df74a
22 files changed
+85 -110

No files matched your search

+4 -7
View File
@@ -546,13 +546,10 @@ class PipelineRegressions(unittest.TestCase):
argv = ["pipeline.py", "--offline", "--skip-packs", "--skip-docs",
"--with-export", "--target", "switch"]
with (
mock.patch.object(sys, "argv", argv),
mock.patch.object(pipeline, "run", side_effect=fake_run),
contextlib.redirect_stdout(io.StringIO()),
):
with contextlib.suppress(SystemExit):
pipeline.main()
with mock.patch.object(sys, "argv", argv), mock.patch.object(
pipeline, "run", side_effect=fake_run
), contextlib.redirect_stdout(io.StringIO()), contextlib.suppress(SystemExit):
pipeline.main()
truth_runs = [c for c in commands if "scripts/generate_truth.py" in c]
export = next(c for c in commands if "scripts/export_native.py" in c)
read_dir = export[export.index("--truth-dir") + 1]
+1 -2
View File
@@ -12,6 +12,7 @@ from __future__ import annotations
import sys
import unittest
from pathlib import Path
import yaml
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
@@ -43,8 +44,6 @@ class Companions(unittest.TestCase):
self.assertEqual([sha for sha, _ in found], ["a"])
def test_pcsx2_profiles_name_no_free_standing_companion(self):
import yaml
for name in ("pcsx2", "pcsx2-legacy"):
profile = yaml.safe_load((REPO_ROOT / "emulators" / f"{name}.yml").read_text())
names = {str(f.get("name", "")).lower() for f in profile.get("files", [])}
+1 -2
View File
@@ -15,12 +15,11 @@ import yaml
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from common import load_platform_config # noqa: E402
class CaseInsensitiveWhereTheFilesystemIs(unittest.TestCase):
def test_windows_and_macos_platforms_carry_the_flag(self):
from common import load_platform_config
registry = yaml.safe_load((REPO_ROOT / "platforms" / "_registry.yml").read_text())
for name, data in registry["platforms"].items():
systems = {str(d.get("os")) for d in (data.get("install") or {}).get("detect", [])}
+1 -8
View File
@@ -18,6 +18,7 @@ from unittest import mock
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
import generate_db # noqa: E402
class _NoCoreInfo:
@@ -27,8 +28,6 @@ class _NoCoreInfo:
class AliasesNeedAnUnambiguousName(unittest.TestCase):
def _aliases(self, files: dict) -> dict:
import generate_db
stub = types.ModuleType("scraper.coreinfo_scraper")
stub.Scraper = _NoCoreInfo
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
@@ -71,8 +70,6 @@ class NoNetworkInTheBuild(unittest.TestCase):
self.assertNotIn("urllib.request", source)
def test_hash_proven_entry_registers_its_own_name(self):
import generate_db
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
previous = os.getcwd()
os.chdir(tmp)
@@ -91,8 +88,6 @@ class NoNetworkInTheBuild(unittest.TestCase):
class AcceptedRevisionLists(unittest.TestCase):
def test_a_list_of_sha1_names_every_held_revision(self):
"""A profile accepting several revisions writes sha1 as a list."""
import generate_db
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
previous = os.getcwd()
os.chdir(tmp)
@@ -114,8 +109,6 @@ class AcceptedRevisionLists(unittest.TestCase):
class CrossNamingStaysInItsProfile(unittest.TestCase):
def test_an_alias_naming_a_sibling_entry_is_not_indexed(self):
"""dosbox-x aliases MT32_CONTROL.ROM and CM32L_CONTROL.ROM to each other."""
import generate_db
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
previous = os.getcwd()
os.chdir(tmp)
+2 -6
View File
@@ -22,6 +22,8 @@ from exporter.baseline import NativeFile, NativeSystem, build_native_model # no
from exporter.emudeck_exporter import Exporter as EmuDeck # noqa: E402
from exporter.retrobat_exporter import Exporter as RetroBat # noqa: E402
from exporter.retrodeck_exporter import Exporter as RetroDeck # noqa: E402
from exporter.recalbox_exporter import Exporter as Recalbox # noqa: E402
from exporter.retropie_exporter import Exporter as RetroPie # noqa: E402
A = "a" * 32
B = "b" * 32
@@ -171,16 +173,12 @@ class OneFileOneIdentity(unittest.TestCase):
class RecalboxKeepsItsOwnNotes(unittest.TestCase):
def test_no_profile_prose_reaches_a_note(self):
from exporter.recalbox_exporter import Exporter as Recalbox
fe = NativeFile("bios.bin", "bios.bin", "psx", platform={"md5": A},
truth={"md5": A, "note": "Loaded at libretro.c:120"})
self.assertNotIn("note=", Recalbox()._bios_element(fe, "psx"))
class RetroPieProposals(unittest.TestCase):
def test_required_is_read_for_the_package_core(self):
from exporter.retropie_exporter import Exporter as RetroPie
fe = NativeFile("scph5501.bin", "scph5501.bin", "psx",
truth={"required": True, "_required_by": ["beetle_psx"],
"_cores": ["beetle_psx", "pcsx_rearmed"]})
@@ -188,8 +186,6 @@ class RetroPieProposals(unittest.TestCase):
self.assertFalse(RetroPie._required_for(fe, "pcsx_rearmed"))
def test_a_list_of_alternatives_is_not_extended(self):
from exporter.retropie_exporter import Exporter as RetroPie
alternatives = "Copy the required BIOS file a.rom or b.rom to $biosdir"
enumeration = "Copy the required BIOS files a.rom and b.rom to $biosdir"
self.assertIsNone(RetroPie._insertion_point(alternatives))
+2 -3
View File
@@ -16,6 +16,8 @@ REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from common import PROFILE_IDENTITY_FIELDS # noqa: E402
from packextras import _collect_emulator_extras # noqa: E402
from verify import find_undeclared_files # noqa: E402
ENTRY = {
"name": "bios.rom",
@@ -29,9 +31,6 @@ ENTRY = {
class IdentityTravels(unittest.TestCase):
def test_report_and_extra_keep_every_identity_field(self):
from packextras import _collect_emulator_extras
from verify import find_undeclared_files
profile = {
"emulator": "NP2kai",
"type": "libretro",
+1 -2
View File
@@ -16,12 +16,11 @@ from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from generate_pack import verify_and_finalize_packs # noqa: E402
class FinalizeByExactName(unittest.TestCase):
def test_a_custom_pack_is_not_judged_as_the_platform_pack(self):
from generate_pack import verify_and_finalize_packs
previous = os.getcwd()
os.chdir(REPO_ROOT)
self.addCleanup(os.chdir, previous)
+3 -5
View File
@@ -9,7 +9,6 @@ the pack and the manifest while verify, comparing md5, called it OK.
from __future__ import annotations
import hashlib
import json
import os
import sys
import tempfile
@@ -21,6 +20,9 @@ import yaml
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from common import load_platform_config # noqa: E402
from generate_pack import generate_manifest, generate_pack # noqa: E402
from verify import verify_platform # noqa: E402
class FrontendDigestDecides(unittest.TestCase):
@@ -61,10 +63,6 @@ class FrontendDigestDecides(unittest.TestCase):
self.root = root
def test_pack_manifest_and_verify_agree(self):
from common import load_platform_config
from generate_pack import generate_manifest, generate_pack
from verify import verify_platform
os.chdir(self.root)
self.addCleanup(os.chdir, REPO_ROOT)
zip_path = generate_pack(
+2 -5
View File
@@ -12,6 +12,7 @@ import hashlib
import io
import json
import os
import shutil
import sys
import tempfile
import threading
@@ -24,6 +25,7 @@ sys.path.insert(0, str(REPO_ROOT / "scripts"))
import common # noqa: E402
import largefiles
import check_release_assets # noqa: E402
PAYLOAD_A = b"A" * (256 * 1024)
PAYLOAD_B = b"B" * (256 * 1024)
@@ -366,7 +368,6 @@ class ReleaseAssetNames(unittest.TestCase):
self.assertEqual(name, os.path.basename(registered_path))
def test_manifest_checker_and_fetcher_agree_on_a_path(self):
import check_release_assets
import generate_pack
expected = largefiles.asset_names(self.REGISTERED)
@@ -488,8 +489,6 @@ class DownloadFailuresAndRevisions(unittest.TestCase):
self.addCleanup(setattr, largefiles.urllib.request, "urlopen", self._urlopen)
def tearDown(self):
import shutil
shutil.rmtree(self.dir, ignore_errors=True)
def test_a_stalled_stream_leaves_no_scratch(self):
@@ -534,8 +533,6 @@ class GameDataHasOneDefinition(unittest.TestCase):
"""
def test_the_release_section_follows_the_composition_tier(self):
import check_release_assets
for path in (
"bios/Id Software/Doom 3/demo/demo00.pk4",
"bios/Valve/Half-Life/valve/pak0.pak",
+1
View File
@@ -45,6 +45,7 @@ class SuiteWithoutJsonschema(unittest.TestCase):
[sys.executable, "-c", HIDE_AND_RUN, *names],
cwd=REPO_ROOT,
capture_output=True,
check=False,
text=True,
timeout=600,
)
+3 -5
View File
@@ -10,6 +10,8 @@ from __future__ import annotations
import hashlib
import io
import json
import re
import sys
import tempfile
import unittest
@@ -18,12 +20,11 @@ from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from packverify import verify_pack # noqa: E402
class MembersMustBeKnown(unittest.TestCase):
def test_unknown_bytes_are_an_error_and_assembled_sets_pass(self):
from packverify import verify_pack
known = b"known rom" * 10
md5 = hashlib.md5(known).hexdigest()
inner = io.BytesIO()
@@ -46,9 +47,6 @@ class SchemaAcceptsEveryStatus(unittest.TestCase):
"""verified_members reached every pack manifest and the schema refused it."""
def test_each_status_packverify_writes_is_in_the_schema(self):
import json
import re
source = (REPO_ROOT / "scripts" / "packverify.py").read_text(encoding="utf-8")
written = set(re.findall(r'status = "([a-z_]+)"', source))
schema = json.loads(
+1 -2
View File
@@ -8,6 +8,7 @@ does not have, while the registry names the path.
from __future__ import annotations
import re
import sys
import unittest
from pathlib import Path
@@ -49,8 +50,6 @@ class GuidesPointAtTheReadPath(unittest.TestCase):
class GuidesNameShippedInstallers(unittest.TestCase):
def test_every_installer_named_exists(self):
"""RetroBat's guide sent users to an install.bat no release carries."""
import re
source = (REPO_ROOT / "scripts" / "packreadme.py").read_text(encoding="utf-8")
for name in set(re.findall(r"install\.(?:bat|ps1|sh|py)", source)):
with self.subTest(installer=name):
+7 -5
View File
@@ -23,6 +23,7 @@ REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
import refresh_data_dirs as rdd # noqa: E402
from generate_pack import _data_directory_members # noqa: E402
def _zip_bytes(files: dict[str, bytes]) -> bytes:
@@ -117,9 +118,8 @@ class RefreshConcurrency(unittest.TestCase):
class PackWalkHoldsTheCache(unittest.TestCase):
def test_a_refresh_waits_for_the_walk(self):
import fcntl
import fcntl # noqa: PLC0415
from generate_pack import _data_directory_members
with tempfile.TemporaryDirectory(dir=REPO_ROOT / "tmp") as tmp:
cache = Path(tmp) / "data" / "sdlpal"
@@ -130,9 +130,11 @@ class PackWalkHoldsTheCache(unittest.TestCase):
registry = {"sdlpal": {"local_cache": str(cache)}}
walk = _data_directory_members(systems, registry, "p", "", False, set(), set(), set())
next(walk)
with open(cache.with_name(".sdlpal.lock"), "a") as handle:
with self.assertRaises(BlockingIOError):
fcntl.flock(handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
with (
open(cache.with_name(".sdlpal.lock"), "a") as handle,
self.assertRaises(BlockingIOError),
):
fcntl.flock(handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
list(walk)
with open(cache.with_name(".sdlpal.lock"), "a") as handle:
fcntl.flock(handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
+1 -2
View File
@@ -14,12 +14,11 @@ from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from packextras import platform_region_groups # noqa: E402
class RequiredOnlyBeforeRegion(unittest.TestCase):
def test_optional_files_leave_the_groups(self):
from packextras import platform_region_groups
systems = {"vic20": {"files": [
{"name": "kernel-ntsc.bin", "destination": "Vic20/kernel-ntsc.bin", "required": True},
{"name": "kernel-japanese.bin", "destination": "Vic20/kernel-japanese.bin",
+1 -1
View File
@@ -24,7 +24,7 @@ class RequiredOnlyArchives(unittest.TestCase):
result = subprocess.run(
[sys.executable, "scripts/generate_pack.py", "--emulator", "geolith",
"--required-only", "--offline", "--output-dir", tmp],
capture_output=True, text=True, cwd=REPO_ROOT, timeout=600,
capture_output=True, check=False, text=True, cwd=REPO_ROOT, timeout=600,
)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
pack = next(Path(tmp).glob("*.zip"))
+1 -2
View File
@@ -12,6 +12,7 @@ from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
import slots # noqa: E402
from slots import Claim, Conflict, arbitrate, format_decision # noqa: E402
def _db(entries: dict[str, dict]) -> dict:
@@ -559,8 +560,6 @@ class StrongestProfileClaimWins(unittest.TestCase):
"""yaps2 pins GameIndex.yaml by sha1; armsx2 matched a path only."""
def test_hash_proof_beats_path_proof(self):
from slots import Claim, Conflict, arbitrate, format_decision
def claim(emu, path, status):
return Claim("profile", "pcsx2/resources/GameIndex.yaml", "GameIndex.yaml",
emulator=emu, local_path=path, status=status)
+13 -12
View File
@@ -8,6 +8,7 @@ packs built for it shrank without an error.
from __future__ import annotations
import json
import sys
import unittest
import urllib.error
@@ -35,10 +36,12 @@ class FailedRequestsStopTheScrape(unittest.TestCase):
retropie_targets_scraper,
retroarch_targets_scraper,
):
with self.subTest(scraper=module.__name__):
with mock.patch.object(module.urllib.request, "urlopen", _refuse):
with self.assertRaises(RuntimeError):
module.Scraper().fetch_targets()
with (
self.subTest(scraper=module.__name__),
mock.patch.object(module.urllib.request, "urlopen", _refuse),
self.assertRaises(RuntimeError),
):
module.Scraper().fetch_targets()
def test_an_empty_listing_is_not_a_target(self):
class _Empty:
@@ -52,12 +55,12 @@ class FailedRequestsStopTheScrape(unittest.TestCase):
return b"[]"
for module in (emudeck_targets_scraper, retropie_targets_scraper):
with self.subTest(scraper=module.__name__):
with mock.patch.object(
module.urllib.request, "urlopen", lambda *a, **k: _Empty()
):
with self.assertRaises(RuntimeError):
module.Scraper().fetch_targets()
with (
self.subTest(scraper=module.__name__),
mock.patch.object(module.urllib.request, "urlopen", lambda *_a, **_k: _Empty()),
self.assertRaises(RuntimeError),
):
module.Scraper().fetch_targets()
@@ -101,8 +104,6 @@ class RetroPieModuleFlags(unittest.TestCase):
}
def fake_fetch(url, accept="text/plain"):
import json
section = url.rstrip("/").rsplit("/", 1)[-1]
if section in listings:
return json.dumps(listings[section])
+5 -15
View File
@@ -10,14 +10,16 @@ discrepancy that does not exist. Content decides, as everywhere else here.
from __future__ import annotations
import pathlib
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO_ROOT / "scripts"))
from truth import _match_renames # noqa: E402
from truth import _diff_system, _match_renames, _merge_file_into_system # noqa: E402
def _entry(name: str, **hashes) -> dict:
@@ -33,16 +35,13 @@ class ATargetedModelIsItsOwnArtifact(unittest.TestCase):
"""
def test_a_target_writes_beside_the_full_model(self):
import subprocess
import tempfile
repo = pathlib.Path(__file__).resolve().parent.parent
with tempfile.TemporaryDirectory(dir=str(repo / "tmp")) as directory:
for extra in ([], ["--target", "browser"]):
proc = subprocess.run(
[sys.executable, "scripts/generate_truth.py", "--platform",
"romm", *extra, "--output-dir", directory],
capture_output=True, text=True, cwd=str(repo), timeout=400,
capture_output=True, check=False, text=True, cwd=str(repo), timeout=400,
)
self.assertEqual(proc.returncode, 0, proc.stdout + proc.stderr)
produced = sorted(
@@ -60,16 +59,13 @@ class ADiffThatComparedNothingFails(unittest.TestCase):
"""diff_truth --all skipped every platform without a model and exited 0."""
def test_an_empty_truth_directory_is_an_error(self):
import subprocess
import tempfile
repo = pathlib.Path(__file__).resolve().parent.parent
with tempfile.TemporaryDirectory(dir=str(repo / "tmp")) as directory:
for selection in (["--all"], ["--platform", "retroarch"]):
proc = subprocess.run(
[sys.executable, "scripts/diff_truth.py", *selection,
"--truth-dir", directory, "--json"],
capture_output=True, text=True, cwd=str(repo), timeout=120,
capture_output=True, check=False, text=True, cwd=str(repo), timeout=120,
)
self.assertEqual(proc.returncode, 1, selection)
self.assertIn("skip", proc.stderr)
@@ -81,8 +77,6 @@ class OneNameSeveralFiles(unittest.TestCase):
REGIONS = {"USA": "a" * 32, "EUR": "b" * 32, "JAP": "c" * 32}
def _system(self) -> dict:
from truth import _merge_file_into_system
system: dict = {}
for core in ("dolphin", "ishiiruka"):
for region, md5 in self.REGIONS.items():
@@ -105,8 +99,6 @@ class OneNameSeveralFiles(unittest.TestCase):
self.assertEqual(entry["_cores"] - {"other"}, {"dolphin", "ishiiruka"})
def test_revisions_under_one_name_and_no_path_stay_one_file(self):
from truth import _merge_file_into_system
system: dict = {}
for md5 in ("a" * 32, "b" * 32):
_merge_file_into_system(
@@ -115,8 +107,6 @@ class OneNameSeveralFiles(unittest.TestCase):
self.assertEqual(len(system["files"]), 1)
def test_the_diff_pairs_each_by_destination(self):
from truth import _diff_system
scraped = {"files": [
{"name": "IPL.bin", "destination": f"dolphin-emu/Sys/GC/{region}/IPL.bin",
"md5": md5}
+1 -1
View File
@@ -12,7 +12,7 @@ REPO_ROOT = Path(__file__).resolve().parents[1]
def _run(*argv: str) -> subprocess.CompletedProcess:
return subprocess.run(
[sys.executable, *argv], capture_output=True, text=True, cwd=REPO_ROOT, timeout=300
[sys.executable, *argv], capture_output=True, check=False, text=True, cwd=REPO_ROOT, timeout=300
)