fix(scripts): the mutation harness must not churn source mtimes
It rewrites a tracked file and restores it byte-for-byte — but the restore bumped the mtime, and in this repo that is not cosmetic. The repo IS the deployment root and nothing takes effect until the service restarts, so 'is :8090 stale?' is answered by comparing the service's start time against source mtimes. A tool that moves those without changing a byte makes that check lie: it reported the live service 16 minutes stale while it was serving current code. Restores atime/mtime with os.utime, with a test whose defeating change is dropping that line. Found by using the staleness check for real, not by review. 649 green; 12/12 U7 falsifiers still proved.
This commit is contained in:
@@ -84,6 +84,7 @@ def check(mutation: dict, repo: Path = REPO) -> tuple[bool, str]:
|
||||
return False, f"anchor not found in {mutation['file']} — the table has drifted"
|
||||
|
||||
INFLIGHT.write_text(f"{path}\n")
|
||||
stat = path.stat() # mtime included; see the restore below
|
||||
try:
|
||||
path.write_text(src.replace(mutation["old"], mutation["new"], 1))
|
||||
red = run(test, repo) != 0
|
||||
@@ -92,6 +93,13 @@ def check(mutation: dict, repo: Path = REPO) -> tuple[bool, str]:
|
||||
# Verified, not assumed: a restore that silently failed would leave a
|
||||
# mutation in a tracked file and the next run would measure it.
|
||||
assert path.read_text() == src, f"RESTORE FAILED for {path} — fix by hand"
|
||||
# ⚠ AND THE MTIME, which matters more here than it would elsewhere.
|
||||
# This repo IS its own deployment root and nothing takes effect until
|
||||
# the service restarts, so "is :8090 stale?" is answered by comparing
|
||||
# the service's start time against source mtimes. A tool that churns
|
||||
# those mtimes without changing a byte makes that check lie — it
|
||||
# reported the live service 16 minutes stale when it was current.
|
||||
os.utime(path, ns=(stat.st_atime_ns, stat.st_mtime_ns))
|
||||
INFLIGHT.unlink(missing_ok=True)
|
||||
|
||||
return red, "" if red else "VACUOUS — stayed green under the change it forbids"
|
||||
|
||||
@@ -108,3 +108,23 @@ def test_the_source_is_restored_even_when_the_mutation_proves(tmp_path):
|
||||
check({"label": "flip", "file": "mod.py", "test": "test_probe.py::test_f",
|
||||
"old": "return 2", "new": "return 3"}, repo=repo)
|
||||
assert (repo / "mod.py").read_text() == before
|
||||
|
||||
|
||||
def test_a_reverted_file_keeps_its_mtime(tmp_path):
|
||||
"""The repo IS its own deployment root: nothing takes effect until the
|
||||
service restarts, so "is :8090 stale?" is answered by comparing the
|
||||
service's start time against source mtimes. A tool that rewrites a file
|
||||
with identical bytes still bumps its mtime and makes that check lie — it
|
||||
reported the live service 16 minutes stale when it was current.
|
||||
|
||||
Defeating change: dropping the os.utime in the restore."""
|
||||
import os
|
||||
|
||||
repo = _tree(tmp_path, "def f():\n return 2\n",
|
||||
"def test_f():\n assert f() == 2\n")
|
||||
mod = repo / "mod.py"
|
||||
os.utime(mod, (1_000_000_000, 1_000_000_000))
|
||||
before = mod.stat().st_mtime_ns
|
||||
check({"label": "flip", "file": "mod.py", "test": "test_probe.py::test_f",
|
||||
"old": "return 2", "new": "return 3"}, repo=repo)
|
||||
assert mod.stat().st_mtime_ns == before
|
||||
|
||||
Reference in New Issue
Block a user