Files
horizon-airdef/tests/test_parity_main.py
T
Ludovic Marie 2c5dac354e parity-main: name a merge only when HEAD fails again and the base passes
The bisect ended on the newest merge when the failed harnesses pass
everywhere now (a flake, or a runner that was missing the sounds), and
on the oldest when they fail everywhere (the runner), and commented on
that pull request either way. It now reruns them at HEAD and at the base
first and names nobody unless HEAD fails and the base passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 06:11:01 +01:00

73 lines
4.1 KiB
Python

"""tools/parity_main.py: the base of a parity-main run, and the bisect after a failure."""
from pathlib import Path
import tempfile
import unittest
from unittest import mock
from tools import parity_main
class ParityMainTests(unittest.TestCase):
def test_first_bad_finds_the_first_failing_merge(self):
commits = list("abcdefgh") # h failed; the base before a passed
for culprit in commits:
tried = []
fails = lambda commit: tried.append(commit) or commit >= culprit
self.assertEqual(parity_main.first_bad(commits, fails), culprit)
self.assertLessEqual(len(tried), 3, "log2 of 8 merges")
self.assertEqual(parity_main.first_bad(["a"], lambda commit: self.fail("nothing to try")), "a")
def test_base_is_the_newest_green_run_head_contains(self):
with tempfile.TemporaryDirectory() as tmp, mock.patch.object(parity_main, "ROOT", Path(tmp)):
git = lambda *arguments: parity_main.git(*arguments).stdout.strip()
git("init", "-q")
for n in range(3):
git("-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "--allow-empty", "-m", str(n))
head, parent, grandparent = git("rev-parse", "HEAD"), git("rev-parse", "HEAD^1"), git("rev-parse", "HEAD~2")
git("checkout", "-q", "-b", "side", grandparent)
git("-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "--allow-empty", "-m", "side")
side = git("rev-parse", "HEAD")
git("checkout", "-q", head)
self.assertEqual(parity_main.base(runs=[side, grandparent, parent]), grandparent,
"a run on a commit HEAD doesn't contain is skipped")
self.assertEqual(parity_main.base(runs=[]), parent, "no green run yet: the last merge")
self.assertEqual(parity_main.base(runs=[head]), head)
def test_bisect_names_a_merge_only_when_head_fails_and_the_base_passes(self):
with tempfile.TemporaryDirectory() as tmp, mock.patch.object(parity_main, "ROOT", Path(tmp)):
git = lambda *arguments: parity_main.git(*arguments).stdout.strip()
git("init", "-q")
for n in range(4):
git("-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "--allow-empty",
"-m", f"Merge pull request #{n} from x/y")
commits = git("rev-list", "--reverse", "HEAD").split()
last_run = Path(tmp) / ".local/parity-runner/last-run.json"
last_run.parent.mkdir(parents=True)
last_run.write_text('{"failed": ["music"]}')
real_run = parity_main.subprocess.run
for broken_from, blamed in ((None, None), (0, None), (2, "2")):
comments = []
# git runs for real in the scratch repo; a `gh pr comment` is only recorded, never sent.
fake_run = lambda command, **kwargs: (comments.append(command) if command[0] == "gh"
else real_run(command, **kwargs))
with mock.patch.object(parity_main, "LAST_RUN", last_run), \
mock.patch.object(parity_main, "run_harnesses", lambda names, timeout: broken_from is not None
and commits.index(git("rev-parse", "HEAD")) >= broken_from), \
mock.patch.object(parity_main.subprocess, "run", fake_run), \
mock.patch("builtins.print") as printed:
parity_main.bisect(commits[0], 60, comment=True)
if blamed:
self.assertEqual([command[3] for command in comments], [blamed])
else:
self.assertEqual(comments, [], printed.call_args_list[-1])
self.assertEqual(git("rev-parse", "HEAD"), commits[-1], "HEAD checked out again")
def test_a_harness_a_commit_does_not_have_cannot_fail_there(self):
with mock.patch.object(parity_main.subprocess, "run") as run:
self.assertFalse(parity_main.run_harnesses(["not_a_harness_yet"], 60))
run.assert_not_called()
if __name__ == "__main__":
unittest.main()