Files
kandev/apps/backend/internal/backendapp/startup_order_test.go
T
2026-08-24 19:35:07 +00:00

95 lines
3.2 KiB
Go

package backendapp
import (
"errors"
"reflect"
"testing"
)
func TestStartOrchestratorAndAutomationConsumersOrder(t *testing.T) {
var order []string
err := startOrchestratorAndAutomationConsumers(
func() error { order = append(order, "bind"); return nil },
func() error {
order = append(order, "orchestrator")
return nil
},
func() { order = append(order, "automation") },
func() { order = append(order, "github") },
)
if err != nil {
t.Fatalf("start sequence returned error: %v", err)
}
want := []string{"bind", "orchestrator", "automation", "github"}
if !reflect.DeepEqual(order, want) {
t.Fatalf("start order = %v, want %v", order, want)
}
}
func TestStartOrchestratorAndAutomationConsumersStopsAfterOrchestratorFailure(t *testing.T) {
startErr := errors.New("orchestrator unavailable")
var automationStarted, githubStarted bool
err := startOrchestratorAndAutomationConsumers(
func() error { return nil },
func() error { return startErr },
func() { automationStarted = true },
func() { githubStarted = true },
)
if !errors.Is(err, startErr) {
t.Fatalf("start sequence error = %v, want %v", err, startErr)
}
if automationStarted || githubStarted {
t.Fatalf("downstream consumers started after orchestrator failure: automation=%v github=%v", automationStarted, githubStarted)
}
}
// TestStartOrchestratorAndAutomationConsumersStopsAfterBindFailure pins the
// bind-before-startup ordering invariant (docs/plans/startup-listener-before-
// recovery/task-03-ordering-guard.md): a bind failure must short-circuit
// before the orchestrator, automation, or GitHub poller ever start, exactly
// like an orchestrator-start failure does today.
func TestStartOrchestratorAndAutomationConsumersStopsAfterBindFailure(t *testing.T) {
bindErr := errors.New("bind unavailable")
var orchestratorStarted, automationStarted, githubStarted bool
err := startOrchestratorAndAutomationConsumers(
func() error { return bindErr },
func() error { orchestratorStarted = true; return nil },
func() { automationStarted = true },
func() { githubStarted = true },
)
if !errors.Is(err, bindErr) {
t.Fatalf("start sequence error = %v, want %v", err, bindErr)
}
if orchestratorStarted || automationStarted || githubStarted {
t.Fatalf("downstream steps started after bind failure: orchestrator=%v automation=%v github=%v",
orchestratorStarted, automationStarted, githubStarted)
}
}
// TestPublishReadinessFlipsReadyBeforeSwappingHandler is the regression test
// for R1-2 (docs/specs/health-endpoint-version/spec.md's 2026-08-22
// amendment): startGatewayAndServe must flip the readiness flag before
// swapping in the fully wired router, never the reverse, or a request racing
// the swap could observe the real router with ready still false and get a
// spurious 503 — recreating the exact flap docs/specs/startup-listener-
// before-recovery/spec.md exists to prevent.
func TestPublishReadinessFlipsReadyBeforeSwappingHandler(t *testing.T) {
var order []string
publishReadiness(
func() { order = append(order, "ready") },
func() { order = append(order, "handler") },
)
want := []string{"ready", "handler"}
if !reflect.DeepEqual(order, want) {
t.Fatalf("publishReadiness order = %v, want %v", order, want)
}
}