Files
felhom.eu/documentation/audits/night2-2026-10-20/P2/redproof_r893.py
T

51 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Red-proof the R-893 option A tests: apply one mutation, run its test, expect FAIL, restore the file."""
import subprocess, sys
ROOT = "/mnt/5_hdd/felhom.eu/git/felhom-controller/controller"
U = ROOT + "/internal/backup/offbox_restore_undo.go"
R = ROOT + "/internal/backup/offbox_reconstitute.go"
CASES = [
("put-back skipped", U, " if volumesMoved {\n if err := m.putBack(stack, c); err != nil {",
" if false {\n if err := m.putBack(stack, c); err != nil {", "TestR893A_AFailedReplayPutsTheLiveVolumesBackExactly"),
("volume-replay branch without undo", R, "if definitionMoved || nVols > 0 || undo != nil {", "if definitionMoved || nVols > 0 {",
"TestR893A_AFailedVolumeReplayStillPutsBackWhenItCountedNothing"),
("fit check without the copy", R, "if free < need+volNeed {", "if free < need {", "TestR893A_TheCopyMustFitBeforeAnythingStops"),
("probe error ignored", U, " if pErr != nil {\n return 0, nil, pErr\n }", " if pErr != nil {\n continue\n }",
"TestR893A_AnUnmeasurableVolumeRefusesBeforeAnythingStops"),
("no drop on exit", R, " defer undo.drop(m, stack)\n", "", "TestR893A_ASuccessfulRestoreRemovesTheCopy"),
("copy not kept on a failed put-back", U, " c.keep = true\n", "", "TestR893A_AFailedPutBackHoldsTheAppAndKeepsTheCopy"),
("copy error ignored", R, " if cErr != nil {\n m.logger.Printf(\"[ERROR] [offbox] %s: the copy of the live volumes failed",
" if cErr != nil && false {\n m.logger.Printf(\"[ERROR] [offbox] %s: the copy of the live volumes failed",
"TestR893A_AFailedCopyRestoresNothingAndStartsTheApp"),
("slice-1 hold after the rollback", R,
" return res, m.putBackAfterFailedRestore(stack, iErr, liveDef, undo, res.VolumesReplayed > 0, res.FilesPlaced, restartStack, \"err.backup.db_restore_failed_held_mixed\")",
" m.holdAppAfterMixedRestore(stack, iErr, liveDef)\n return res, util.MsgError(\"err.backup.db_restore_failed_held_mixed\", stack)",
"TestR893_AVersionChangeThenAFailedReplayStartsTheAppAtItsLiveDefinition"),
("DB-start branch only restarts", R,
" return res, m.putBackAfterFailedRestore(stack, err, liveDef, undo, res.VolumesReplayed > 0, res.FilesPlaced, restartStack, \"err.backup.restore_failed_held_mixed\")",
" _ = restartStack()\n return res, err",
"TestR893_AVersionChangeThenAFailedDBStartStartsTheAppAtItsLiveDefinition"),
]
bad = 0
for name, path, old, new, test in CASES:
src = open(path).read()
if src.count(old) != 1:
print("SETUP-ERROR", name, "match count", src.count(old)); bad += 1; continue
open(path, "w").write(src.replace(old, new))
try:
p = subprocess.run(["go", "test", "./internal/backup/", "-run", "^" + test + "$", "-count=1"], cwd=ROOT,
capture_output=True, text=True)
out = p.stdout + p.stderr
line = next((l.strip() for l in out.splitlines() if "_test.go:" in l), out.strip().splitlines()[-1] if out.strip() else "")
verdict = "RED (good)" if p.returncode != 0 else "STILL GREEN (BAD)"
if p.returncode == 0:
bad += 1
print("%-38s %-18s %s" % (name, verdict, line[:220]))
finally:
open(path, "w").write(src)
print("restored; failures-to-go-red:", bad)
sys.exit(1 if bad else 0)