package backup import ( "io" "log" "testing" "time" "gitea.dooplex.hu/admin/felhom-controller/internal/settings" ) // R-671 (v0.272.0) — the undo copies kept by an update hold are removed when a restore lifts that hold; a // RESTORE hold (R-379) lifts nothing and removes nothing; an app a guarded update is moving is never touched. // // COMPANION RED-PROOF (REPORT.md): drop the undoCopyRemover call from clearUpdateHoldAfterRestore — this test // fails at "the lifted update hold's undo copies were left behind". func TestR671_RestoreThatClearsAnUpdateHoldRemovesItsUndoCopies(t *testing.T) { sett := slice4Settings(t) m := &Manager{logger: log.New(io.Discard, "", 0), settings: sett} removed := map[string]int{} m.SetUndoCopyRemover(func(s string) int { removed[s]++; return 3 }) _ = m.HoldAfterFailedUpdate("nextcloud", time.Now(), time.Now(), UpdateTierLocal) _ = sett.SetRestoreHold(settings.RestoreHold{Stack: "rst", At: "2026-08-22T14:00:00Z"}) m.clearUpdateHoldAfterRestore("nextcloud") m.clearUpdateHoldAfterRestore("rst") if removed["nextcloud"] != 1 { t.Fatalf("the lifted update hold's undo copies were left behind (remover calls: %v)", removed) } if removed["rst"] != 0 { t.Fatal("a restore hold is not lifted by a restore, so nothing of it may be removed") } // an app mid-update: its copies are the live undo — never removed _ = m.HoldAfterFailedUpdate("moving", time.Now(), time.Now(), UpdateTierLocal) m.SetUpdatingCheck(func(s string) bool { return s == "moving" }) m.clearUpdateHoldAfterRestore("moving") if removed["moving"] != 0 { t.Fatal("the undo copies of an app a guarded update is moving must never be removed") } }