carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package activator
2
3import (
4 "context"
5 "errors"
6 "os"
7 "strings"
8 "testing"
9 "time"
10
11 "github.com/carlosframework/platform/internal/release"
12)
13
14func TestPlan14GenerationWorkerStartBoundary(t *testing.T) {
15 t.Parallel()
16 for _, claimed := range []bool{false, true} {
17 for _, staged := range []bool{false, true} {
18 for _, pinned := range []bool{false, true} {
19 name := "legacy"
20 if claimed {
21 name = "claimed"
22 }
23 if staged {
24 name += "/staged"
25 } else {
26 name += "/plain"
27 }
28 if pinned {
29 name += "/pinned"
30 } else {
31 name += "/live"
32 }
33 t.Run(name, func(t *testing.T) {
34 a, b, _, reg, _ := stagedActivator(t)
35 t.Cleanup(func() { a.Shutdown(context.Background()); reg.Close() })
36 a.cfg.HostWrites.Enabled = claimed
37 if !staged {
38 a.backend = b.fakeBackend
39 }
40 a.GenerationsFile = release.GenerationsPath(t.TempDir())
41 var onto *release.StagedIdentity
42 if pinned {
43 id := fakeIdentity("v2")
44 onto = &id
45 }
46 gates := 0
47 p, id, pending, err := a.startWorker(t.Context(), workerRoute("bot.x.internal"), nil, onto, func() error { gates++; return nil })
48 if p != nil {
49 defer p.Stop(context.Background())
50 }
51 if claimed {
52 if !errors.Is(err, ErrClaimIsolationUnavailable) || p != nil || id != (release.StagedIdentity{}) || pending != 0 || b.workerStarts() != 0 || gates != 0 {
53 t.Fatalf("unreserved worker reached backend: proc=%v id=%+v pending=%v starts=%d gates=%d err=%v", p, id, pending, b.workerStarts(), gates, err)
54 }
55 if _, err := os.Stat(a.GenerationsFile); !os.IsNotExist(err) {
56 t.Fatalf("refused start published agent generations: %v", err)
57 }
58 } else if err != nil || p == nil || b.workerStarts() != 1 || gates == 0 {
59 t.Fatalf("legacy worker changed: proc=%v starts=%d gates=%d err=%v", p, b.workerStarts(), gates, err)
60 }
61 })
62 }
63 }
64 }
65}
66
67func TestPlan14GenerationWorkerRealBackendRefusal(t *testing.T) {
68 t.Parallel()
69 for _, pinned := range []bool{false, true} {
70 name := "live"
71 if pinned {
72 name = "pinned"
73 }
74 t.Run(name, func(t *testing.T) {
75 a, b, rt, output, _ := workerGateService(t, nil)
76 a.cfg.HostWrites.Enabled = true
77 var onto *release.StagedIdentity
78 if pinned {
79 id, err := release.ResolveLive(b.OptDir, rt.Host)
80 if err != nil {
81 t.Fatal(err)
82 }
83 onto = &id
84 }
85 p, _, _, err := a.startWorker(t.Context(), rt, nil, onto, nil)
86 if p != nil {
87 defer p.Stop(context.Background())
88 }
89 if !errors.Is(err, ErrClaimIsolationUnavailable) || p != nil {
90 t.Fatalf("real backend admitted unreserved worker: %v %v", p, err)
91 }
92 if _, err := os.Stat(output); !os.IsNotExist(err) {
93 t.Fatalf("refused worker executed: %v", err)
94 }
95 if _, err := os.Stat(a.GenerationsFile); !os.IsNotExist(err) {
96 t.Fatalf("refused worker published agent generations: %v", err)
97 }
98 })
99 }
100}
101
102func TestPlan14GenerationWorkerReplacementBoundary(t *testing.T) {
103 shrinkFirstWake(t, 55*time.Second, 25*time.Second, 20*time.Millisecond)
104 for _, claimed := range []bool{false, true} {
105 for _, cause := range []Cause{CauseRelease, CauseRestart, CauseConfig} {
106 name := "legacy/" + string(cause)
107 if claimed {
108 name = "claimed/" + string(cause)
109 }
110 t.Run(name, func(t *testing.T) {
111 a, b, _, reg, _ := stagedActivator(t)
112 t.Cleanup(func() { a.Shutdown(context.Background()); reg.Close() })
113 if err := a.WakeWorker(alwaysOnWorkerRoute("bot.x.internal")); err != nil {
114 t.Fatal(err)
115 }
116 old := b.lastWorker()
117 a.cfg.HostWrites.Enabled = claimed
118 a.GenerationsFile = release.GenerationsPath(t.TempDir())
119 fallback := fakeIdentity("v1")
120 got := a.ReplaceWorker(t.Context(), workerAttempt(cause, ModeOverlap, fakeIdentity("v2")), &fallback, one)
121 if claimed {
122 if got.Outcome != SwapAbandoned || got.Executed || !strings.Contains(got.Reason, ErrClaimIsolationUnavailable.Error()) || b.workerStarts() != 1 {
123 t.Fatalf("unreserved replacement: %+v starts=%d", got, b.workerStarts())
124 }
125 if exited := old.Exited(); exited {
126 t.Fatal("refused replacement stopped the serving worker")
127 }
128 if a.entryServing("bot.x.internal") != fallback {
129 t.Fatal("refused replacement changed serving identity")
130 }
131 if _, err := os.Stat(a.GenerationsFile); !os.IsNotExist(err) {
132 t.Fatalf("refused replacement published agent generations: %v", err)
133 }
134 } else if got.Outcome != SwapDone || !got.Executed || b.workerStarts() != 2 {
135 t.Fatalf("legacy replacement changed: %+v starts=%d", got, b.workerStarts())
136 }
137 })
138 }
139 }
140}
141
142func TestPlan14GenerationWorkerSupervisionBoundary(t *testing.T) {
143 t.Parallel()
144 for _, claimed := range []bool{false, true} {
145 for _, cause := range []string{"crash", "max-run", "converge"} {
146 name := "legacy/" + cause
147 if claimed {
148 name = "claimed/" + cause
149 }
150 t.Run(name, func(t *testing.T) {
151 a, b, clk, reg, ver := stagedActivator(t)
152 t.Cleanup(func() { a.Shutdown(context.Background()); reg.Close() })
153 rt := alwaysOnWorkerRoute("bot.x.internal")
154 if cause == "max-run" {
155 rt.MaxRunSeconds = 30
156 }
157 if err := a.WakeWorker(rt); err != nil {
158 t.Fatal(err)
159 }
160 old := b.lastWorker()
161 a.cfg.HostWrites.Enabled = claimed
162 switch cause {
163 case "crash":
164 old.kill()
165 case "max-run":
166 clk.advance(31 * time.Second)
167 case "converge":
168 ver.Store("v2")
169 a.sweepOnce()
170 clk.advance(ConvergeGrace + time.Minute)
171 }
172 a.sweepOnce()
173 a.mu.Lock()
174 done := a.entries[rt.Host].respawnDone
175 a.mu.Unlock()
176 if done != nil {
177 select {
178 case <-done:
179 case <-time.After(5 * time.Second):
180 t.Fatal("respawn did not settle")
181 }
182 }
183 if claimed {
184 if b.workerStarts() != 1 {
185 t.Fatalf("supervision spawned without root reservation: %d", b.workerStarts())
186 }
187 if exited := old.Exited(); exited && cause != "crash" {
188 t.Fatal("refused recycle stopped the serving worker")
189 }
190 } else if b.workerStarts() != 2 {
191 t.Fatalf("legacy supervision changed: %d", b.workerStarts())
192 }
193 })
194 }
195 }
196}
197