carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostops
2
3import (
4 "context"
5 "errors"
6 "slices"
7 "testing"
8
9 "github.com/carlosframework/platform/internal/release"
10)
11
12func relayPut(before, after string) MutationTarget {
13 return MutationTarget{Surface: "bucket", Method: "Put", Key: RelayAuthorityKey, Before: []byte(before), After: []byte(after)}
14}
15
16// control/relay.json is per-app authority: only the entries a rewrite adds,
17// removes or changes need permits, and a written_at-only rewrite is the one
18// non-app write of that key.
19func TestRelayAuthorityClassifiesChangedEntries(t *testing.T) {
20 ctx := t.Context()
21 const (
22 a = `{"account":"bab","app":"demo","incarnation":"i1","regions":["eu-west-1"]}`
23 b = `{"account":"bab","app":"kass","incarnation":"i2","regions":["eu-west-1"]}`
24 b2 = `{"account":"bab","app":"kass","incarnation":"i3","regions":["eu-west-1"]}`
25 bR = `{"account":"bab","app":"kass","incarnation":"i2","regions":["us-east-1"]}`
26 c = `{"account":"zed","app":"meet","incarnation":"i4","regions":["eu-west-1"]}`
27 at1 = `"written_at":"2026-10-07T12:00:00Z"`
28 at2 = `"written_at":"2026-10-07T12:05:00Z"`
29 )
30 doc := func(at string, apps ...string) string {
31 out := `{"apps":[`
32 for i, e := range apps {
33 if i > 0 {
34 out += ","
35 }
36 out += e
37 }
38 return out + `],` + at + `}`
39 }
40 for _, tc := range []struct {
41 name string
42 before, after string
43 want []AppScope
44 }{
45 {"written-at-only", doc(at1, a, b), doc(at2, a, b), nil},
46 {"order-only", doc(at1, a, b), doc(at2, b, a), nil},
47 {"first-publish", "", doc(at1, a), []AppScope{{"bab", "demo"}}},
48 {"added", doc(at1, a), doc(at2, c, a), []AppScope{{"zed", "meet"}}},
49 {"removed", doc(at1, a, b), doc(at2, a), []AppScope{{"bab", "kass"}}},
50 {"incarnation", doc(at1, a, b), doc(at2, a, b2), []AppScope{{"bab", "kass"}}},
51 {"regions", doc(at1, a, b), doc(at2, a, bR), []AppScope{{"bab", "kass"}}},
52 {"many", doc(at1, a, b), doc(at2, c, b2), []AppScope{{"bab", "demo"}, {"bab", "kass"}, {"zed", "meet"}}},
53 } {
54 t.Run(tc.name, func(t *testing.T) {
55 c, err := ClassifyMutation(ctx, nil, nil, relayPut(tc.before, tc.after))
56 if err != nil {
57 t.Fatal(err)
58 }
59 if !slices.Equal(c.Scopes, tc.want) {
60 t.Fatalf("scopes %v, want %v", c.Scopes, tc.want)
61 }
62 if (len(tc.want) == 0) != (c.NonApp != "") {
63 t.Fatalf("non-app reason %q with scopes %v", c.NonApp, c.Scopes)
64 }
65 got, err := RelayAuthorityScopes([]byte(tc.before), []byte(tc.after))
66 if err != nil || !slices.Equal(got, tc.want) {
67 t.Fatalf("publisher scopes %v %v disagree with the boundary", got, err)
68 }
69 })
70 }
71 for name, tgt := range map[string]MutationTarget{
72 "malformed-after": relayPut(doc(at1, a), `{"apps":[`),
73 "malformed-before": relayPut(`not json`, doc(at1, a)),
74 "duplicate-after": relayPut(doc(at1, a), doc(at2, a, a)),
75 "duplicate-before": relayPut(doc(at1, a, a), doc(at2, a)),
76 "unknown-field": relayPut(doc(at1, a), `{"apps":[],"extra":1,`+at2+`}`),
77 "unknown-entry-key": relayPut(doc(at1, a), `{"apps":[{"account":"bab","app":"demo","incarnation":"i1","regions":[],"x":1}],`+at2+`}`),
78 "invalid-identity": relayPut(doc(at1, a), doc(at2, `{"account":"","app":"demo","incarnation":"i1","regions":[]}`)),
79 "trailing-value": relayPut(doc(at1, a), doc(at2, a)+`{}`),
80 } {
81 if _, err := ClassifyMutation(ctx, nil, nil, tgt); !errors.Is(err, ErrIdentity) {
82 t.Fatalf("%s: %v", name, err)
83 }
84 }
85 del := MutationTarget{Surface: "bucket", Method: "Delete", Key: RelayAuthorityKey, Before: []byte(doc(at1, a))}
86 if _, err := ClassifyMutation(ctx, nil, nil, del); !errors.Is(err, ErrUnclassified) {
87 t.Fatalf("aggregate delete: %v", err)
88 }
89 if _, err := ClassifyMutation(ctx, nil, nil, MutationTarget{Method: "Put", Key: "control/relay.json.tmp", After: []byte(`{}`)}); !errors.Is(err, ErrUnclassified) {
90 t.Fatalf("no prefix admission: %v", err)
91 }
92}
93
94// control/relay-issuer.json is the operator's regional issuer pointer: an
95// exact non-app family when its body is a valid {region: kid} map.
96func TestRelayIssuerIsExactNonApp(t *testing.T) {
97 ctx := t.Context()
98 put := func(body string) MutationTarget {
99 return MutationTarget{Surface: "bucket", Method: "Put", Key: RelayIssuerKey, After: []byte(body)}
100 }
101 c, err := ClassifyMutation(ctx, nil, nil, put(`{"eu-west-1":"k2","us-east-1":"k1"}`))
102 if err != nil || c.NonApp == "" || len(c.Scopes) != 0 {
103 t.Fatalf("issuer pointer: %+v %v", c, err)
104 }
105 for _, body := range []string{`{"eu-west-1":"TOOLONGKID"}`, `{"EU":"k1"}`, `[]`, `null`, `{"eu-west-1":"k1"} {}`} {
106 if _, err := ClassifyMutation(ctx, nil, nil, put(body)); !errors.Is(err, ErrIdentity) {
107 t.Fatalf("%s: %v", body, err)
108 }
109 }
110 if _, err := ClassifyMutation(ctx, nil, nil, MutationTarget{Method: "Delete", Key: RelayIssuerKey}); !errors.Is(err, ErrUnclassified) {
111 t.Fatalf("issuer delete: %v", err)
112 }
113}
114
115func boundRunner(t *testing.T, apps ...string) (context.Context, release.Store, *release.DirStore) {
116 t.Helper()
117 ctx := t.Context()
118 w, raw, _ := testWriter(t)
119 for _, app := range apps {
120 seedAdmission(t, raw, "bab", app, openAdmission(app+"-id"))
121 }
122 check, err := NewProductionMutationCheck(raw, w)
123 if err != nil {
124 t.Fatal(err)
125 }
126 data, err := NewMutationBoundary(true, raw, check)
127 if err != nil {
128 t.Fatal(err)
129 }
130 if err = BindMutationRunner(data, w, testOwner, func(_ context.Context, _, app string) (string, error) { return app + "-id", nil }); err != nil {
131 t.Fatal(err)
132 }
133 return ctx, data, raw
134}
135
136// A raw write made under a nested scope is a possible late effect of every
137// enclosing operation, so a failing multi-scope call holds both apps.
138func TestNestedScopeErrorHoldsEveryEnclosingApp(t *testing.T) {
139 ctx, data, raw := boundRunner(t, "demo", "kass")
140 failure := errors.New("ambiguous nested failure")
141 err := release.WithAppMutation(ctx, data, "bab", "demo", "outer", func(outer context.Context) error {
142 return release.WithAppMutation(outer, data, "bab", "kass", "inner", func(inner context.Context) error {
143 if _, err := data.Put(inner, "apps/bab/kass/test.json", []byte(`{}`), ""); err != nil {
144 return err
145 }
146 return failure
147 })
148 })
149 if !errors.Is(err, failure) {
150 t.Fatalf("nested failure: %v", err)
151 }
152 for _, app := range []string{"demo", "kass"} {
153 a, _ := ReadAdmission(ctx, raw, "bab", app, app+"-id")
154 if a.Value.State != "closed" || a.Value.Op == nil {
155 t.Fatalf("%s released after an ambiguous nested effect: %+v", app, a.Value)
156 }
157 }
158}
159
160// A nested acquisition that fails issues nothing, so the outer operation
161// still releases as unapplied.
162func TestFailedNestedAcquisitionReleasesOuter(t *testing.T) {
163 ctx, data, raw := boundRunner(t, "demo")
164 err := release.WithAppMutation(ctx, data, "bab", "demo", "outer", func(outer context.Context) error {
165 // kass has no admission: the nested acquisition refuses before any effect.
166 return release.WithAppMutation(outer, data, "bab", "kass", "inner", func(context.Context) error {
167 t.Fatal("unadmitted nested scope ran")
168 return nil
169 })
170 })
171 if err == nil {
172 t.Fatal("nested acquisition of an unadmitted app succeeded")
173 }
174 a, _ := ReadAdmission(ctx, raw, "bab", "demo", "demo-id")
175 if a.Value.State != "open" || a.Value.Op != nil {
176 t.Fatalf("unissued outer operation retained authority: %+v", a.Value)
177 }
178}
179
180// A context whose permit for an app is no longer valid cannot open a fresh
181// operation for that app by nesting.
182func TestInvalidNestedPermitRefuses(t *testing.T) {
183 ctx, data, raw := boundRunner(t, "demo")
184 var saved context.Context
185 if err := release.WithAppMutation(ctx, data, "bab", "demo", "outer", func(pctx context.Context) error {
186 saved = pctx
187 return nil
188 }); err != nil {
189 t.Fatal(err)
190 }
191 before, _ := ReadAdmission(ctx, raw, "bab", "demo", "demo-id")
192 called := false
193 err := release.WithAppMutation(saved, data, "bab", "demo", "nested", func(context.Context) error {
194 called = true
195 return nil
196 })
197 after, _ := ReadAdmission(ctx, raw, "bab", "demo", "demo-id")
198 if called || !errors.Is(err, ErrPending) || before.ETag != after.ETag {
199 t.Fatalf("retired permit acquired a new operation: called=%v err=%v", called, err)
200 }
201}
202