package hostops import ( "context" "errors" "testing" "time" "github.com/carlosframework/platform/internal/lease" "github.com/carlosframework/platform/internal/lease/leasetest" "github.com/carlosframework/platform/internal/release" ) type delayedPurgeDelete struct { lease.VersionedStore control release.Store key string replacement string calls int } func (d *delayedPurgeDelete) DeleteVersion(ctx context.Context, bucket, key, version string) error { d.calls++ if d.replacement != "" { _, tag, err := d.control.Get(ctx, d.key) if err != nil { return err } if _, err := d.control.Put(ctx, d.key, []byte(d.replacement), tag); err != nil { return err } d.replacement = "" } return d.VersionedStore.DeleteVersion(ctx, bucket, key, version) } func TestClaimPurgeExactSweep(t *testing.T) { ctx := t.Context() control := release.NewDirStore(t.TempDir()) versions := leasetest.NewVersionedBucket() versions.AddBucket("control") key := "apps/bab/demo/payload" old := versions.Put("control", key, []byte("same")) journal := PurgeJournal{V: 1, Purge: Purge{ID: "p", Phase: "retired"}, AppID: "old", Account: "bab", App: "demo", Hosts: map[string]PurgeHost{}} w := seedPurge(t, ctx, control, time.Now(), journal) if err := PreparePurgeSweep(ctx, control, w, versions, "control", "bab", "demo", "p", "old"); err != nil { t.Fatal(err) } successor := versions.Put("control", key, []byte("same")) if old == successor { t.Fatal("test requires distinct versions") } if err := DeletePurgeSweep(ctx, control, w, versions, "control", "bab", "demo", "p", "old"); err != nil { t.Fatal(err) } if _, err := versions.GetVersion(ctx, "control", key, old); !errors.Is(err, lease.ErrMirrorNotFound) { t.Fatalf("old version: %v", err) } if _, err := versions.GetVersion(ctx, "control", key, successor); err != nil { t.Fatalf("successor deleted: %v", err) } if err := VerifyPurgeSweep(ctx, control, w, versions, "control", "bab", "demo", "p", "old"); !errors.Is(err, ErrPending) { t.Fatalf("unexpected new key must block completion: %v", err) } } func TestClaimPurgeSweepDoneCannotRestart(t *testing.T) { ctx := t.Context() control := release.NewDirStore(t.TempDir()) versions := leasetest.NewVersionedBucket() versions.AddBucket("control") j := PurgeJournal{V: 1, Purge: Purge{ID: "p", Phase: "done"}, AppID: "old", Account: "bab", App: "demo", Hosts: map[string]PurgeHost{}} w := seedPurge(t, ctx, control, time.Now(), j) if err := PreparePurgeSweep(ctx, control, w, versions, "control", "bab", "demo", "p", "old"); !errors.Is(err, ErrPending) { t.Fatalf("done: %v", err) } }