package host import ( "context" "github.com/carlosframework/platform/internal/hostguard" "testing" ) func TestClaimStopProducerFenceJoinsAndDenies(t *testing.T) { _, req, _ := claimStopFixture(t) target := hostguard.FenceTarget{Host: req.Host, Incarnation: req.Incarnation, Stamp: req.InstallationStamp, Session: req.WriterSession, Box: req.Box, Enrollment: req.Enrollment, BootID: req.BootID, ControllerID: req.ControllerID} recorded := 0 p, err := NewClaimProducers(target, "start-42", func(context.Context, hostguard.FenceTarget, string) error { recorded++; return nil }) if err != nil { t.Fatal(err) } child, finish, err := p.Register(t.Context(), target, "replication") if err != nil { t.Fatal(err) } done := make(chan struct{}) go func() { defer close(done); <-child.Done(); finish(nil) }() ack, err := p.DrainClaim(t.Context(), req, "fence") if err != nil { t.Fatal(err) } <-done if len(ack.ProducerIDs) != 1 || ack.ProducerIDs[0] != "replication" || recorded != 1 { t.Fatalf("ack=%+v records=%d", ack, recorded) } if _, _, err := p.Register(t.Context(), target, "late"); err == nil { t.Fatal("producer admitted after fence") } } type exactFixtureInventory struct{ StopInventoryReader } func (r exactFixtureInventory) ReadExactStopInventory(ctx context.Context, target hostguard.FenceTarget) (StopInventory, error) { return r.ReadStopInventory(ctx, target.Host) } func TestClaimStopCleanupUsesDurableFenceDuringOutage(t *testing.T) { c, req, store := claimStopFixture(t) drainer := c.Drainer c.Drainer = stopDrainFunc(func(context.Context, StopRequest, string) (DrainAcknowledgement, error) { return DrainAcknowledgement{}, ErrClaimStopUnavailable }) if _, err := c.FenceAndStop(t.Context(), req); err == nil { t.Fatal("initial drain should fail") } c.Drainer = drainer c.Inventory = exactFixtureInventory{c.Inventory} c.Claims = stopClaimReader{} store.err = ErrClaimStopUnavailable req.Cleanup = true result, err := c.FenceAndStop(t.Context(), req) if err != nil { t.Fatal(err) } if len(result.Bytes) == 0 { t.Fatal("missing local receipt") } if store.err == nil { t.Fatal("cleanup attempted remote publication") } req.WriterSession++ if _, err := c.FenceAndStop(t.Context(), req); err == nil { t.Fatal("cleanup widened session") } }