carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package mail
2
3import (
4 "context"
5 "errors"
6 "reflect"
7 "sync"
8 "testing"
9)
10
11type fakeClaimAdmitter struct {
12 mu sync.Mutex
13 calls [][]ClaimMailApp
14 holds []ClaimMailHold
15 released int
16 refuse error
17}
18
19func (a *fakeClaimAdmitter) AdmitClaimMailApps(ctx context.Context, hold ClaimMailHold, apps []ClaimMailApp) (ClaimMailAdmission, error) {
20 a.mu.Lock()
21 defer a.mu.Unlock()
22 a.calls = append(a.calls, append([]ClaimMailApp(nil), apps...))
23 a.holds = append(a.holds, hold)
24 if a.refuse != nil {
25 return nil, a.refuse
26 }
27 return fixtureAdmission{ctx: ctx, released: &a.released, mu: &a.mu}, nil
28}
29
30func TestClaimMailRequiresProductionAdmitter(t *testing.T) {
31 f := newClaimDomainFixture(t, "alpha")
32 if _, err := NewClaimMailStore(f.log, f.mg, nil, claimTestOwner); !errors.Is(err, ErrClaimMailPending) {
33 t.Fatalf("constructor accepted a nil admitter: %v", err)
34 }
35 f.marked = ClaimMailStore{} // zero value: no gate, no admitter
36 rec, etag, err := GetDomain(f.ctx, f.base, claimTestAccount, claimTestDomain)
37 if err != nil {
38 t.Fatal(err)
39 }
40 before, tag := f.domainRaw()
41 f.reset()
42 if _, err = PutDomain(f.ctx, f.marked, claimTestAccount, rec, etag); !errors.Is(err, ErrClaimMailPending) {
43 t.Fatalf("missing provider: %v", err)
44 }
45 f.requireUntouched(before, tag)
46 if g := f.gate(); g.Revision != 0 {
47 t.Fatalf("gate used without an admitter: %+v", &g)
48 }
49}
50
51func TestClaimMailAdmitterReceivesSortedDedupedUnionOnce(t *testing.T) {
52 f := newClaimDomainFixture(t, "alpha", "beta")
53 a := &fakeClaimAdmitter{}
54 f.useAdmitter(a)
55 rec, etag, err := GetDomain(f.ctx, f.base, claimTestAccount, claimTestDomain)
56 if err != nil {
57 t.Fatal(err)
58 }
59 rec.Apps = []string{"gamma", "beta", "alpha", "beta"} // reordered, duplicated, one app added
60 if _, err = PutDomain(f.ctx, f.marked, claimTestAccount, rec, etag); err != nil {
61 t.Fatalf("PutDomain: %v", err)
62 }
63 want := []ClaimMailApp{{claimTestAccount, "alpha"}, {claimTestAccount, "beta"}, {claimTestAccount, "gamma"}}
64 if len(a.calls) != 1 || !reflect.DeepEqual(a.calls[0], want) {
65 t.Fatalf("admitter calls=%v want one call %v", a.calls, want)
66 }
67 if a.holds[0].Gate == "" || a.holds[0].Owner != claimTestOwner {
68 t.Fatalf("hold=%+v", a.holds[0])
69 }
70 if a.released != 1 {
71 t.Fatalf("released=%d", a.released)
72 }
73 if n := f.log.admissionGets(); n != 0 {
74 t.Fatalf("fallback read admissions %d times although a hook is installed", n)
75 }
76 f.requireGateFree()
77}
78
79func TestClaimMailAdmitterRefusalLeavesNothingBehind(t *testing.T) {
80 f := newClaimDomainFixture(t, "alpha", "beta")
81 a := &fakeClaimAdmitter{refuse: ErrClaimMailPending}
82 f.useAdmitter(a)
83 rec, etag, err := GetDomain(f.ctx, f.base, claimTestAccount, claimTestDomain)
84 if err != nil {
85 t.Fatal(err)
86 }
87 beforeRaw, beforeEtag := f.domainRaw()
88 f.reset()
89 rec.Apps = []string{"alpha"}
90 if _, err = PutDomain(f.ctx, f.marked, claimTestAccount, rec, etag); !errors.Is(err, ErrClaimMailPending) {
91 t.Fatalf("PutDomain: %v", err)
92 }
93 if a.released != 0 {
94 t.Fatalf("released=%d after a refused admission", a.released)
95 }
96 f.requireUntouched(beforeRaw, beforeEtag)
97 f.requireGateFree()
98}
99
100// A rebinding VerifyDomain runs a nested PutDomain and a nested RefreshPolicies. Neither
101// may call the hook or read admissions: the outer call preflighted the whole set.
102func TestClaimMailVerifyDomainNestedCallsReuseThePreflightedSet(t *testing.T) {
103 f := newClaimDomainFixture(t, "alpha", "beta")
104 a := &fakeClaimAdmitter{}
105 f.useAdmitter(a)
106 if err := f.mem.SetIdentityConfigSet(f.ctx, "eu-west-1", claimTestDomain, ""); err != nil {
107 t.Fatal(err)
108 }
109 f.reset()
110 rec, err := VerifyDomain(f.ctx, f.marked, f.prov, testDeployment(), claimTestAccount, claimTestDomain, "eu-west-1", f.now)
111 if err != nil {
112 t.Fatalf("VerifyDomain: %v", err)
113 }
114 if f.prov.hits["SetIdentityConfigSet"] != 1 || f.log.putsTo(DomainKey(claimTestAccount, claimTestDomain)) != 1 {
115 t.Fatalf("rebind path not exercised: %v", f.prov.hits)
116 }
117 if rec.Regions["eu-west-1"].Status != StatusVerified {
118 t.Fatalf("status=%q", rec.Regions["eu-west-1"].Status)
119 }
120 if len(a.calls) != 1 || a.released != 1 {
121 t.Fatalf("admitter calls=%d released=%d, want 1 and 1", len(a.calls), a.released)
122 }
123 if n := f.log.admissionGets(); n != 0 {
124 t.Fatalf("nested calls read admissions %d times", n)
125 }
126 f.requireGateFree()
127}
128
129func TestClaimMailNestedCallNeverWidensOrRereadsAdmission(t *testing.T) {
130 outer := func(f *claimDomainFixture, inner func(ctx context.Context) error) error {
131 return WithClaimMailResource(f.ctx, f.marked, func(held context.Context) error {
132 return claimMailAdmitted(held, f.marked, claimTestAccount, claimMailPlan{Apps: []string{"alpha"}}, inner)
133 })
134 }
135 t.Run("covered nested call ignores a purge that starts after preflight", func(t *testing.T) {
136 f := newClaimDomainFixture(t, "alpha")
137 rec, etag, err := GetDomain(f.ctx, f.base, claimTestAccount, claimTestDomain)
138 if err != nil {
139 t.Fatal(err)
140 }
141 err = outer(f, func(inner context.Context) error {
142 f.setAdmission("beta", "purging")
143 f.log.reset()
144 rec.Apps = []string{"alpha"}
145 if _, err := PutDomain(inner, f.marked, claimTestAccount, rec, etag); err != nil {
146 return err
147 }
148 if n := f.log.admissionGets(); n != 0 {
149 t.Errorf("nested call read admissions %d times", n)
150 }
151 return nil
152 })
153 if err != nil {
154 t.Fatalf("outer: %v", err)
155 }
156 f.requireGateFree()
157 })
158 t.Run("widening nested call fails closed without reading admissions", func(t *testing.T) {
159 f := newClaimDomainFixture(t, "alpha")
160 rec, etag, err := GetDomain(f.ctx, f.base, claimTestAccount, claimTestDomain)
161 if err != nil {
162 t.Fatal(err)
163 }
164 err = outer(f, func(inner context.Context) error {
165 rec.Apps = []string{"alpha"}
166 newEtag, err := PutDomain(inner, f.marked, claimTestAccount, rec, etag)
167 if err != nil {
168 return err
169 } // first effect, marks the gate dirty
170 _, widenedEtag := f.domainRaw()
171 if widenedEtag != newEtag {
172 t.Errorf("etag mismatch %s %s", widenedEtag, newEtag)
173 }
174 f.log.reset()
175 rec.Apps = []string{"alpha", "beta"}
176 _, err = PutDomain(inner, f.marked, claimTestAccount, rec, newEtag)
177 if !errors.Is(err, ErrClaimMailPending) {
178 t.Errorf("widening PutDomain: %v", err)
179 }
180 if n := f.log.admissionGets(); n != 0 {
181 t.Errorf("widening call read admissions %d times", n)
182 }
183 if n := f.log.putsTo(DomainKey(claimTestAccount, claimTestDomain)); n != 0 {
184 t.Errorf("widening call wrote %d times", n)
185 }
186 return err
187 })
188 if !errors.Is(err, ErrClaimMailPending) {
189 t.Fatalf("outer: %v", err)
190 }
191 // After an effect the gate is retained for reconciliation. Real wrappers never reach
192 // this state because their plans union domain membership before the first effect.
193 if g := f.gate(); g.State != "held" {
194 t.Fatalf("gate=%+v, want held", &g)
195 }
196 })
197}
198