package console import ( "bytes" "context" "crypto/ed25519" "crypto/rand" "log" "strings" "testing" "time" "github.com/carlosframework/platform/internal/hostops" "github.com/carlosframework/platform/internal/release" ) func TestConfigureClaimBackfillMissingContractDoesNotFailStartup(t *testing.T) { for _, missing := range []string{"store", "bucket", "public-key"} { t.Run(missing, func(t *testing.T) { s := &Server{cfg: Config{HostClaim: true, Releases: release.NewDirStore(t.TempDir()), Bucket: "bucket", ReleasePub: make(ed25519.PublicKey, ed25519.PublicKeySize)}} switch missing { case "store": s.cfg.Releases = nil case "bucket": s.cfg.Bucket = "" case "public-key": s.cfg.ReleasePub = nil } var logs bytes.Buffer previous := log.Writer() log.SetOutput(&logs) t.Cleanup(func() { log.SetOutput(previous) }) if err := s.ConfigureClaimBackfill(); err != nil { t.Errorf("configuration failed startup: %v", err) } if s.cfg.HostClaimOps != nil || !strings.Contains(logs.String(), hostops.ErrContract.Error()) { t.Fatalf("ops=%v log=%q", s.cfg.HostClaimOps, logs.String()) } s.StartClaimRecoveryPass(context.Background()) }) } } func TestClaimBackfillQuietWithoutAdoptingPlan(t *testing.T) { for _, phase := range []string{"absent", "collecting", "done", "future"} { t.Run(phase, func(t *testing.T) { pub, key, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } store := release.NewDirStore(t.TempDir()) if phase != "absent" { raw, err := release.SignRootEnvelope(release.RootSigner(key), hostops.BackfillPlan{V: 1, ID: "backfill", Phase: phase, CreatedAt: time.Now()}) if err != nil { t.Fatal(err) } if _, err := store.Put(context.Background(), hostops.BackfillKey, raw, ""); err != nil { t.Fatal(err) } } s := &Server{cfg: Config{HostClaim: true, Releases: store, Bucket: "bucket", ReleasePub: pub}} if err := s.ConfigureClaimBackfill(); err != nil { t.Fatal(err) } ops := s.cfg.HostClaimOps if ops == nil { t.Fatal("backfill not configured") } if err := s.ConfigureClaimBackfill(); err != nil || s.cfg.HostClaimOps != ops { t.Fatal("controller replaced", err) } var logs bytes.Buffer previous := log.Writer() log.SetOutput(&logs) t.Cleanup(func() { log.SetOutput(previous) }) ctx, cancel := context.WithCancel(context.Background()) cancel() s.StartClaimRecoveryPass(ctx) if logs.Len() != 0 { t.Fatalf("inactive backfill logged: %s", &logs) } }) } }