carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package release
2
3import (
4 "context"
5 "encoding/json"
6 "errors"
7 "os"
8 "testing"
9 "time"
10)
11
12// TestSidecarWakeKeyIsAnAppSibling pins the key's shape: a SIBLING prefix
13// under the app's own account-scoped prefix, deliberately not a key under
14// sidecars/ — provision.ParseSidecarKey's "exactly one non-empty segment
15// after sidecars/" rule stays exactly as strict as it reads only if nothing
16// else ever lands under that prefix.
17func TestSidecarWakeKeyIsAnAppSibling(t *testing.T) {
18 got, want := SidecarWakeKey("bdm", "eleven", "bot"), "apps/bdm/eleven/sidecar-wake/bot.json"
19 if got != want {
20 t.Fatalf("SidecarWakeKey = %q, want %q", got, want)
21 }
22}
23
24// TestSidecarWakeJSONShape pins the wire shape against the exact example the
25// design settled on, so a field rename or a json-tag typo fails loudly
26// instead of silently breaking every box's etag comparison (which never
27// parses the body at all) while still breaking a human reading the object
28// during an incident.
29func TestSidecarWakeJSONShape(t *testing.T) {
30 w := SidecarWake{
31 Schema: 1,
32 Generation: 3,
33 At: "2026-08-17T23:05:00Z",
34 By: "member:bdm",
35 Reason: "operator wake",
36 }
37 raw, err := json.Marshal(w)
38 if err != nil {
39 t.Fatalf("marshal: %v", err)
40 }
41 const want = `{"schema":1,"generation":3,"at":"2026-08-17T23:05:00Z","by":"member:bdm","reason":"operator wake"}`
42 if string(raw) != want {
43 t.Fatalf("SidecarWake JSON = %s, want %s", raw, want)
44 }
45 var back SidecarWake
46 if err := json.Unmarshal(raw, &back); err != nil {
47 t.Fatalf("unmarshal: %v", err)
48 }
49 if back != w {
50 t.Fatalf("round trip = %+v, want %+v", back, w)
51 }
52}
53
54// sidecarWakeEtag reads name's wake etag, "" for absent — the exact
55// observation a box's pass makes, so a test asserting on it asserts on the
56// signal itself rather than on this file's internals.
57func sidecarWakeEtag(t *testing.T, s Store, acct, app, name string) string {
58 t.Helper()
59 _, etag, err := s.Get(context.Background(), SidecarWakeKey(acct, app, name))
60 if err != nil {
61 if errors.Is(err, os.ErrNotExist) {
62 return ""
63 }
64 t.Fatalf("read sidecar wake: %v", err)
65 }
66 return etag
67}
68
69func TestTouchSidecarWakeCreatesAndMoves(t *testing.T) {
70 s := NewDirStore(t.TempDir())
71 ctx := context.Background()
72 if err := TouchSidecarWake(ctx, s, "bdm", "eleven", "bot", "member:bdm", "operator wake"); err != nil {
73 t.Fatalf("first TouchSidecarWake: %v", err)
74 }
75 raw, first, err := s.Get(ctx, SidecarWakeKey("bdm", "eleven", "bot"))
76 if err != nil {
77 t.Fatalf("Get after first touch: %v", err)
78 }
79 var w SidecarWake
80 if err := json.Unmarshal(raw, &w); err != nil {
81 t.Fatalf("decode sidecar wake: %v", err)
82 }
83 if w.Schema != 1 {
84 t.Fatalf("Schema = %d, want 1", w.Schema)
85 }
86 if w.Generation != 1 {
87 t.Fatalf("Generation = %d, want 1 on first touch", w.Generation)
88 }
89 if w.By != "member:bdm" || w.Reason != "operator wake" {
90 t.Fatalf("By/Reason = %q/%q, want the values passed in", w.By, w.Reason)
91 }
92 if _, err := time.Parse(time.RFC3339, w.At); err != nil {
93 t.Fatalf("At %q is not RFC3339: %v", w.At, err)
94 }
95 // The etag is the whole point: a second request must be a DIFFERENT
96 // object, and Generation must climb, or the box's comparison sees
97 // nothing and nothing wakes.
98 if err := TouchSidecarWake(ctx, s, "bdm", "eleven", "bot", "member:bdm", "second wake"); err != nil {
99 t.Fatalf("second TouchSidecarWake: %v", err)
100 }
101 second := sidecarWakeEtag(t, s, "bdm", "eleven", "bot")
102 if second == first {
103 t.Fatalf("etag %q unchanged after a second request — the wake signal never fires", second)
104 }
105 raw2, _, err := s.Get(ctx, SidecarWakeKey("bdm", "eleven", "bot"))
106 if err != nil {
107 t.Fatalf("Get after second touch: %v", err)
108 }
109 var w2 SidecarWake
110 if err := json.Unmarshal(raw2, &w2); err != nil {
111 t.Fatalf("decode sidecar wake: %v", err)
112 }
113 if w2.Generation != 2 {
114 t.Fatalf("Generation after second touch = %d, want 2", w2.Generation)
115 }
116}
117
118// racingSidecarWakePutStore lands a different writer's value at key just
119// before forwarding the caller's Put, which then fails CAS against the etag
120// the caller read — two operators (or a person and a retrying CLI) asking
121// for a wake at the same moment. Mirrors racingRestartPutStore exactly.
122type racingSidecarWakePutStore struct {
123 Store
124 key string
125 done bool
126}
127
128func (r *racingSidecarWakePutStore) Put(ctx context.Context, key string, body []byte, ifMatch string) (string, error) {
129 if key == r.key && !r.done {
130 r.done = true
131 other := []byte(`{"schema":1,"generation":1,"at":"2026-01-01T00:00:00Z","by":"member:other","reason":"racing"}`)
132 if _, err := r.Store.Put(ctx, key, other, ifMatch); err != nil {
133 return "", err
134 }
135 }
136 return r.Store.Put(ctx, key, body, ifMatch)
137}
138
139func TestTouchSidecarWakeCASConflictIsSuccess(t *testing.T) {
140 inner := NewDirStore(t.TempDir())
141 ctx := context.Background()
142 racing := &racingSidecarWakePutStore{Store: inner, key: SidecarWakeKey("bdm", "eleven", "bot")}
143 if err := TouchSidecarWake(ctx, racing, "bdm", "eleven", "bot", "member:bdm", "operator wake"); err != nil {
144 t.Fatalf("TouchSidecarWake on a lost CAS race: %v, want nil (the request already fired)", err)
145 }
146 if !racing.done {
147 t.Fatal("the racing writer never ran — this test proved nothing")
148 }
149}
150
151func TestTouchSidecarWakeRefusesInvalidNames(t *testing.T) {
152 s := NewDirStore(t.TempDir())
153 ctx := context.Background()
154 if err := TouchSidecarWake(ctx, s, "../etc", "eleven", "bot", "member:bdm", "x"); err == nil {
155 t.Fatal("TouchSidecarWake accepted an invalid account")
156 }
157 if err := TouchSidecarWake(ctx, s, "bdm", "../etc", "bot", "member:bdm", "x"); err == nil {
158 t.Fatal("TouchSidecarWake accepted an invalid app")
159 }
160 if err := TouchSidecarWake(ctx, s, "bdm", "eleven", "../etc", "member:bdm", "x"); err == nil {
161 t.Fatal("TouchSidecarWake accepted an invalid sidecar name")
162 }
163}
164