29d3c533aa
gates / gates (push) Successful in 28s
Red-proofs RP43, RP44. MinAgent 0.131.0 (unchanged). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
32 lines
1.6 KiB
Go
32 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/quiesce"
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/stacks"
|
|
)
|
|
|
|
// R-721 (v0.283.1) — the seam, not the rule. The rule is pinned in internal/backup and internal/quiesce with
|
|
// fakes that DO answer WantsStopped; production hands the backup manager a *stackAdapter and the quiesce loop
|
|
// a *stacks.Manager, and a type that does not answer makes the check silently skip. Measured live on 9202
|
|
// 2026-09-30 with v0.283.0: the adapter lacked the method and the dump restarted a stopped app.
|
|
// COMPANION RED-PROOF: delete stackAdapter.WantsStopped → this test fails.
|
|
func TestR721_TheBackupsStackProviderAnswersWantsStopped(t *testing.T) {
|
|
var prov interface{} = &stackAdapter{}
|
|
if _, ok := prov.(interface{ WantsStopped(string) bool }); !ok {
|
|
t.Fatal("the backup manager's production stack provider does not answer WantsStopped — a household Stop is undone by the volume dump (R-721)")
|
|
}
|
|
// The quiesce loop is handed the stacks manager itself (main.go quiesce.Options{Stacks: stackMgr}).
|
|
// The startup crash recovery is handed gatedAppStopStarter{inner: stackMgr} (main.go SetStarter).
|
|
var gs interface{} = gatedAppStopStarter{inner: (*stacks.Manager)(nil)}
|
|
if _, ok := gs.(interface{ WantsStopped(string) bool }); !ok {
|
|
t.Fatal("the crash recovery's starter does not answer WantsStopped (R-721)")
|
|
}
|
|
var mgr *stacks.Manager
|
|
var _ quiesce.Stacks = mgr
|
|
if _, ok := interface{}(mgr).(interface{ WantsStopped(string) bool }); !ok {
|
|
t.Fatal("the quiesce loop's production Stacks does not answer WantsStopped (R-721)")
|
|
}
|
|
}
|