package mail import ( "context" "errors" "sync" "testing" "github.com/carlosframework/platform/internal/release" ) // okAdmitter admits nothing and refuses nothing: these tests exercise the gate. type okAdmitter struct{} func (okAdmitter) AdmitClaimMailApps(ctx context.Context, _ ClaimMailHold, _ []ClaimMailApp) (ClaimMailAdmission, error) { var n int var mu sync.Mutex return fixtureAdmission{ctx: ctx, released: &n, mu: &mu}, nil } func TestClaimMailGateSerializesAndRetainsUncertain(t *testing.T) { ctx := t.Context() base := release.NewDirStore(t.TempDir()) gate := &memGate{State: "free"} one, err := NewClaimMailStore(base, gate, okAdmitter{}, ClaimMailOwner{Console: "c", Enrollment: "e", Controller: "one"}) if err != nil { t.Fatal(err) } two, err := NewClaimMailStore(base, gate, okAdmitter{}, ClaimMailOwner{Console: "c", Enrollment: "e", Controller: "two"}) if err != nil { t.Fatal(err) } calls := 0 if err := WithClaimMailResource(ctx, one, func(held context.Context) error { if err := WithClaimMailResource(ctx, two, func(context.Context) error { calls++; return nil }); !errors.Is(err, ErrClaimMailPending) { t.Fatalf("competing gate: %v", err) } return WithClaimMailResource(held, one, func(context.Context) error { calls++; return nil }) }); err != nil { t.Fatal(err) } if calls != 1 { t.Fatalf("calls=%d", calls) } uncertain := errors.New("backend outcome unknown") if err := WithClaimMailResource(ctx, two, func(held context.Context) error { markClaimMailDirty(held); return uncertain }); !errors.Is(err, uncertain) { t.Fatal(err) } if g := gate.snapshot(); g.State != "held" { t.Fatalf("uncertain call released the gate: %+v", &g) } if err := WithClaimMailResource(ctx, one, func(context.Context) error { t.Fatal("uncertain owner replaced"); return nil }); !errors.Is(err, ErrClaimMailPending) { t.Fatal(err) } } func TestClaimMailGateFlagOffWritesNothing(t *testing.T) { ctx := t.Context() base := release.NewDirStore(t.TempDir()) calls := 0 if err := WithClaimMailResource(ctx, base, func(context.Context) error { calls++; return nil }); err != nil { t.Fatal(err) } keys, err := base.List(ctx, "") if err != nil { t.Fatal(err) } if calls != 1 || len(keys) != 0 { t.Fatalf("calls=%d keys=%v", calls, keys) } }