"""Regression tests and drift guard for the deterministic check manifest."""
from __future__ import annotations
import ast
import json
import os
import re
import shutil
import subprocess
import sys
import tempfile
import unittest
import importlib.util
from collections import Counter
from contextlib import redirect_stderr, redirect_stdout
from io import StringIO
from pathlib import Path
from unittest.mock import patch
from git_bash import bash_executable, bash_path, native_path_from_bash
from run_checks import (
VALID_PLATFORMS,
Check,
Manifest,
command_for_check,
command_for_host,
detect_platform,
execute_checks,
load_manifest,
resolve_check_selections,
resolve_checks,
resolve_explicit_checks,
run_git,
skipped_platform_checks,
trigger_matches,
validate_manifest,
)
SCRIPT_DIR = Path(__file__).resolve().parent
REPO_ROOT = SCRIPT_DIR.parents[1]
MANIFEST_PATH = REPO_ROOT / ".github/checks-manifest.yaml"
WORKFLOWS_DIR = REPO_ROOT / ".github/workflows"
SCRIPT_REFERENCE_RE = re.compile(r"(?P<path>(?:\.github|backend|desktop/macos)/scripts/[A-Za-z0-9_.-]+\.py)")
def load_deferred_marker_module():
path = SCRIPT_DIR / "deferred-work-marker-count.py"
spec = importlib.util.spec_from_file_location("deferred_work_marker_count", path)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def deterministic_workflow_references(workflows_dir: Path) -> set[str]:
references: set[str] = set()
for workflow in sorted(workflows_dir.glob("*.y*ml")):
for match in SCRIPT_REFERENCE_RE.finditer(workflow.read_text(encoding="utf-8")):
path = match.group("path")
name = Path(path).name
if (
(
path.startswith(".github/scripts/")
and (name.startswith(("check_", "check-")) or name.endswith("-count.py"))
)
or (path.startswith("backend/scripts/") and name.startswith(("scan_", "check_")))
or (path.startswith("desktop/macos/scripts/") and name.startswith(("check_", "check-")))
):
references.add(path)
return references
def registered_script_paths() -> set[str]:
manifest = load_manifest(MANIFEST_PATH)
return {token for check in manifest.checks for token in check.command if token.endswith(".py")}
TEST_MODULE_RE = re.compile(r"(?:^|/)test[_-][A-Za-z0-9_.-]*\.py$")
def interpreter_invoked_test_modules(command: tuple[str, ...]) -> list[str]:
"""Test modules a command hands straight to the interpreter.
Commands that name an explicit runner (`-m pytest`, `-m unittest`) delegate
discovery to that runner and are not subject to the self-running contract.
"""
if any(token in {"-m", "pytest", "unittest"} for token in command):
return []
return [token for token in command if TEST_MODULE_RE.search(token)]
def non_self_running_reason(source: str) -> str | None:
"""Explain why `python3 <module>` would execute no test cases, or None.
Two shapes execute nothing and still exit 0:
* no `__main__` block at all -- a pytest-only module handed to the
interpreter defines its functions and exits.
* a `__main__` block calling `unittest.main()` in a module with no
`TestCase` subclass -- discovery finds nothing to run.
A script-style module whose `__main__` calls its own `main()` of assertions
is self-running and must not be reported.
"""
try:
tree = ast.parse(source)
except SyntaxError as exc:
return f"could not be parsed: {exc}"
main_blocks = [
node
for node in ast.walk(tree)
if isinstance(node, ast.If)
and any(
isinstance(cmp_, ast.Constant) and cmp_.value == "__main__"
for cmp_ in getattr(node.test, "comparators", [])
)
]
invoking_blocks = [node for node in main_blocks if any(isinstance(inner, ast.Call) for inner in ast.walk(node))]
if not invoking_blocks:
return "has no __main__ block invoking a test runner, so the interpreter runs no cases"
delegates_to_unittest = any(
isinstance(inner, ast.Attribute) and inner.attr == "main" and getattr(inner.value, "id", "") == "unittest"
for block in invoking_blocks
for inner in ast.walk(block)
)
if not delegates_to_unittest:
return None
has_test_case = any(
isinstance(node, ast.ClassDef)
and any(
(isinstance(base, ast.Attribute) and base.attr.endswith("TestCase"))
or (isinstance(base, ast.Name) and base.id.endswith("TestCase"))
for base in node.bases
)
for node in ast.walk(tree)
)
if not has_test_case:
return "calls unittest.main() with no TestCase subclass, so discovery collects nothing"
return None
class ManifestContractTests(unittest.TestCase):
def test_firestore_guard_reuses_selector_scope_in_both_lanes(self) -> None:
trigger_matches('@firestore-index-guard', 'firestore.indexes.json')
from select_backend_unit_tests import (
FIRESTORE_INDEX_GUARD_CONTROL_PATHS,
FIRESTORE_INDEX_GUARD_SCHEMA_PATHS,
FIRESTORE_INDEX_GUARD_TESTS,
is_firestore_index_guard_path,
)
manifest = load_manifest(MANIFEST_PATH)
check = next(check for check in manifest.checks if check.id == 'firestore-index-guard')
self.assertEqual(check.command, ('python3', 'backend/scripts/run_firestore_index_guard.py'))
self.assertFalse(check.requires_pr_body)
self.assertEqual(len(FIRESTORE_INDEX_GUARD_TESTS), 7)
paths = set(FIRESTORE_INDEX_GUARD_CONTROL_PATHS | FIRESTORE_INDEX_GUARD_SCHEMA_PATHS)
paths.update('backend/' + test for test in FIRESTORE_INDEX_GUARD_TESTS)
paths.update(
{
'backend/new_package/new_query.py',
'backend/routers/conversations.py',
'backend/tests/support/firestore_new_driver.py',
}
)
for path in paths:
self.assertTrue(is_firestore_index_guard_path(path), path)
for lane in ('local', 'ci'):
self.assertIn(check, resolve_checks(manifest, [path], lane, include_pr_body_checks=False), path)
def test_firestore_guard_is_not_selected_for_docs_or_excluded_sources(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
for path in (
'docs/README.md',
'backend/AGENTS.md',
'.github/agent-docs/firestore-queries-and-indexes.md',
'backend/scripts/unrelated.py',
'backend/tests/unit/test_unrelated.py',
'backend/migrations/unrelated.py',
'web/personas-open-source/src/app/page.tsx',
):
for lane in ('local', 'ci'):
self.assertNotIn('firestore-index-guard', {c.id for c in resolve_checks(manifest, [path], lane)}, path)
def test_firestore_guard_runner_fails_closed_and_uses_only_shared_test_list(self) -> None:
trigger_matches('@firestore-index-guard', 'firestore.indexes.json')
import run_firestore_index_guard as runner
scratch = REPO_ROOT / '.agent-brief'
scratch.mkdir(exist_ok=True)
with tempfile.TemporaryDirectory(dir=scratch) as tmp:
backend = Path(tmp) / 'backend'
backend.mkdir()
(backend / '.python-version').write_text('3.11.15')
for test in runner.FIRESTORE_INDEX_GUARD_TESTS:
path = backend / test
path.parent.mkdir(parents=True, exist_ok=True)
path.touch()
with patch.object(runner, 'BACKEND_DIR', backend):
with patch.object(runner.subprocess, 'run', side_effect=OSError('uv unavailable')):
output = StringIO()
with redirect_stderr(output):
self.assertEqual(runner.main(), 2)
self.assertIn('environment setup failed', output.getvalue())
self.assertIn(runner.GUIDE, output.getvalue())
for status in (0, 1):
with patch.object(
runner.subprocess, 'run', return_value=subprocess.CompletedProcess([], status)
) as run:
output = StringIO()
with redirect_stderr(output), redirect_stdout(output):
self.assertEqual(runner.main(), status)
args, kwargs = run.call_args
self.assertEqual(args[0], ['bash', 'test.sh'])
self.assertEqual(kwargs['cwd'], backend)
env = kwargs['env']
self.assertEqual(
Path(env['BACKEND_UNIT_TEST_FILE_LIST']).read_text().splitlines(),
list(runner.FIRESTORE_INDEX_GUARD_TESTS),
)
self.assertEqual(env['PYTEST_DISABLE_PLUGIN_AUTOLOAD'], '1')
self.assertEqual(env['BACKEND_PYTEST_MARK_EXPR'], 'not integration')
self.assertEqual(env['BACKEND_FAST_UNIT_FAIL_SECONDS'], 'inf')
if status:
self.assertIn('Declare the required index', output.getvalue())
self.assertIn(runner.GUIDE, output.getvalue())
def test_manifest_is_valid(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
self.assertEqual(validate_manifest(manifest, REPO_ROOT), [])
def test_removing_ci_lane_is_invalid(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
first = manifest.checks[0]
local_only = Check(first.id, first.command, first.triggers, ("local",), first.reason)
invalid = type(manifest)((local_only, *manifest.checks[1:]), manifest.exempt)
self.assertTrue(any("missing required lanes: ci" in error for error in validate_manifest(invalid, REPO_ROOT)))
def test_requires_pr_body_must_be_boolean(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
first = manifest.checks[0]
malformed = Check(
first.id,
first.command,
first.triggers,
first.lanes,
first.reason,
requires_pr_body="yes",
)
invalid = type(manifest)((malformed, *manifest.checks[1:]), manifest.exempt)
self.assertIn(
f"{first.id}: requires_pr_body must be a boolean",
validate_manifest(invalid, REPO_ROOT),
)
def test_explicit_trigger_path_must_exist(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
first = manifest.checks[0]
missing = ".github/scripts/does-not-exist.py"
malformed = Check(
first.id,
first.command,
(*first.triggers, missing),
first.lanes,
first.reason,
)
invalid = type(manifest)((malformed, *manifest.checks[1:]), manifest.exempt)
self.assertIn(
f"{first.id}: explicit trigger path does not exist: {missing}",
validate_manifest(invalid, REPO_ROOT),
)
def test_workflow_checks_are_registered_or_exempt(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
registered = registered_script_paths()
exempt = {item.path for item in manifest.exempt}
missing = sorted(deterministic_workflow_references(WORKFLOWS_DIR) - registered - exempt)
self.assertEqual(missing, [], f"workflow checks missing from manifest/exempt: {missing}")
def test_ci_lane_is_reachable_from_repo_checks(self) -> None:
workflow = (WORKFLOWS_DIR / "repo-checks.yml").read_text(encoding="utf-8")
self.assertRegex(workflow, r"run_checks\.py\s+--lane\s+ci")
self.assertNotIn("--skip-pr-body-checks", workflow)
self.assertRegex(workflow, r"git log -1 --format=%B HEAD")
self.assertRegex(workflow, r"pr_metadata\.py")
self.assertRegex(workflow, r"--from-commit-body-file")
self.assertRegex(workflow, r"--pr-body-file")
manifest = load_manifest(MANIFEST_PATH)
self.assertTrue(any("ci" in check.lanes for check in manifest.checks))
def test_manifest_test_modules_execute_their_cases(self) -> None:
"""A registered test command must not be able to pass without running tests.
`python3 some_test_module.py` exits 0 when the module defines only
module-level `def test_*` functions, because `unittest.main()` discovers
`TestCase` subclasses. Such a check is green forever without asserting
anything, which is indistinguishable from a guard that works.
"""
manifest = load_manifest(MANIFEST_PATH)
offenders: list[str] = []
for check in manifest.checks:
for relative in interpreter_invoked_test_modules(check.command):
path = REPO_ROOT / relative
if not path.exists():
offenders.append(f"{check.id}: {relative} does not exist")
continue
reason = non_self_running_reason(path.read_text(encoding="utf-8"))
if reason:
offenders.append(f"{check.id}: {relative} {reason}")
self.assertEqual(offenders, [], f"manifest test commands that execute no cases: {offenders}")
def test_pytest_only_module_is_reported_as_non_self_running(self) -> None:
"""The guard above must fail on the real historical shape it exists to catch."""
pytest_only = (
"from pathlib import Path\n" "\n" "def test_something(tmp_path: Path) -> None:\n" " assert True\n"
)
self.assertIn("has no __main__", non_self_running_reason(pytest_only) or "")
with_runner = (
"import unittest\n"
"\n"
"class T(unittest.TestCase):\n"
" def test_something(self) -> None:\n"
" self.assertTrue(True)\n"
"\n"
'if __name__ == "__main__":\n'
" unittest.main()\n"
)
self.assertIsNone(non_self_running_reason(with_runner))
no_main = (
"import unittest\n"
"\n"
"class T(unittest.TestCase):\n"
" def test_something(self) -> None:\n"
" self.assertTrue(True)\n"
)
self.assertIn("has no __main__", non_self_running_reason(no_main) or "")
unittest_main_without_test_case = (
"import unittest\n"
"\n"
"def test_something() -> None:\n"
" assert True\n"
"\n"
'if __name__ == "__main__":\n'
" unittest.main()\n"
)
self.assertIn("no TestCase subclass", non_self_running_reason(unittest_main_without_test_case) or "")
script_style = (
"def main() -> int:\n"
" assert True\n"
" return 0\n"
"\n"
'if __name__ == "__main__":\n'
" raise SystemExit(main())\n"
)
self.assertIsNone(non_self_running_reason(script_style))
def test_unregistered_fake_workflow_check_is_named(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
workflows = Path(tmp)
fake_name = "check_" + "something.py"
(workflows / "fake.yml").write_text(
f"steps:\n - run: python3 .github/scripts/{fake_name}\n",
encoding="utf-8",
)
self.assertEqual(deterministic_workflow_references(workflows), {f".github/scripts/{fake_name}"})
class RunnerBehaviorTests(unittest.TestCase):
def _prepare_cli_fixture(
self,
root: Path,
checks: list[dict[str, object]],
*,
changed_files: tuple[str, ...] = ("backend/example.py",),
) -> tuple[Path, Path]:
"""Create a tiny committed repo that exercises the real runner CLI."""
scripts = root / "checks"
scripts.mkdir(parents=True)
runs_file = root / "runs.txt"
manifest_lines = ["checks:"]
for spec in checks:
check_id = str(spec["id"])
script = scripts / f"{check_id}.py"
exit_code = int(spec.get("exit_code", 0))
script.write_text(
"from pathlib import Path\n"
f"Path({json.dumps(str(runs_file))}).open('a', encoding='utf-8').write({json.dumps(check_id + chr(10))})\n"
f"raise SystemExit({exit_code})\n",
encoding="utf-8",
)
triggers = spec.get("triggers", ("backend/**",))
manifest_lines.extend(
[
f" - id: {check_id}",
f" command: [\"python3\", \"checks/{check_id}.py\"]",
f" triggers: {json.dumps(list(triggers))}",
" lanes: [\"local\", \"ci\"]",
f" reason: {spec.get('reason', 'fixture check')}",
f" requires_pr_body: {'true' if spec.get('requires_pr_body', False) else 'false'}",
]
)
if spec.get("platforms"):
manifest_lines.append(f" platforms: {json.dumps(list(spec['platforms']))}")
manifest = root / ".github/checks-manifest.yaml"
manifest.parent.mkdir(parents=True)
manifest.write_text("\n".join(manifest_lines) + "\n", encoding="utf-8")
changed = root / "changed-files.txt"
changed.write_text("".join(f"{path}\n" for path in changed_files), encoding="utf-8")
env = os.environ.copy()
for key in tuple(env):
if key.startswith("GIT_"):
del env[key]
subprocess.run(["git", "init", "-q", str(root)], check=True, env=env)
subprocess.run(["git", "-C", str(root), "add", "."], check=True, env=env)
subprocess.run(
[
"git",
"-C",
str(root),
"-c",
"core.hooksPath=/dev/null",
"-c",
"commit.gpgsign=false",
"-c",
"user.name=fixture",
"-c",
"user.email=fixture@example.invalid",
"commit",
"-qm",
"fixture",
],
check=True,
env=env,
)
return manifest, changed
def _run_cli(self, root: Path, manifest: Path, changed: Path, *extra: str) -> subprocess.CompletedProcess[str]:
runner = REPO_ROOT / ".github/scripts/run_checks.py"
env = {key: value for key, value in os.environ.items() if not key.startswith("GIT_")}
return subprocess.run(
[
sys.executable,
str(runner),
"--root",
str(root),
"--manifest",
str(manifest),
"--changed-files",
str(changed),
"--base",
"HEAD",
"--head",
"HEAD",
"--lane",
"ci",
"--platform",
"linux",
*extra,
],
env=env,
text=True,
capture_output=True,
check=False,
)
def test_metadata_only_selects_body_checks_for_matching_path_and_platform(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
manifest, changed = self._prepare_cli_fixture(
root,
[
{"id": "body-linux", "requires_pr_body": True, "platforms": ("linux",)},
{"id": "source-linux"},
{"id": "body-macos", "requires_pr_body": True, "platforms": ("macos",)},
{
"id": "body-unrelated",
"requires_pr_body": True,
"triggers": ("app/**",),
},
],
)
result = self._run_cli(root, manifest, changed, "--metadata-only", "--list")
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("SELECTED body-linux", result.stdout)
self.assertNotIn("SELECTED source-linux", result.stdout)
self.assertNotIn("SELECTED body-macos", result.stdout)
self.assertNotIn("SELECTED body-unrelated", result.stdout)
def test_metadata_only_runs_all_failures_and_returns_nonzero(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
manifest, changed = self._prepare_cli_fixture(
root,
[
{"id": "body-first", "requires_pr_body": True, "exit_code": 3},
{"id": "body-second", "requires_pr_body": True, "exit_code": 4},
],
)
result = self._run_cli(root, manifest, changed, "--metadata-only")
runs = (root / "runs.txt").read_text(encoding="utf-8").splitlines()
self.assertEqual(result.returncode, 1)
self.assertEqual(runs, ["body-first", "body-second"])
self.assertIn("<== FAIL body-first", result.stdout)
self.assertIn("<== FAIL body-second", result.stdout)
self.assertIn("Manifest checks failed: body-first, body-second", result.stderr)
def test_metadata_only_success_returns_zero_without_running_source_checks(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
manifest, changed = self._prepare_cli_fixture(
root,
[
{"id": "body-pass", "requires_pr_body": True},
{"id": "source-fails", "exit_code": 9},
],
)
result = self._run_cli(root, manifest, changed, "--metadata-only")
runs = (root / "runs.txt").read_text(encoding="utf-8").splitlines()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(runs, ["body-pass"])
self.assertIn("Manifest checks passed: 1 check(s).", result.stdout)
def test_default_mode_runs_source_checks_and_remains_fail_fast(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
manifest, changed = self._prepare_cli_fixture(
root,
[
{"id": "body-pass", "requires_pr_body": True},
{"id": "source-fails", "exit_code": 7},
{"id": "source-after-failure", "exit_code": 8},
],
)
result = self._run_cli(root, manifest, changed)
runs = (root / "runs.txt").read_text(encoding="utf-8").splitlines()
self.assertEqual(result.returncode, 1)
self.assertEqual(runs, ["body-pass", "source-fails"])
self.assertIn("Manifest checks failed: source-fails", result.stderr)
self.assertNotIn("==> source-after-failure", result.stdout)
def test_metadata_only_rejects_conflicting_selection_flags(self) -> None:
runner = REPO_ROOT / ".github/scripts/run_checks.py"
for flags in (("--skip-pr-body-checks",), ("--check-id", "source-check")):
with self.subTest(flags=flags):
result = subprocess.run(
[sys.executable, str(runner), "--lane", "ci", "--metadata-only", *flags],
text=True,
capture_output=True,
check=False,
)
self.assertEqual(result.returncode, 2)
self.assertIn("--metadata-only cannot combine", result.stderr)
def test_run_git_decodes_unicode_checkout_path_as_utf8(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp) / "路径 checkout"
root.mkdir()
env = os.environ.copy()
for key in tuple(env):
if key.startswith("GIT_"):
del env[key]
subprocess.run(["git", "init", "-q", str(root)], check=True, env=env)
with patch.dict(os.environ, env, clear=True):
resolved = run_git(root, "rev-parse", "--show-toplevel")
self.assertEqual(Path(resolved).resolve(), root.resolve())
def test_windows_manifest_interpreters_use_the_active_toolchain(self) -> None:
with patch("run_checks.bash_executable", return_value="C:\\Git\\bin\\bash.exe"):
self.assertEqual(
command_for_host(["bash", "scripts/check.sh"], platform_name="nt"),
["C:\\Git\\bin\\bash.exe", "scripts/check.sh"],
)
self.assertEqual(
command_for_host(
["python3", ".github/scripts/check.py"],
platform_name="nt",
python_executable="C:\\Python\\python.exe",
),
["C:\\Python\\python.exe", ".github/scripts/check.py"],
)
def test_non_interpreter_and_non_windows_commands_are_unchanged(self) -> None:
node_command = ["node", "--test", "test.mjs"]
bash_command = ["bash", "scripts/check.sh"]
self.assertIs(command_for_host(node_command, platform_name="nt"), node_command)
self.assertIs(command_for_host(bash_command, platform_name="posix"), bash_command)
def test_execute_checks_normalizes_the_manifest_command(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
changed = root / "changed.txt"
changed.write_text("example.txt\n", encoding="utf-8")
body = root / "body.txt"
body.write_text("", encoding="utf-8")
check = Check("shell", ("bash", "check.sh"), ("all",), ("ci",), "fixture")
with (
patch("run_checks.command_for_host", return_value=["git-bash.exe", "check.sh"]) as normalize,
patch(
"run_checks.subprocess.run",
return_value=subprocess.CompletedProcess(["git-bash.exe", "check.sh"], 0),
) as run,
redirect_stdout(StringIO()),
):
result = execute_checks(
root,
[check],
changed_files_path=changed,
base="base",
head="HEAD",
pr_body_file=body,
)
self.assertEqual(result, 0)
normalize.assert_called_once_with(["bash", "check.sh"])
run.assert_called_once_with(["git-bash.exe", "check.sh"], cwd=root, check=False)
def test_windows_bash_resolution_uses_the_git_install(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
git_root = Path(tmp)
git = git_root / "cmd/git.exe"
git.parent.mkdir()
git.touch()
bash = git_root / "bin/bash.exe"
bash.parent.mkdir()
bash.touch()
resolved = bash_executable(
platform_name="nt",
which=lambda name: str(git) if name == "git" else None,
)
self.assertTrue(Path(resolved).samefile(bash))
def test_windows_bash_resolution_from_git_hook_exec_path(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
git_root = Path(tmp)
git = git_root / "mingw64/libexec/git-core/git.exe"
git.parent.mkdir(parents=True)
git.touch()
bash = git_root / "bin/bash.exe"
bash.parent.mkdir()
bash.touch()
resolved = bash_executable(
platform_name="nt",
which=lambda name: str(git) if name == "git" else None,
)
self.assertTrue(Path(resolved).samefile(bash))
def test_windows_bash_path_is_converted_back_to_native(self) -> None:
commands: list[list[str]] = []
def fake_run(command, **_kwargs):
commands.append(command)
return subprocess.CompletedProcess(command, 0, stdout="C:\\Temp\\guard.py\n", stderr="")
converted = native_path_from_bash(
"/tmp/guard.py",
"git-bash.exe",
platform_name="nt",
run=fake_run,
)
self.assertEqual(converted, Path("C:\\Temp\\guard.py"))
self.assertEqual(
commands,
[["git-bash.exe", "-c", 'cygpath -w "$1"', "bash", "/tmp/guard.py"]],
)
def test_windows_native_path_is_converted_for_bash(self) -> None:
commands: list[list[str]] = []
def fake_run(command, **_kwargs):
commands.append(command)
return subprocess.CompletedProcess(command, 0, stdout="/c/Temp/body.md\n", stderr="")
converted = bash_path(
Path("C:\\Temp\\body.md"),
"git-bash.exe",
platform_name="nt",
run=fake_run,
)
self.assertEqual(converted, "/c/Temp/body.md")
self.assertEqual(
commands,
[["git-bash.exe", "-c", 'cygpath -u "$1"', "bash", "C:\\Temp\\body.md"]],
)
@unittest.skipIf(os.name == "nt", "requires a POSIX shell")
def test_firestore_contention_runner_uses_uv_without_backend_venv(self) -> None:
source = REPO_ROOT / "backend/testing/desktop_beta_admission/run.sh"
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
runner = root / "backend/testing/desktop_beta_admission/run.sh"
runner.parent.mkdir(parents=True)
shutil.copy2(source, runner)
(root / "backend/.python-version").write_text("3.11\n", encoding="utf-8")
fake_bin = root / "fake-bin"
fake_bin.mkdir()
capture = root / "node-args.txt"
for name, body in {
"uv": "#!/bin/sh\nexit 99\n",
"node": f"""#!/bin/sh
case "$1" in
-p) echo 22 ;;
*emulator_config.mjs) printf '45678 45679\\n' ;;
*supervise.mjs) printf '%s\\n' "$@" > "{capture}" ;;
esac
""",
"java": "#!/bin/sh\necho ' java.version = 21.0.1' >&2\n",
}.items():
path = fake_bin / name
path.write_text(body, encoding="utf-8")
path.chmod(0o755)
env = os.environ.copy()
env["PATH"] = f"{fake_bin}:/usr/bin:/bin"
result = subprocess.run(["bash", str(runner)], text=True, capture_output=True, env=env, check=False)
self.assertEqual(result.returncode, 0, result.stderr)
captured = capture.read_text(encoding="utf-8")
self.assertIn("uv run --no-project", captured)
self.assertIn("--cleanup-path", captured)
def test_trigger_matching_selects_only_relevant_checks(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
selected = {check.id for check in resolve_checks(manifest, ["app/lib/widgets/example.dart"], "ci")}
self.assertIn("brand-ui", selected)
self.assertNotIn("backend-async-blockers", selected)
self.assertNotIn("backend-route-policy-baseline", selected)
def test_manifest_only_trigger_requires_own_entry_change(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
selected = {
check.id
for check in resolve_checks(
manifest,
[".github/checks-manifest.yaml"],
"ci",
platform="macos",
manifest_changed_ids={"backend-deploy-source-admission"},
)
}
self.assertIn("backend-deploy-source-admission", selected)
self.assertNotIn("rayban-dat-build-wrapper", selected)
def test_manifest_only_trigger_without_diff_context_selects_all_manifest_checks(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
selected = {
check.id
for check in resolve_checks(
manifest,
[".github/checks-manifest.yaml"],
"ci",
platform="macos",
)
}
self.assertIn("rayban-dat-build-wrapper", selected)
def test_manifest_worktree_edit_selects_only_changed_check_entry(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
selected = {
check.id
for check in resolve_checks(
manifest,
[".github/checks-manifest.yaml"],
"local",
platform="macos",
manifest_changed_ids={"backend-runtime-env-compose"},
)
}
self.assertIn("backend-runtime-env-compose", selected)
self.assertNotIn("rayban-dat-build-wrapper", selected)
def test_posix_contracts_skip_windows_without_dropping_linux_ci(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
expected_by_path = {
"app/ios/Podfile": {
"rayban-dat-plugin-boundary",
"rayban-dat-xcode-graph",
"rayban-dat-build-wrapper",
},
}
for path, expected in expected_by_path.items():
windows = {check.id for check in resolve_checks(manifest, [path], "ci", platform="windows")}
linux = {check.id for check in resolve_checks(manifest, [path], "ci", platform="linux")}
self.assertTrue(expected.isdisjoint(windows), path)
self.assertTrue(expected <= linux, path)
def test_shared_windows_entrypoints_route_their_behavioral_contracts(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
expected_by_path = {
".github/workflows/gcp_storage_lifecycle.yml": {"pr-preflight-contract-tests"},
"Makefile": {"dev-harness-unit-tests", "setup-pre-push-prerequisites"},
"scripts/dev-harness/_resolve_python.sh": {
"dev-harness-unit-tests",
"desktop-release-process-guards",
},
"scripts/pre-push-singleflight": {"pr-preflight-contract-tests"},
".github/scripts/preflight_runner.py": {"pr-preflight-contract-tests"},
"desktop/macos/scripts/check-e2e-flow-coverage.py": {
"desktop-e2e-flow-coverage",
"pr-preflight-contract-tests",
},
".github/scripts/git_bash.py": {
"check-manifest-contract",
"desktop-release-process-guards",
"desktop-swiftlint-config",
},
}
for path, expected in expected_by_path.items():
selected = {check.id for check in resolve_checks(manifest, [path], "ci", platform="macos")}
self.assertTrue(expected <= selected, f"{path}: missing {sorted(expected - selected)}")
def test_root_agents_md_selects_agent_doc_checks(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
for lane in ("local", "ci"):
selected = {check.id for check in resolve_checks(manifest, ["AGENTS.md"], lane)}
self.assertIn("agents-md-lean", selected)
self.assertIn("agent-doc-references", selected)
def test_backend_route_change_selects_route_policy_baseline_in_both_lanes(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
changed = ["backend/routers/chat_sessions.py"]
for lane in ("local", "ci"):
selected = {check.id for check in resolve_checks(manifest, changed, lane)}
self.assertIn("backend-route-policy-baseline", selected)
def test_failure_class_protocol_runs_in_both_lanes(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
for lane in ("local", "ci"):
selected = {check.id for check in resolve_checks(manifest, ["app/lib/example.dart"], lane)}
self.assertIn("failure-class-protocol", selected)
def test_main_push_includes_pr_body_checks_when_body_supplied(self) -> None:
"""#9744: main pushes now pass the merge-commit body through
--pr-body-file, so body-requiring checks (product-invariants,
failure-class-protocol) must run — not be silently skipped."""
manifest = load_manifest(MANIFEST_PATH)
selected = {
check.id
for check in resolve_checks(
manifest,
["app/lib/example.dart"],
"ci",
include_pr_body_checks=True,
)
}
self.assertIn("product-invariants", selected)
self.assertIn("failure-class-protocol", selected)
self.assertIn("diff-hygiene", selected)
def test_product_invariants_diffs_three_dot_from_base_not_a_changed_files_list(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
check = next(check for check in manifest.checks if check.id == "product-invariants")
self.assertIn("{base}", check.command)
self.assertIn("{head}", check.command)
self.assertNotIn("{changed_files}", check.command)
def test_main_push_without_body_still_excludes_pr_body_checks(self) -> None:
"""Fail-closed: a main push with no body must NOT run body-requiring
checks (they would fail on empty text), preserving the old skip."""
manifest = load_manifest(MANIFEST_PATH)
selected = {
check.id
for check in resolve_checks(
manifest,
["app/lib/example.dart"],
"ci",
include_pr_body_checks=False,
)
}
self.assertNotIn("product-invariants", selected)
self.assertNotIn("failure-class-protocol", selected)
self.assertIn("diff-hygiene", selected)
def test_every_pr_body_consuming_check_is_excluded_from_post_merge_runs(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
for check in manifest.checks:
if "{pr_body_file}" in check.command:
self.assertTrue(
check.requires_pr_body,
f"{check.id} consumes the PR body, so it must declare requires_pr_body: true",
)
def test_line_count_ratchet_receives_pr_body_metadata(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
check = next(check for check in manifest.checks if check.id == "product-file-line-count-ratchet")
self.assertTrue(check.requires_pr_body)
self.assertIn("{pr_body_file}", check.command)
self.assertIn("{target_base}", check.command)
self.assertIn("{head}", check.command)
selected = resolve_checks(
manifest,
["backend/routers/example.py"],
"ci",
include_pr_body_checks=False,
)
self.assertNotIn(check, selected)
self.assertIn(check, resolve_checks(manifest, ["backend/routers/example.py"], "ci"))
self.assertIn(check, resolve_checks(manifest, ["app/lib/pages/chat/page.dart"], "ci"))
self.assertIn("app/lib/**/*.dart", check.triggers)
command = command_for_check(
check,
changed_files_path=Path("changed.txt"),
base="merge-base",
target_base="origin/main",
head="candidate-head",
pr_body_file=Path("body.txt"),
skip_changelog=False,
)
self.assertEqual(command[command.index("--base") + 1], "origin/main")
self.assertEqual(command[command.index("--head") + 1], "candidate-head")
def test_backend_datetime_sort_sentinel_ratchet_runs_for_backend_sources(self) -> None:
manifest = load_manifest(MANIFEST_PATH)
for lane in ("local", "ci"):
selected = {check.id for check in resolve_checks(manifest, ["backend/routers/example.py"], lane)}
self.assertIn("backend-datetime-sort-sentinel-ratchet", selected)
def test_failure_is_propagated(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
fail = root / "fail.py"
fail.write_text("raise SystemExit(7)\n", encoding="utf-8")
changed = root / "changed.txt"
changed.write_text("example.txt\n", encoding="utf-8")
body = root / "body.txt"
body.write_text("", encoding="utf-8")
check = Check("fails", (sys.executable, str(fail)), ("all",), ("ci",), "fixture")
with redirect_stdout(StringIO()), redirect_stderr(StringIO()):
result = execute_checks(
root,
[check],
changed_files_path=changed,
base="base",
head="HEAD",
pr_body_file=body,
)
self.assertEqual(result, 1)
def test_release_process_guard_uses_locked_pyyaml_in_every_declared_lane(self) -> None:
"""The guard must never depend on a runner-global PyYAML install."""
manifest = load_manifest(MANIFEST_PATH)
check = next(check for check in manifest.checks if check.id == "desktop-release-process-guards")
self.assertEqual(check.command, ("bash", "scripts/run-release-process-guards.sh"))
for lane in ("local", "ci"):
selected = resolve_checks(manifest, list(check.triggers), lane)
self.assertIn(check, selected)
try:
bash = bash_executable()
except FileNotFoundError as exc:
self.skipTest(str(exc))
runner = REPO_ROOT / check.command[1]
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
copied_runner = root / check.command[1]
copied_runner.parent.mkdir(parents=True)
shutil.copy2(runner, copied_runner)
resolver = root / "scripts/dev-harness/_resolve_python.sh"
resolver.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(REPO_ROOT / "scripts/dev-harness/_resolve_python.sh", resolver)
sync = root / "backend/scripts/sync-python-deps.sh"
sync.parent.mkdir(parents=True)
python = root / "backend/.venv/bin/python"
sync.write_text(
f'''#!/usr/bin/env bash
set -euo pipefail
mkdir -p "{bash_path(python.parent, bash)}"
cat > "{bash_path(python, bash)}" <<'PYTHON'
#!/usr/bin/env bash
set -euo pipefail
if [[ "$1" == "-c" ]]; then
exit 0
fi
printf '%s\\n' "$@" > "{bash_path(root / 'guard-args.txt', bash)}"
PYTHON
chmod +x "{bash_path(python, bash)}"
''',
encoding="utf-8",
)
sync.chmod(0o755)
guard = root / ".github/scripts/check-release-process-guards.py"
guard.parent.mkdir(parents=True, exist_ok=True)
guard.write_text("# fixture\n", encoding="utf-8")
env = os.environ.copy()
env["PYTHON"] = "ambient-python-must-not-run"
result = subprocess.run(
[bash, str(copied_runner)],
text=True,
capture_output=True,
env=env,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
recorded_guard = (root / "guard-args.txt").read_text(encoding="utf-8").strip()
self.assertTrue(
native_path_from_bash(recorded_guard, bash).samefile(guard),
f"release guard received {recorded_guard!r}, expected {str(guard)!r}",
)
self.assertRegex(
(REPO_ROOT / "backend/requirements.txt").read_text(encoding="utf-8"),
r"(?im)^pyyaml==6\.0\.1$",
)
for lock in REPO_ROOT.glob("backend/pylock*.toml"):
self.assertRegex(
lock.read_text(encoding="utf-8"),
r'(?ms)^\[\[packages\]\]\nname = "pyyaml"\nversion = "6\.0\.1"$',
)
def test_runtime_env_compose_uses_locked_pyyaml_in_every_declared_lane(self) -> None:
"""The compose check must never depend on a runner-global PyYAML install."""
manifest = load_manifest(MANIFEST_PATH)
check = next(check for check in manifest.checks if check.id == "backend-runtime-env-compose")
self.assertEqual(check.command, ("bash", "backend/scripts/check_runtime_env_compose.sh"))
for lane in ("local", "ci"):
selected = resolve_checks(manifest, list(check.triggers), lane)
self.assertIn(check, selected)
try:
bash = bash_executable()
except FileNotFoundError as exc:
self.skipTest(str(exc))
runner = REPO_ROOT / check.command[1]
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
copied_runner = root / check.command[1]
copied_runner.parent.mkdir(parents=True)
shutil.copy2(runner, copied_runner)
resolver = root / "scripts/dev-harness/_resolve_python.sh"
resolver.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(REPO_ROOT / "scripts/dev-harness/_resolve_python.sh", resolver)
sync = root / "backend/scripts/sync-python-deps.sh"
sync.parent.mkdir(parents=True, exist_ok=True)
python = root / "backend/.venv/bin/python"
compose = root / "backend/deploy/compose_runtime_env.py"
compose.parent.mkdir(parents=True)
compose.write_text("# fixture\n", encoding="utf-8")
sync.write_text(
f'''#!/usr/bin/env bash
set -euo pipefail
mkdir -p "{bash_path(python.parent, bash)}"
cat > "{bash_path(python, bash)}" <<'PYTHON'
#!/usr/bin/env bash
set -euo pipefail
if [[ "$1" == "-c" ]]; then
exit 0
fi
printf '%s\\n' "$@" > "{bash_path(root / 'compose-args.txt', bash)}"
PYTHON
chmod +x "{bash_path(python, bash)}"
''',
encoding="utf-8",
)
sync.chmod(0o755)
env = os.environ.copy()
env["PYTHON"] = "ambient-python-must-not-run"
result = subprocess.run(
[bash, str(copied_runner)],
text=True,
capture_output=True,
env=env,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
recorded_lines = (root / "compose-args.txt").read_text(encoding="utf-8").splitlines()
self.assertGreaterEqual(len(recorded_lines), 1)
recorded_script = native_path_from_bash(recorded_lines[0], bash)
self.assertTrue(
recorded_script.samefile(compose),
f"compose check received {recorded_lines[0]!r}, expected {str(compose)!r}",
)
self.assertIn("--check", recorded_lines[1:])
class PlatformTests(unittest.TestCase):
"""Tests for the platform-aware manifest model (#9843 Ticket 02)."""
def test_macos_check_selected_on_macos(self):
manifest = Manifest(
checks=(
Check(
id="mac-only", command=("true",), triggers=("all",), lanes=("ci",), reason="t", platforms=("macos",)
),
),
exempt=(),
)
selected = resolve_checks(manifest, ["any/file"], "ci", platform="macos")
self.assertEqual([c.id for c in selected], ["mac-only"])
def test_macos_check_skipped_on_linux(self):
manifest = Manifest(
checks=(
Check(
id="mac-only", command=("true",), triggers=("all",), lanes=("ci",), reason="t", platforms=("macos",)
),
),
exempt=(),
)
selected = resolve_checks(manifest, ["any/file"], "ci", platform="linux")
self.assertEqual(selected, [])
def test_no_platforms_means_all_platforms(self):
manifest = Manifest(
checks=(Check(id="portable", command=("true",), triggers=("all",), lanes=("ci",), reason="t"),), exempt=()
)
for plat in ("macos", "linux"):
selected = resolve_checks(manifest, ["any/file"], "ci", platform=plat)
self.assertEqual([c.id for c in selected], ["portable"])
def test_exclusive_macos_query_excludes_portable_checks(self):
manifest = Manifest(
checks=(
Check(id="portable", command=("true",), triggers=("all",), lanes=("ci",), reason="portable"),
Check(
id="mac-only",
command=("true",),
triggers=("all",),
lanes=("ci",),
reason="macOS",
platforms=("macos",),
),
),
exempt=(),
)
self.assertEqual(
[check.id for check in resolve_checks(manifest, ["any/file"], "ci", platform="macos")],
["portable", "mac-only"],
)
self.assertEqual(
[
check.id
for check in resolve_checks(
manifest,
["any/file"],
"ci",
platform="macos",
exclusive_platform=True,
)
],
["mac-only"],
)
def test_machine_readable_selection_carries_path_and_reason(self):
manifest = Manifest(
checks=(
Check(
id="target",
command=("true",),
triggers=("desktop/macos/**",),
lanes=("ci",),
reason="desktop source changed",
),
),
exempt=(),
)
selections = resolve_check_selections(manifest, ["desktop/macos/Desktop/Sources/App.swift"], "ci")
self.assertEqual(len(selections), 1)
self.assertEqual(selections[0].check.id, "target")
self.assertEqual(selections[0].matched_paths, ("desktop/macos/Desktop/Sources/App.swift",))
self.assertEqual(selections[0].check.reason, "desktop source changed")
def test_globstar_prefix_trigger_matches_repository_root(self):
"""`**/x` covers depth 0. A root-level file is not a different file type."""
for pattern, path in (
("**/*.json", "firebase.json"),
("**/*.yaml", "codemagic.yaml"),
("**/*.swift", "Package.swift"),
("**/Dockerfile*", "Dockerfile"),
("**/AGENTS.md", "AGENTS.md"),
):
with self.subTest(pattern=pattern, path=path):
self.assertTrue(trigger_matches(pattern, path))
def test_globstar_prefix_trigger_still_matches_nested_and_rejects_others(self):
self.assertTrue(trigger_matches("**/*.json", "backend/config/plan_catalog.json"))
self.assertFalse(trigger_matches("**/*.json", "firebase.yaml"))
self.assertFalse(trigger_matches("**/AGENTS.md", "AGENTS.md.bak"))
def test_literal_package_json_does_not_select_nested_copies(self):
"""Root firebase-tools pins must not wake admission when a web package changes.
The iOS compile runner executes macOS-exclusive checks and has no backend
venv. `web/frontend/package.json` is not the Firestore emulator pin.
"""
self.assertTrue(trigger_matches("package.json", "package.json"))
self.assertFalse(trigger_matches("package.json", "web/frontend/package.json"))
self.assertFalse(trigger_matches("package-lock.json", "web/frontend/package-lock.json"))
self.assertTrue(trigger_matches("**/AGENTS.md", "backend/AGENTS.md"))
self.assertFalse(trigger_matches("AGENTS.md", "backend/AGENTS.md"))
manifest = load_manifest(MANIFEST_PATH)
web_share = {
check.id
for check in resolve_checks(
manifest,
[".github/checks-manifest.yaml", "web/frontend/package.json"],
"ci",
platform="macos",
exclusive_platform=True,
manifest_changed_ids={"web-share-http-tests"},
)
}
self.assertNotIn("desktop-beta-admission-firestore-contention", web_share)
root_pin = {
check.id
for check in resolve_checks(
manifest,
["package.json"],
"ci",
platform="macos",
exclusive_platform=True,
)
}
self.assertIn("desktop-beta-admission-firestore-contention", root_pin)
nested_agents = {check.id for check in resolve_checks(manifest, ["backend/AGENTS.md"], "ci")}
self.assertIn("agents-md-lean", nested_agents)
def test_root_level_source_change_selects_plan_catalog_contract(self):
"""The Stripe-literal scan walks from the root, so selection must too.
`plan-catalog-contract` is triggered only by `**/*.<ext>` patterns. Before
the leading-`**/` collapse, a production Stripe object ID committed to a
root-level source file -- `firebase.json`, `omi.json`, `codemagic.yaml` --
changed no path the guard could see, and the exhaustiveness contract it
exists to enforce reported success without running.
"""
manifest = load_manifest(MANIFEST_PATH)
for path in ("firebase.json", "codemagic.yaml", "Package.swift"):
with self.subTest(path=path):
selected = {
selection.check.id for selection in resolve_check_selections(manifest, [path], "ci")
}
self.assertIn("plan-catalog-contract", selected)
def test_explicit_check_ids_preserve_manifest_commands(self):
manifest = Manifest(
checks=(
Check(
id="portable",
command=("python3", "check.py"),
triggers=("never/**",),
lanes=("ci",),
reason="test",
),
),
exempt=(),
)
selections = resolve_explicit_checks(
manifest,
["portable"],
"ci",
include_pr_body_checks=True,
platform="windows",
)
self.assertEqual([selection.check.id for selection in selections], ["portable"])
with self.assertRaisesRegex(ValueError, "unknown check id"):
resolve_explicit_checks(
manifest,
["missing"],
"ci",
include_pr_body_checks=True,
platform="windows",
)
def test_skipped_platform_checks_reports_macos_on_linux(self):
manifest = Manifest(
checks=(
Check(
id="mac-only", command=("true",), triggers=("all",), lanes=("ci",), reason="t", platforms=("macos",)
),
),
exempt=(),
)
skipped = skipped_platform_checks(manifest, ["any/file"], "ci", "linux")
self.assertEqual([c.id for c in skipped], ["mac-only"])
def test_invalid_platform_rejected_by_validation(self):
manifest = Manifest(
checks=(
Check(id="bad", command=("true",), triggers=("all",), lanes=("ci",), reason="t", platforms=("plan9",)),
),
exempt=(),
)
errors = validate_manifest(manifest, REPO_ROOT)
self.assertTrue(any("invalid platforms" in e for e in errors))
def test_detect_platform_maps_windows(self):
with patch("run_checks._platform_mod.system", return_value="Windows"):
self.assertEqual(detect_platform(), "windows")
def test_detect_platform_returns_known_value(self):
plat = detect_platform()
self.assertIn(plat, VALID_PLATFORMS - {"all"})
class DeferredMarkerTests(unittest.TestCase):
def test_git_content_reads_are_utf8(self) -> None:
module = load_deferred_marker_module()
completed = subprocess.CompletedProcess([], 0, stdout="", stderr="")
with patch.object(module.subprocess, "run", return_value=completed) as run:
self.assertEqual(module.added_lines("origin/main", "fixture.txt"), [])
self.assertEqual(module.marker_counts_at_base("origin/main", "fixture.txt"), Counter())
content_reads = [call for call in run.call_args_list if call.args[0][1] in {"diff", "show"}]
self.assertEqual(len(content_reads), 2)
for call in content_reads:
self.assertEqual(call.kwargs.get("encoding"), "utf-8")
def test_new_marker_requires_tracking_issue(self) -> None:
module = load_deferred_marker_module()
marker = "TO" + "DO"
with tempfile.TemporaryDirectory(dir=REPO_ROOT, prefix=".manifest-marker-") as tmp:
root = Path(tmp)
candidate = root / "fixture.txt"
changed = root / "changed.txt"
relative = candidate.relative_to(REPO_ROOT).as_posix()
changed.write_text(f"{relative}\n", encoding="utf-8")
candidate.write_text(f"// {marker}: missing owner\n", encoding="utf-8")
with redirect_stdout(StringIO()), redirect_stderr(StringIO()):
self.assertEqual(module.check_new_markers("origin/main", changed), 1)
candidate.write_text(f"// {marker}(#9448): owned follow-up\n", encoding="utf-8")
with redirect_stdout(StringIO()), redirect_stderr(StringIO()):
self.assertEqual(module.check_new_markers("origin/main", changed), 0)
def test_marker_guard_ignores_product_text_and_reformatted_existing_comments(self) -> None:
module = load_deferred_marker_module()
self.assertIsNone(module.marker_signature('let status = item.completed ? "done" : "todo"'))
original = " // TODO: Implement when adding watchOS support"
reformatted = " // TODO: Implement when adding watchOS support"
signature = module.marker_signature(original)
assert signature is not None
self.assertEqual(
module.new_marker_violations([(88, reformatted)], Counter({signature: 1})),
[],
)
if __name__ == "__main__":
unittest.main()