R-1251: sync the restore copy's folders before the marker names it (a cut left undo.json as .tmp on Tester 1); the interrupted-restore record says the put-back waits, not 'run it again'. Commit only.
gates / gates (push) Successful in 1m24s
gates / gates (push) Successful in 1m24s
This commit is contained in:
@@ -318,3 +318,44 @@ func TestR1251_ACompletedRestoreDropsTheWaitingPutBack(t *testing.T) {
|
||||
t.Fatal("a completed restore must drop the waiting put-back hold")
|
||||
}
|
||||
}
|
||||
|
||||
// MEASURED on Tester 1 (2026-10-24, audits/restore-holes-2026-10-24/P1-tester1/): a power cut 2.1 s after the copy was
|
||||
// recorded left its journal as undo.json.tmp — the marker named a copy the start could not read. The copy's folders
|
||||
// must be synced BEFORE the marker names it. RED-PROOF: with the syncUndoDirs call removed from persistUndoForCrash this
|
||||
// fails on „no folder was synced before the marker named the copy".
|
||||
func TestR1251_TheCopyIsOnDiskBeforeTheMarkerNamesIt(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
marker := filepath.Join(root, "appstop-state.json")
|
||||
copyDir := filepath.Join(root, "drive", "backups", "restore-undo", "app", "20261024T171928Z")
|
||||
if err := os.MkdirAll(copyDir, 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
g := NewAppStopGuard(marker, log.New(io.Discard, "", 0))
|
||||
if err := g.Begin("unit-restore:app", ReasonUnitRestore, []string{"app"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m := &Manager{logger: log.New(io.Discard, "", 0), appStop: g}
|
||||
var synced []string
|
||||
markerNamedCopyAtSync := false
|
||||
orig := syncUndoDirs
|
||||
t.Cleanup(func() { syncUndoDirs = orig })
|
||||
syncUndoDirs = func(dir string) error {
|
||||
b, _ := os.ReadFile(marker)
|
||||
markerNamedCopyAtSync = strings.Contains(string(b), dir)
|
||||
synced = append(synced, dir)
|
||||
return orig(dir)
|
||||
}
|
||||
m.persistUndoForCrash("app", &liveVolumeCopy{dir: copyDir, copied: []string{"app_data"}})
|
||||
if len(synced) != 1 || synced[0] != copyDir {
|
||||
t.Fatalf("no folder was synced before the marker named the copy: %v", synced)
|
||||
}
|
||||
if markerNamedCopyAtSync {
|
||||
t.Fatal("the marker already named the copy when its folders were synced — the order is the fix")
|
||||
}
|
||||
if b, _ := os.ReadFile(marker); !strings.Contains(string(b), copyDir) {
|
||||
t.Fatal("the copy must still be recorded in the marker")
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(copyDir, "undo.json")); err != nil {
|
||||
t.Fatal("the journal must be in place")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user