//go:build unix package hostguard import ( "context" "errors" "github.com/carlosframework/platform/internal/hostclaim" "testing" "time" ) func TestColdHandoverBarrierSurvivesFailureAndBlocksActivateBypass(t *testing.T) { f, prior, _ := fenceFixture(t) f.obs.Claim.Op.Kind = hostclaim.KindMoving if _, err := f.g.BeginFence(t.Context(), prior); err != nil { t.Fatal(err) } if err := f.g.CompleteFence(t.Context(), prior, []byte("root receipt"), time.Now().UTC(), func(context.Context, FenceTarget, []byte, time.Time) error { return nil }); err != nil { t.Fatal(err) } barrier := prior barrier.FenceID = "handover" barrier.Stamp = 17 barrier.Session = 17 f.obs.Claim.Holder.Stamp = 17 f.obs.Claim.Holder.Session = 17 if err := f.g.BeginColdHandover(t.Context(), prior, barrier, allow); err != nil { t.Fatal(err) } if err := f.g.Activate(t.Context(), prior.Host, prior.Box, nil); err != nil { t.Fatal(err) } called := false if err := f.g.With(t.Context(), prior.Host, Captured{Incarnation: prior.Incarnation, Stamp: 17}, allow, func() error { called = true; return nil }); !errors.Is(err, ErrFenced) || called { t.Fatalf("barrier bypass = %v", err) } crash := errors.New("crash before handover commit") if err := f.g.CompleteColdHandover(t.Context(), barrier, false, allow, func() error { return crash }); !errors.Is(err, crash) { t.Fatal(err) } if err := f.g.With(t.Context(), prior.Host, Captured{Incarnation: prior.Incarnation, Stamp: 17}, allow, func() error { called = true; return nil }); !errors.Is(err, ErrFenced) || called { t.Fatalf("failed commit lost barrier: %v", err) } if err := f.g.CompleteColdHandover(t.Context(), barrier, false, allow, func() error { return nil }); err != nil { t.Fatal(err) } if err := f.g.With(t.Context(), prior.Host, Captured{Incarnation: prior.Incarnation, Stamp: 17}, allow, func() error { called = true; return nil }); err != nil || !called { t.Fatal(err) } }