Files
felhom-controller/controller/cmd/controller/r1286_hold_why_test.go
T

39 lines
1.8 KiB
Go

package main
import (
"strings"
"testing"
"gitea.dooplex.hu/admin/felhom-controller/internal/settings"
)
// R-1286: demo-hp's Kimai was held by the crash-loop guard (reason unhealthy_stop, 2026-10-14) and the boot sweep, the
// start gate and `--restore-holds` all said „held after a failed restore whose rollback also failed" for 11 days.
// Each reason now says what it is and what lifts it.
// RED-PROOF: holdWhy back to the old two-way branch → the unhealthy_stop, restore_mixed and putback_pending cases fail.
func TestR1286_EveryHoldReasonSaysWhatItIs(t *testing.T) {
sett := holdTestSettings(t)
g := driveStartGate{sett: sett}
for _, tc := range []struct {
hold settings.RestoreHold
want string
}{
{settings.RestoreHold{Stack: "kimai", At: "2026-10-14T09:06:31Z", Reason: settings.HoldReasonUnhealthyStop, UnhealthyKind: "crash_loop"}, "stopped by the box for a crash loop"},
{settings.RestoreHold{Stack: "a", At: "t", Reason: settings.HoldReasonUpdateFailed}, "failed update"},
{settings.RestoreHold{Stack: "b", At: "t", Reason: settings.HoldReasonRestoreMixed}, "off-site restore failed its database replay"},
{settings.RestoreHold{Stack: "c", At: "t", Reason: settings.HoldReasonPutBackPending}, "pre-restore copy is poured back"},
{settings.RestoreHold{Stack: "d", At: "t"}, "failed restore whose rollback also failed"},
} {
if err := sett.SetRestoreHold(tc.hold); err != nil {
t.Fatal(err)
}
ok, why := g.MayStart(tc.hold.Stack)
if ok || !strings.Contains(why, tc.want) {
t.Fatalf("%s (reason %q): the gate says %q, want it to contain %q", tc.hold.Stack, tc.hold.Reason, why, tc.want)
}
if tc.hold.Reason != "" && strings.Contains(why, "failed restore whose rollback also failed") {
t.Fatalf("%s: a %q hold must not read as a failed restore: %q", tc.hold.Stack, tc.hold.Reason, why)
}
}
}