package console import ( "context" "testing" "time" "github.com/carlosframework/platform/internal/plans" ) func readMarker(t *testing.T, fx *consoleFixture) (*plans.Marker, string) { t.Helper() m, etag, err := plans.GetMarker(context.Background(), fx.rel) if err != nil { t.Fatal(err) } return m, etag } func TestPublishPlansMarkerOffAndAbsentWritesNothing(t *testing.T) { fx := newConsoleFixture(t) fx.srv.PublishPlansMarker(context.Background()) if m, _ := readMarker(t, fx); m != nil { t.Fatalf("wrote a marker with no catalog: %+v", m) } } func TestPublishPlansMarkerEnables(t *testing.T) { fx := newConsoleFixture(t) fx.srv.cfg.PlanCatalog = examplePlanCatalog(t) fx.srv.PublishPlansMarker(context.Background()) m, _ := readMarker(t, fx) if m == nil || !m.Enabled || m.CatalogID != fx.srv.cfg.PlanCatalog.ID() { t.Fatalf("marker %+v", m) } } func TestPublishPlansMarkerIsIdempotent(t *testing.T) { fx := newConsoleFixture(t) fx.srv.cfg.PlanCatalog = examplePlanCatalog(t) fx.srv.PublishPlansMarker(context.Background()) _, first := readMarker(t, fx) fx.srv.PublishPlansMarker(context.Background()) if _, second := readMarker(t, fx); second != first { t.Fatal("an up-to-date marker was rewritten") } } func TestPublishPlansMarkerFollowsACatalogChange(t *testing.T) { fx := newConsoleFixture(t) fx.srv.cfg.PlanCatalog = examplePlanCatalog(t) fx.srv.PublishPlansMarker(context.Background()) next := bumpedCatalog(t, "2026-10-22-v2", "4") fx.srv.cfg.PlanCatalog = next fx.srv.PublishPlansMarker(context.Background()) if m, _ := readMarker(t, fx); m.CatalogID != next.ID() { t.Fatalf("marker %+v, want catalog %s", m, next.ID()) } } func TestPublishPlansMarkerDisablesWhenCatalogRemoved(t *testing.T) { fx := newConsoleFixture(t) fx.srv.cfg.PlanCatalog = examplePlanCatalog(t) fx.srv.PublishPlansMarker(context.Background()) fx.srv.cfg.PlanCatalog = nil fx.srv.PublishPlansMarker(context.Background()) if m, _ := readMarker(t, fx); m == nil || m.Enabled { t.Fatalf("marker %+v, want disabled", m) } } // Astra plans-2 finding 1: a bucket failure at start must not leave the // marker in the wrong state for the life of the console. The worker retries // until the marker is right. func TestPublishPlansMarkerRetriesUntilDisabled(t *testing.T) { fx := newConsoleFixture(t) fx.srv.cfg.PlanCatalog = examplePlanCatalog(t) fx.srv.PublishPlansMarker(context.Background()) defer func(d time.Duration) { plansMarkerRetry = d }(plansMarkerRetry) plansMarkerRetry = time.Millisecond fp := &planFailingPuts{Store: fx.rel} fp.n.Store(3) // the first three writes fail fx.srv.cfg.Releases = fp fx.srv.cfg.PlanCatalog = nil ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() fx.srv.PublishPlansMarker(ctx) fx.srv.cfg.Releases = fp.Store if m, _ := readMarker(t, fx); m == nil || m.Enabled { t.Fatalf("marker %+v after transient write failures, want disabled", m) } } func TestPublishPlansMarkerStopsWithItsContext(t *testing.T) { fx := newConsoleFixture(t) fx.srv.cfg.PlanCatalog = examplePlanCatalog(t) defer func(d time.Duration) { plansMarkerRetry = d }(plansMarkerRetry) plansMarkerRetry = time.Millisecond fp := &planFailingPuts{Store: fx.rel} fp.n.Store(1 << 30) // never succeeds fx.srv.cfg.Releases = fp ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) defer cancel() done := make(chan struct{}) go func() { fx.srv.PublishPlansMarker(ctx); close(done) }() select { case <-done: case <-time.After(5 * time.Second): t.Fatal("PublishPlansMarker kept retrying after its context ended") } }