carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package layout
2
3import (
4 "path/filepath"
5 "strings"
6 "testing"
7
8 "github.com/carlosframework/platform/internal/provision"
9)
10
11func TestPlanForNestedDerivesEveryPathFromTheHost(t *testing.T) {
12 p, err := PlanFor("/data", "/run/carlos", "h.example.com", Mode("nested"))
13 if err != nil {
14 t.Fatal(err)
15 }
16 iid := provision.InstanceID("h.example.com")
17 if p.From != (Endpoint{DB: "/data/h.example.com.db", Socket: "/run/carlos/h.example.com.sock"}) {
18 t.Errorf("from = %+v", p.From)
19 }
20 if p.To != (Endpoint{DB: provision.NestedDBPath("/data", "h.example.com"), Socket: provision.NestedSocket("h.example.com")}) {
21 t.Errorf("to = %+v", p.To)
22 }
23 if p.Host != "h.example.com" || p.IID != iid || p.Mode != Mode("nested") {
24 t.Errorf("host/iid/mode = %q %q %q", p.Host, p.IID, p.Mode)
25 }
26 if len(p.Artifacts) != 9 {
27 t.Fatalf("len(Artifacts) = %d, want 9", len(p.Artifacts))
28 }
29 byName := map[string]Artifact{}
30 for _, a := range p.Artifacts {
31 byName[a.Name] = a
32 }
33 if byName["db"].Src != "/data/h.example.com.db" || byName["db"].Dst != filepath.Join("/data/.instances", iid, "h.example.com.db") || !byName["db"].Required {
34 t.Errorf("db artifact = %+v (the destination must be the RAW directory)", byName["db"])
35 }
36 if byName["db"].Dir {
37 t.Errorf("db artifact should not be marked as a directory: %+v", byName["db"])
38 }
39 if byName["env"].Dst != filepath.Join("/data/.instances", iid, "h.example.com.env") || byName["env"].Required {
40 t.Errorf("env artifact = %+v", byName["env"])
41 }
42 if byName["db-wal"].Src != "/data/h.example.com.db-wal" || byName["db-shm"].Src != "/data/h.example.com.db-shm" {
43 t.Errorf("sidecar files = %+v %+v", byName["db-wal"], byName["db-shm"])
44 }
45 if byName["config-env"].Src != "/data/h.example.com.config.env" || byName["sidecar-env"].Src != "/data/h.example.com-sidecar.env" {
46 t.Errorf("env files = %+v %+v", byName["config-env"], byName["sidecar-env"])
47 }
48 if strings.Contains(byName["db"].Dst, "/data/instances/") {
49 t.Error("a destination through the bind mount would EXDEV")
50 }
51
52 // The two artifacts appended after socket.
53 if byName["litestream-shadow"].Src != "/data/.activator-h.example.com.db-litestream" {
54 t.Errorf("litestream-shadow src = %q", byName["litestream-shadow"].Src)
55 }
56 if byName["litestream-shadow"].Dst != filepath.Join("/data/.instances", iid, ".activator-h.example.com.db-litestream") {
57 t.Errorf("litestream-shadow dst = %q", byName["litestream-shadow"].Dst)
58 }
59 if !byName["litestream-shadow"].Dir {
60 t.Error("litestream-shadow should be marked as a directory")
61 }
62 if byName["litestream-shadow"].Required {
63 t.Error("litestream-shadow must be optional")
64 }
65 if byName["corrupt"].Src != "/data/h.example.com.db.corrupt" {
66 t.Errorf("corrupt src = %q", byName["corrupt"].Src)
67 }
68 if byName["corrupt"].Dst != filepath.Join("/data/.instances", iid, "h.example.com.db.corrupt") {
69 t.Errorf("corrupt dst = %q", byName["corrupt"].Dst)
70 }
71 if byName["corrupt"].Dir || byName["corrupt"].Required {
72 t.Errorf("corrupt artifact = %+v, want a non-directory optional file", byName["corrupt"])
73 }
74
75 // Both socket endpoints come from the socketDir argument, and the
76 // nested one sits under "instances" (the mount-visible name), not the
77 // raw dotted directory: nothing is ever renamed for the socket.
78 if byName["socket"].Src != "/run/carlos/h.example.com.sock" {
79 t.Errorf("socket src = %q", byName["socket"].Src)
80 }
81 if byName["socket"].Dst != filepath.Join("/run/carlos/instances", iid, "app.sock") {
82 t.Errorf("socket dst = %q", byName["socket"].Dst)
83 }
84 if byName["socket"].Required {
85 t.Error("socket must be optional: it is reported, never renamed")
86 }
87}
88
89// TestPlanForUsesTheGivenSocketDirNotTheCompiledDefault pins that PlanFor
90// must derive both socket endpoints from its socketDir argument, never from
91// the compiled-in provision.SocketDir or provision.DefaultSocket/NestedSocket
92// (which ignore the argument entirely). A test that only ever passes
93// "/run/carlos" as socketDir cannot catch a PlanFor that silently falls back
94// to the compiled default, because the two values coincide in production.
95func TestPlanForUsesTheGivenSocketDirNotTheCompiledDefault(t *testing.T) {
96 sd := "/tmp/not-run-carlos"
97 p, err := PlanFor("/data", sd, "h.example.com", Mode("nested"))
98 if err != nil {
99 t.Fatal(err)
100 }
101 iid := provision.InstanceID("h.example.com")
102 if p.From.Socket != filepath.Join(sd, "h.example.com.sock") {
103 t.Errorf("from.socket = %q, want under %q", p.From.Socket, sd)
104 }
105 if p.To.Socket != filepath.Join(sd, "instances", iid, "app.sock") {
106 t.Errorf("to.socket = %q, want under %q", p.To.Socket, sd)
107 }
108 if strings.HasPrefix(p.To.Socket, "/run/carlos") {
109 t.Error("nested socket endpoint fell back to the compiled-in socket dir")
110 }
111 for _, a := range p.Artifacts {
112 if a.Name == "socket" && strings.HasPrefix(a.Dst, "/run/carlos") {
113 t.Errorf("socket artifact fell back to the compiled-in socket dir: %+v", a)
114 }
115 }
116}
117
118func TestPlanForFlatIsTheExactReverse(t *testing.T) {
119 n, _ := PlanFor("/data", "/run/carlos", "h.example.com", Mode("nested"))
120 f, err := PlanFor("/data", "/run/carlos", "h.example.com", Mode("flat"))
121 if err != nil {
122 t.Fatal(err)
123 }
124 if f.From != n.To || f.To != n.From {
125 t.Errorf("flat endpoints %+v %+v are not nested's swapped %+v %+v", f.From, f.To, n.From, n.To)
126 }
127 if len(f.Artifacts) != len(n.Artifacts) {
128 t.Fatalf("artifact counts differ: %d vs %d", len(f.Artifacts), len(n.Artifacts))
129 }
130 for i := range n.Artifacts {
131 if f.Artifacts[i].Src != n.Artifacts[i].Dst || f.Artifacts[i].Dst != n.Artifacts[i].Src {
132 t.Errorf("artifact %s not reversed: %+v vs %+v", n.Artifacts[i].Name, f.Artifacts[i], n.Artifacts[i])
133 }
134 if f.Artifacts[i].Name != n.Artifacts[i].Name || f.Artifacts[i].Required != n.Artifacts[i].Required || f.Artifacts[i].Dir != n.Artifacts[i].Dir {
135 t.Errorf("artifact %d metadata not preserved across the reversal: %+v vs %+v", i, f.Artifacts[i], n.Artifacts[i])
136 }
137 }
138}
139
140// TestRawRunDirIsTheDottedRawSocketTree pins rawRunDir's own doc comment
141// ("<socketDir>/.instances/<iid>"): a later pass creates the nested run
142// directory through this raw path even though the socket file inside it is
143// never renamed (PlanFor's socket artifact records the mount-visible path
144// instead).
145func TestRawRunDirIsTheDottedRawSocketTree(t *testing.T) {
146 got := rawRunDir("/run/carlos", "h.example.com")
147 want := filepath.Join("/run/carlos/.instances", provision.InstanceID("h.example.com"))
148 if got != want {
149 t.Errorf("rawRunDir = %q, want %q", got, want)
150 }
151}
152
153// NestedPlatformNames is exactly the plan's raw-directory names (every
154// nested artifact the pass moves into the instance directory, the socket
155// aside) plus the generation markers, litestream's stock meta directory and
156// the adoption record; and it covers every name a nested plan's artifacts
157// land at in the raw directory, so no platform file of the layout pass can
158// reach an app archive.
159func TestNestedPlatformNamesAreThePlansRawNames(t *testing.T) {
160 const h = "h.example.com"
161 got := NestedPlatformNames(h)
162 want := map[string]bool{
163 h + ".db": true, h + ".db-wal": true, h + ".db-shm": true, h + ".db.corrupt": true,
164 h + ".env": true, h + "-sidecar.env": true, h + ".config.env": true,
165 ".activator-" + h + ".db-litestream": true, ".files-gen": true,
166 h + ".db.gen": true, h + ".db-litestream": true, h + ".instance-key-adoption.json": true,
167 h + ".db.seed": true,
168 "launch.run.json": true, "launch.seed.json": true, "launch.sidecar.json": true, "launch.cmd.json": true,
169 }
170 if len(got) != len(want) {
171 t.Fatalf("NestedPlatformNames = %v, want %v", got, want)
172 }
173 for n := range want {
174 if !got[n] {
175 t.Errorf("%s missing", n)
176 }
177 }
178 p, err := PlanFor("/data", "/run/carlos", h, ModeNested)
179 if err != nil {
180 t.Fatal(err)
181 }
182 raw := rawInstanceDir("/data", h)
183 for _, a := range p.Artifacts {
184 if filepath.Dir(a.Dst) == raw && !got[filepath.Base(a.Dst)] {
185 t.Errorf("artifact %s lands at %s, which NestedPlatformNames does not name", a.Name, a.Dst)
186 }
187 if a.Name == "socket" && got[filepath.Base(a.Dst)] {
188 t.Errorf("the socket is in the run directory, not the instance directory")
189 }
190 }
191}
192
193// IsNestedPlatformName is NestedPlatformNames plus a generation's launch
194// descriptor exactly as instancectl.GenLaunchFileName writes it; anything
195// shaped almost like one is the app's.
196func TestIsNestedPlatformNameMatchesGenerationLaunchFilesExactly(t *testing.T) {
197 const h = "h.example.com"
198 for name := range NestedPlatformNames(h) {
199 if !IsNestedPlatformName(h, name) {
200 t.Errorf("%s: not a platform name", name)
201 }
202 }
203 for _, name := range []string{"launch.gen.0.json", "launch.gen.7.json", "launch.gen.18446744073709551615.json"} {
204 if !IsNestedPlatformName(h, name) {
205 t.Errorf("%s: not a platform name", name)
206 }
207 }
208 for _, name := range []string{h, "launch.gen.json", "launch.gen..json", "launch.gen.07.json", "launch.gen.-1.json", "launch.gen.7.json.bak",
209 "launch.gen.7", "xlaunch.gen.7.json", "launch.gen.x.json", "launch.gen.18446744073709551616.json", "launch.other.json", h + "-blobs", "uploads"} {
210 if IsNestedPlatformName(h, name) {
211 t.Errorf("%s: taken for a platform name", name)
212 }
213 }
214}
215
216func TestPlanForRefusesBadInput(t *testing.T) {
217 if _, err := PlanFor("/data", "/run/carlos", "h.example.com", Mode("sideways")); err == nil {
218 t.Error("unknown mode accepted")
219 }
220 if _, err := PlanFor("/data", "/run/carlos", "../h", Mode("nested")); err == nil {
221 t.Error("invalid host accepted")
222 }
223}
224