chore: merge tooling follow-up

# Conflicts:
#	tests/test_audit_regressions.py
This commit is contained in:
Abdessamad Derraz committed 2026-10-21 06:50:20 +02:00
commit 6c2204a7a8
27 files changed
+618 -84

No files matched your search

+85
View File
@@ -129,5 +129,90 @@ class TheNativeIndexKeepsEveryPlatform(unittest.TestCase):
self.assertEqual(recorded.get("batocera/file"), "https://a")
self.assertEqual((root / "batocera" / "file").read_bytes(), b"payload")
class ScratchFilesGetThePlainMode(unittest.TestCase):
"""mkstemp makes its file 0600 and the rename kept it: database.json,
the manifests and the packs came out readable by their owner only."""
def setUp(self):
self._tmp = tempfile.TemporaryDirectory()
self.addCleanup(self._tmp.cleanup)
self.dir = Path(self._tmp.name)
previous = os.umask(0o022)
self.addCleanup(os.umask, previous)
def _mode(self, path: Path) -> int:
return path.stat().st_mode & 0o777
def test_text_and_bytes_writers(self):
artifacts.write_text_atomic(str(self.dir / "a.json"), "{}")
artifacts.write_bytes_atomic(str(self.dir / "b.bin"), b"x")
self.assertEqual(self._mode(self.dir / "a.json"), 0o644)
self.assertEqual(self._mode(self.dir / "b.bin"), 0o644)
def test_the_umask_decides(self):
os.umask(0o002)
artifacts.write_text_atomic(str(self.dir / "a.json"), "{}")
self.assertEqual(self._mode(self.dir / "a.json"), 0o664)
def test_packs_and_their_manifest(self):
import zipfile # noqa: PLC0415
import generate_pack # noqa: PLC0415
pack = self.dir / "Pack.zip"
with generate_pack._writing_pack(str(pack)) as zf:
zf.writestr("a.bin", b"x")
self.assertEqual(self._mode(pack), 0o644)
os.chmod(pack, 0o600)
generate_pack.inject_manifest(str(pack), {"files": []})
self.assertEqual(self._mode(pack), 0o644)
with zipfile.ZipFile(pack) as zf:
self.assertIn("manifest.json", zf.namelist())
def test_every_renamed_scratch_gets_the_mode(self):
"""A function that renames a mkstemp file into place sets its mode.
copy_file_atomic is the one exception: copy2 gives the scratch the
source file's own mode.
"""
import ast # noqa: PLC0415
def name_of(node: ast.AST) -> str | None:
return node.id if isinstance(node, ast.Name) else None
def callee(call: ast.Call) -> str:
func = call.func
return func.attr if isinstance(func, ast.Attribute) else name_of(func) or ""
unset = []
for path in sorted((REPO_ROOT / "scripts").rglob("*.py")):
tree = ast.parse(path.read_text(encoding="utf-8"))
for func in ast.walk(tree):
if not isinstance(func, (ast.FunctionDef, ast.AsyncFunctionDef)):
continue
if func.name == "copy_file_atomic":
continue
scratches: set[str] = set()
for node in ast.walk(func):
if (isinstance(node, ast.Assign) and isinstance(node.value, ast.Call)
and callee(node.value) == "mkstemp"
and isinstance(node.targets[0], ast.Tuple)):
scratch = name_of(node.targets[0].elts[1])
if scratch:
scratches.add(scratch)
calls = [n for n in ast.walk(func) if isinstance(n, ast.Call)]
moded = {
name_of(c.args[0]) for c in calls
if callee(c) in ("set_plain_mode", "chmod") and c.args
}
for call in calls:
if callee(call) != "replace" or not call.args:
continue
first = name_of(call.args[0])
if first in scratches and first not in moded:
unset.append(f"{path.name}:{call.lineno} {func.name}")
self.assertEqual(unset, [])
if __name__ == "__main__":
unittest.main()
+33 -1
View File
@@ -276,7 +276,7 @@ class WorkflowRegressions(unittest.TestCase):
self.assertTrue(runs, "no job confronts profiles with their upstream")
for name, body in runs:
self.assertIn("--strict", body)
self.assertIn("--diff-filter=A", body)
self.assertIn("--added", body)
self.assertIsNone(workflow["jobs"][name].get("if"), f"{name} must run on push too")
def test_both_events_watch_the_same_paths(self):
@@ -6147,6 +6147,7 @@ class SkipPacksHelpSaysWhatRuns(unittest.TestCase):
self.assertEqual(skipped, {"4", "4b", "4c", "6"})
<<<<<<< HEAD
class AmigaCdDriversLiveInTheExtendedRom(unittest.TestCase):
"""WinUAE starts without the CD32 or CDTV extended ROM, but cd.device,
cdtv.device, cdfs.library and cdstrap are resident modules of those ROMs
@@ -6185,5 +6186,36 @@ class BizHawkListsEveryDsiNandSlot(unittest.TestCase):
self.assertNotIn("sha1", entry)
||||||| 1a41e6a9
=======
class CommentsSayWhy(unittest.TestCase):
"""A one-line comment that names the next statement ("# Load registry",
"# Build cross-reference indexes") repeats the code. A comment that
stays says why (for, only, so, because)."""
LABEL = re.compile(
r"^\s*# (Load|Build|Collect|Determine|Resolve|Group|Copy|Count|Append|"
r"Filter|Separate|Compute|Create|Get|Check|Generate|Write|Read|Parse|Sort)"
r"\b[^.:;,()]{0,60}$"
)
REASON = re.compile(r"\b(for|only|so|because|if|when|unless|before|after)\b")
def test_no_label_comment_restates_the_next_line(self):
found = []
for name in ("verify.py", "generate_site.py", "generate_truth.py"):
lines = (ROOT / "scripts" / name).read_text(encoding="utf-8").splitlines()
for index, line in enumerate(lines):
if not self.LABEL.match(line) or self.REASON.search(line):
continue
around = (lines[index - 1].strip(), lines[index + 1].strip())
if any(neighbour.startswith("#") for neighbour in around):
continue
if not line.startswith(" "):
continue
found.append(f"{name}:{index + 1}: {line.strip()}")
self.assertEqual(found, [])
>>>>>>> worktree-agent-acbb69a80d49db676
if __name__ == "__main__":
unittest.main()
+18
View File
@@ -388,6 +388,24 @@ class ProfileSummaryTests(unittest.TestCase):
self.assertNotIn("a", by_subject)
self.assertNotIn("b", by_subject)
def test_profile_sync_accepts_the_command_it_is_given(self):
"""--json with the detection flags was refused, so --profiles read an
empty stdout and reported "unreadable report" on every run."""
import profile_sync # noqa: PLC0415
captured = []
def run(cmd, **kwargs):
captured.append(cmd)
return mock.Mock(returncode=0, stdout="[]", stderr="")
with mock.patch.object(cf.subprocess, "run", side_effect=run):
cf.check_profiles(True, offline=True)
(cmd,) = captured
args = profile_sync.build_parser().parse_args(cmd[2:])
profile_sync._refuse_flag_combinations(args)
self.assertTrue(args.as_json)
def test_a_non_list_report_is_an_error_not_a_crash(self):
findings = cf.summarize_profile_sync({"oops": 1})
self.assertEqual(findings[0].status, cf.ERROR)
+12
View File
@@ -70,6 +70,18 @@ class BeforeOpeningAPullRequest(unittest.TestCase):
workflow = (REPO_ROOT / ".github" / "workflows" / "validate.yml").read_text(encoding="utf-8")
self.assertIn("validate_schemas.py --source-only", workflow)
def test_it_installs_the_packages_the_site_render_needs(self):
"""Without mkdocs-material and pymdown-extensions the pipeline's
render step (8b) is skipped for every contributor."""
deploy = (REPO_ROOT / ".github" / "workflows" / "deploy-site.yml").read_text(
encoding="utf-8"
)
specs = re.findall(r'"((?:mkdocs-material|pymdown-extensions)[^"]*)"', deploy)
self.assertEqual(len(specs), 2)
text = generate_readme.generate_contributing()
for spec in specs:
self.assertIn(f'"{spec}"', text)
if __name__ == "__main__":
unittest.main()
+15
View File
@@ -272,5 +272,20 @@ class ContributorChecksMatchCi(unittest.TestCase):
)
class PagesOpenOnTheirContent(unittest.TestCase):
"""The download page said "This page picks the right pack for a setup"
before saying anything about a pack."""
def test_no_paragraph_announces_its_page(self):
import generate_site # noqa: PLC0415
text = generate_site.generate_which_pack()
announcing = [
line for line in text.splitlines()
if re.match(r"(This|The) (page|section) ", line)
]
self.assertEqual(announcing, [])
if __name__ == "__main__":
unittest.main()
+111 -3
View File
@@ -1163,6 +1163,13 @@ class TestBuildReport(unittest.TestCase):
profile_sync.upstream._http_json,
profile_sync.upstream._http_text,
profile_sync.upstream.list_gitlinks,
profile_sync.upstream.current_slug,
)
self.current_slugs: dict[str, str] = {}
profile_sync.upstream.current_slug = (
lambda repo, cache_dir, offline=False: self.current_slugs.get(
repo.slug, repo.slug
)
)
self.tags: list[str] = []
self.gitlinks: dict[str, dict[str, str]] = {}
@@ -1218,6 +1225,7 @@ class TestBuildReport(unittest.TestCase):
profile_sync.upstream._http_json,
profile_sync.upstream._http_text,
profile_sync.upstream.list_gitlinks,
profile_sync.upstream.current_slug,
) = self._orig
self.tmp.cleanup()
@@ -1232,6 +1240,25 @@ class TestBuildReport(unittest.TestCase):
],
}
def test_a_renamed_repository_is_review_work(self):
"""AloysHF/NicaiEmu answers as AloysHF/CoolbarEmu: the redirect was
followed in silence and the profile read as up to date."""
self.files[("pinsha", "a.c")] = ["x", "y"]
self.files[("headsha", "a.c")] = ["x", "y"]
self.current_slugs["o/n"] = "o/renamed"
report = build_report("test", self._profile(["a.c:2"]), self.dir)
self.assertEqual(len(report.moved_repos), 1)
self.assertIn("o/renamed", report.moved_repos[0])
self.assertGreaterEqual(report.needs_review(), 1)
self.assertIn("moved repository", profile_sync.format_report(report))
def test_a_repository_under_its_own_name_is_not_moved(self):
self.files[("pinsha", "a.c")] = ["x", "y"]
self.files[("headsha", "a.c")] = ["x", "y"]
self.current_slugs["o/n"] = "O/N"
report = build_report("test", self._profile(["a.c:2"]), self.dir)
self.assertEqual(report.moved_repos, [])
def test_a_refusing_forge_reads_as_unread_not_gone(self):
"""git.eden-emu.dev answers 403 to scripts: the muted repository's
citations read "absent at HEAD" for files that exist."""
@@ -4047,7 +4074,20 @@ class TestOutputModesApplyTheirFlags(unittest.TestCase):
self.assertIn("prose under an older pin", out)
def test_extras_are_refused_with_json(self):
code, _, err = self._main("--json", "--check-version")
code, _, err = self._main("--json", "--detect-new-files")
self.assertEqual(code, 1)
self.assertIn("--detect-new-files", err)
def test_json_carries_the_version_check(self):
"""check_freshness asks for --json --check-version: refused, its
profile row read an empty report as unreadable on every run."""
code, out, err = self._main("--json", "--check-version")
self.assertEqual(code, 0, err)
rows = json.loads(out)
self.assertTrue(all("version" in row and "page_version" in row for row in rows))
def test_rankings_refuse_the_version_check(self):
code, _, err = self._main("--triage", "--check-version")
self.assertEqual(code, 1)
self.assertIn("--check-version", err)
@@ -4246,8 +4286,9 @@ class TestSelectionNamesWhatMatchedNothing(unittest.TestCase):
}
def _args(self, **values):
base = {"emulator": None, "system": None, "type_": None,
"stale_before": None, "limit": None}
base = {"emulator": None, "changed": False, "added": False,
"system": None, "type_": None, "stale_before": None,
"limit": None}
return argparse.Namespace(**{**base, **values})
def test_a_misspelt_system_stops_and_suggests(self):
@@ -4595,5 +4636,72 @@ class TheTriageCountsWhatBlocksThePin(unittest.TestCase):
self.assertEqual(len(err.getvalue().splitlines()), 1, err.getvalue())
class TestBranchProfiles(unittest.TestCase):
"""--changed and --added name the profiles a branch brings, not by hand."""
def setUp(self):
self._tmp = tempfile.TemporaryDirectory()
self.addCleanup(self._tmp.cleanup)
self.root = Path(self._tmp.name)
self._cwd = os.getcwd()
self.addCleanup(os.chdir, self._cwd)
os.chdir(self.root)
env = {**os.environ, "GIT_AUTHOR_NAME": "t", "GIT_AUTHOR_EMAIL": "t@t",
"GIT_COMMITTER_NAME": "t", "GIT_COMMITTER_EMAIL": "t@t"}
self.env = env
self._git("init", "-q", "-b", "main")
(self.root / "emulators").mkdir()
(self.root / "emulators" / "kept.yml").write_text("a: 1\n")
(self.root / "emulators" / "edited.yml").write_text("a: 1\n")
self._git("add", "emulators")
self._git("commit", "-q", "--no-verify", "-m", "base")
self._git("checkout", "-q", "-b", "topic")
(self.root / "emulators" / "edited.yml").write_text("a: 2\n")
(self.root / "emulators" / "new.yml").write_text("a: 1\n")
self._git("add", "emulators")
self._git("commit", "-q", "--no-verify", "-m", "topic")
(self.root / "emulators" / "draft.yml").write_text("a: 1\n")
(self.root / "emulators" / "notes.txt").write_text("x\n")
def _git(self, *args):
subprocess.run(["git", *args], cwd=self.root, env=self.env, check=True)
def test_changed_takes_added_edited_and_uncommitted(self):
self.assertEqual(
profile_sync.branch_profiles("emulators", "main", added_only=False),
["draft", "edited", "new"],
)
def test_added_leaves_edited_profiles_out(self):
self.assertEqual(
profile_sync.branch_profiles("emulators", "main", added_only=True),
["draft", "new"],
)
def test_the_flag_selects_those_profiles(self):
args = profile_sync.build_parser().parse_args(["--changed", "--base", "main"])
profiles = {"kept": {}, "edited": {}, "new": {}, "draft": {}}
self.assertEqual(
list(profile_sync.select_profiles(profiles, args)),
["draft", "edited", "new"],
)
class TestBranchCheckIsWired(unittest.TestCase):
"""CONTRIBUTING and CI name the branch's profiles through the flag."""
def test_contributing_and_ci_use_the_flags(self):
root = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(root / "scripts"))
import generate_readme # noqa: PLC0415
text = generate_readme.generate_contributing()
self.assertIn("profile_sync.py --changed --strict", text)
self.assertNotIn("--emulator NAME --strict", text)
workflow = (root / ".github" / "workflows" / "validate.yml").read_text()
self.assertIn("profile_sync.py --added --base", workflow)
self.assertNotIn('--emulator "$name"', workflow)
if __name__ == "__main__":
unittest.main()
+64
View File
@@ -227,6 +227,70 @@ class PlatformMultiHash(unittest.TestCase):
self.assertEqual(pair_entries(truth, list(scraped.values())), {0: 0})
class ACompositeZipMd5IsNoContainerMd5(unittest.TestCase):
"""Recalbox hashes a .zip by its members. Its neocdz.zip md5 was set
against geolith's container md5 and reported as a mismatch the export,
which reads the same mark, never corrects."""
TRUTH = {"files": [{"name": "neocdz.zip", "md5": "b31a246b69493c35194fe0bac120dc37"}]}
def _scraped(self, **mark):
return {"files": [{"name": "neocdz.zip", "md5": "f39572af7584cb5b3f70ae8cc848aba2",
**mark}]}
def test_a_composite_md5_contradicts_nothing(self):
self.assertEqual(_diff_system(self.TRUTH, self._scraped(zip_digest="composite")), {})
def test_a_container_md5_still_does(self):
result = _diff_system(self.TRUTH, self._scraped())
self.assertEqual([m["name"] for m in result["hash_mismatch"]], ["neocdz.zip"])
class OneSlotUnderSeveralNames(unittest.TestCase):
"""kronos opens saturn_bios.bin, then sega_101.bin as a fallback. Ymir
reads either name, so the sega_101.bin entry answers for saturn_bios.bin
too. kronos sat in that entry's _cores and out of its _required_by while
its saturn_bios.bin entry had it requiring the file."""
PROFILES = {
"kronos": {
"emulator": "Kronos", "type": "libretro", "systems": ["sega-saturn"],
"files": [
{"name": "saturn_bios.bin", "path": "kronos/saturn_bios.bin",
"required": True, "size": 524288},
{"name": "sega_101.bin", "required": False, "size": 524288},
],
},
"ymir": {
"emulator": "Ymir", "type": "libretro", "systems": ["sega-saturn"],
"files": [
{"name": "sega_101.bin", "required": True, "size": 524288,
"aliases": ["saturn_bios.bin"]},
],
},
"other": {
"emulator": "Other", "type": "libretro", "systems": ["sega-saturn"],
"files": [{"name": "saturn_bios.bin", "required": True, "size": 524288}],
},
}
def _files(self) -> dict[str, dict]:
cores = ["kronos", "ymir", "other"]
model = generate_platform_truth("p", {"cores": cores}, {}, self.PROFILES)
return {f["name"]: f for f in model["systems"]["sega-saturn"]["files"]}
def test_a_reader_requiring_an_alias_requires_the_entry(self):
sega = self._files()["sega_101.bin"]
self.assertEqual(sega["_cores"], ["kronos", "ymir"])
self.assertEqual(sega["_required_by"], ["kronos", "ymir"])
def test_no_reader_is_added(self):
"""other requires saturn_bios.bin but never opens sega_101.bin."""
sega = self._files()["sega_101.bin"]
self.assertNotIn("other", sega["_required_by"])
self.assertTrue(set(sega["_required_by"]) <= set(sega["_cores"]))
class OnlySystemDirectoryEntries(unittest.TestCase):
"""The truth kept files read from the save, content or working directory:
diff_truth listed Cemu's mlc01 certificates, panda3ds's seeddb.bin and
+34
View File
@@ -66,6 +66,16 @@ class TestParseRepo(unittest.TestCase):
"/-/raw/abc123/source/Engine.cpp",
)
def test_voidpoint_is_a_gitlab(self):
"""eduke32 and fury were skipped as an unsupported host."""
repo = parse_repo("https://voidpoint.io/terminx/eduke32")
self.assertEqual(repo.family, "gitlab")
self.assertEqual(repo.api_base, "https://voidpoint.io/api/v4")
self.assertEqual(
raw_url(repo, "abc123", "source/build/src/build.cpp"),
"https://voidpoint.io/terminx/eduke32/-/raw/abc123/source/build/src/build.cpp",
)
def test_libretro_gitlab_is_a_gitlab(self):
repo = parse_repo("https://git.libretro.com/libretro/wqxemu.git")
self.assertEqual(repo.family, "gitlab")
@@ -805,5 +815,29 @@ class TestGiteaCommitAt(unittest.TestCase):
)
class TestCurrentSlug(unittest.TestCase):
"""The name a forge answers under, read from the repository payload."""
def test_github_and_gitlab_payloads(self):
answers = {
"https://api.github.com/repos/AloysHF/NicaiEmu": {
"full_name": "AloysHF/CoolbarEmu"
},
"https://gitlab.com/api/v4/projects/g%2Fsub%2Fp": {
"path_with_namespace": "g/sub/p"
},
}
with tempfile.TemporaryDirectory() as tmp, \
mock.patch.object(upstream, "_http_json", side_effect=answers.get):
github = parse_repo("https://github.com/AloysHF/NicaiEmu")
gitlab = parse_repo("https://gitlab.com/g/sub/p")
self.assertEqual(upstream.current_slug(github, tmp), "AloysHF/CoolbarEmu")
self.assertEqual(upstream.current_slug(gitlab, tmp), "g/sub/p")
self.assertIsNone(
upstream.current_slug(parse_repo("https://github.com/a/b"), tmp)
)
if __name__ == "__main__":
unittest.main()