175ecfcdd2
gates / gates (push) Successful in 30s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
55 lines
3.3 KiB
Python
55 lines
3.3 KiB
Python
import subprocess, shutil, sys
|
|
M = [
|
|
("unknown, never empty (parser)", "internal/sysfacts/sysfacts.go",
|
|
"out.Guest.Containerd, out.Guest.LiveRestore = orUnknown(out.Guest.Containerd), orUnknown(out.Guest.LiveRestore)",
|
|
"out.Guest.Containerd, out.Guest.LiveRestore = out.Guest.Containerd, out.Guest.LiveRestore",
|
|
"./internal/sysfacts/", "TestParse_AbsentAndPartialAreUnknown"),
|
|
("Docker never auto-approved", "internal/osupdates/service.go",
|
|
"var Layers = []string{LayerGuest, LayerHost}", "var Layers = []string{LayerGuest, LayerHost, LayerDocker}",
|
|
"./internal/osupdates/", "TestDocker_NeverAutoApproved"),
|
|
("Docker button needs 2 nights", "internal/osupdates/service.go",
|
|
"\tcase need == 0:\n\t\tneed = 2", "\tcase need == 0:\n\t\tneed = 1",
|
|
"./internal/osupdates/", "TestDocker_ApproveNeedsTwoHealthyNightsOnEveryRing0Box"),
|
|
("a Docker approval nudges no box", "internal/osupdates/service.go",
|
|
"if s.Bump != nil && layer != LayerDocker {", "if s.Bump != nil {",
|
|
"./internal/osupdates/", "TestDocker_ApproveNeedsTwoHealthyNightsOnEveryRing0Box"),
|
|
("crash event once per boot", "internal/api/crash.go",
|
|
"\t\tif known[b] {\n\t\t\tcontinue\n\t\t}", "\t\tif false {\n\t\t\tcontinue\n\t\t}",
|
|
"./internal/api/", "TestCheckCrash_EventsOncePerFact"),
|
|
("first sighting is quiet", "internal/api/crash.go",
|
|
"\t\tif first {\n\t\t\treturn\n\t\t}\n\t\td := map", "\t\td := map",
|
|
"./internal/api/", "TestCheckCrash_EventsOncePerFact"),
|
|
("page: unknown cell", "internal/web/system.go",
|
|
'if s == "" || s == sysfacts.Unknown {', 'if false {',
|
|
"./internal/web/", "TestSystemPage_FullPartialUnknown"),
|
|
("page: Docker button gate", "internal/web/templates/system.html",
|
|
'(not .Approved) (eq .Waiting "")}}', '(not .Approved)}}',
|
|
"./internal/web/", "TestSystemPage_DockerButtonOnlyWhenReady"),
|
|
("buttons need the operator login", "internal/web/server.go",
|
|
'if r.URL.Path == "/login" || isPublicBindPath(r.URL.Path) {', 'if r.URL.Path == "/login" || isPublicBindPath(r.URL.Path) || strings.HasPrefix(r.URL.Path, "/os/") {',
|
|
"./internal/web/", "TestSystemButtons_NeedTheOperatorLogin"),
|
|
("Hosts column", "internal/web/templates/hosts.html",
|
|
"<th>Proxmox / kernel</th>", "<th>Proxmox</th>",
|
|
"./internal/web/", "TestHostsPage_ProxmoxKernelColumn"),
|
|
]
|
|
ok = True
|
|
for name, f, old, new, pkg, test in M:
|
|
src = open(f).read()
|
|
assert src.count(old) == 1, (name, src.count(old))
|
|
shutil.copy(f, f + ".bak")
|
|
open(f, "w").write(src.replace(old, new))
|
|
r = subprocess.run(["go", "test", pkg, "-run", "^" + test + "$", "-v", "-count=1"], capture_output=True, text=True)
|
|
shutil.move(f + ".bak", f)
|
|
out = r.stdout + r.stderr
|
|
ran = ("=== RUN " + test) in out
|
|
failed = ("--- FAIL: " + test) in out
|
|
v = "CAUGHT" if ran and failed else "NOT CAUGHT"
|
|
ok &= v == "CAUGHT"
|
|
print(f"[{v}] {name}: {f} mutated; {test} ran={ran} failed={failed}")
|
|
for l in out.splitlines():
|
|
if "_test.go:" in l or "build failed" in l or l.startswith("#"):
|
|
print(" " + l.strip()[:200])
|
|
r = subprocess.run(["go", "test", "./internal/sysfacts/", "./internal/osupdates/", "./internal/api/", "./internal/web/", "-count=1"], capture_output=True, text=True)
|
|
print("after restore:", r.stdout.strip().replace("\n", " | "), "rc=", r.returncode)
|
|
sys.exit(0 if ok and r.returncode == 0 else 1)
|