carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package host
4
5import (
6 "context"
7 "errors"
8 "os"
9 "path/filepath"
10 "testing"
11
12 "github.com/carlosframework/platform/internal/activator"
13 "github.com/carlosframework/platform/internal/hostbox"
14 "github.com/carlosframework/platform/internal/hostfiles"
15 "github.com/carlosframework/platform/internal/provision"
16 "github.com/carlosframework/platform/internal/registry"
17)
18
19func TestFilesSeedPrivateBypassRequiresExactExclusionAndAbsence(t *testing.T) {
20 f := newFilesSeedFixture(t)
21 selected, err := f.inspect()
22 if err != nil {
23 t.Fatal(err)
24 }
25 op := &filesSeedOperation{ctx: t.Context(), claims: f.claims, actor: f.actor, files: f.files, selected: selected}
26 svc := &activator.Service{}
27 token, err := svc.AcquireSeedExclusion(t.Context(), filesHost, nil)
28 if err != nil {
29 t.Fatal(err)
30 }
31 guard := op.prerequisites(token)
32 if err := guard(t.Context(), f.route, f.observed); err != nil {
33 t.Fatal(err)
34 }
35 if err := servingFilesPrerequisites(f.claims, f.files)(t.Context(), f.route, f.observed); !errors.Is(err, hostfiles.ErrNoEvidence) {
36 t.Fatal("ordinary guard bypassed", err)
37 }
38 if err := op.prerequisites(nil)(t.Context(), f.route, f.observed); err == nil {
39 t.Fatal("no exclusion")
40 }
41 bad := f.route
42 bad.DBPath = "/wrong"
43 if err := guard(t.Context(), bad, f.observed); err == nil {
44 t.Fatal("layout bypassed")
45 }
46 f.data.Put("data", hostfiles.ManifestKey(movesFilesPrefix(f.observed.Claim.Holder.Location, "")), []byte("{}"))
47 if err := guard(t.Context(), f.route, f.observed); err == nil {
48 t.Fatal("presence bypassed")
49 }
50 if err := token.Release(); err != nil {
51 t.Fatal(err)
52 }
53 if err := guard(t.Context(), f.route, f.observed); err == nil {
54 t.Fatal("released exclusion")
55 }
56}
57
58func TestFilesSeedRerunSettlementRequiresExclusion(t *testing.T) {
59 for _, fault := range []string{"none", "live-controller", "missing-record", "no-exclusion", "canceled"} {
60 t.Run(fault, func(t *testing.T) {
61 f := newRecoveryFixture(t)
62 if fault == "missing-record" {
63 f.recordPrelaunch = false
64 }
65 old := f.controller("boot-1", "controller-1", 4101, "start-1")
66 o := old.admit(t, f)
67 if fault != "missing-record" {
68 if _, err := old.runtime.Prepare(t.Context(), registry.Route{Host: recoveryHost}, o, recoveryPolicy); err != nil {
69 t.Fatal(err)
70 }
71 }
72 current := f.controller("boot-1", "controller-2", 4202, "start-2")
73 dir := t.TempDir()
74 rt := registry.Route{Host: recoveryHost, DBPath: provision.NestedDBPath(dir, recoveryHost)}
75 if err := os.MkdirAll(filepath.Dir(rt.DBPath), 0700); err != nil {
76 t.Fatal(err)
77 }
78 files := &movesFiles{DataDir: dir, EnvFile: func(host, db string) (claimEnvFile, error) {
79 return claimEnvFile{Nested: true, Dir: filepath.Dir(db), Name: host + ".env"}, nil
80 }}
81 svc := &activator.Service{}
82 token, err := svc.AcquireSeedExclusion(t.Context(), rt.Host, nil)
83 if err != nil {
84 t.Fatal(err)
85 }
86 if fault == "no-exclusion" {
87 token = nil
88 }
89 f.kernel.alive = fault == "live-controller"
90 ctx := t.Context()
91 if fault == "canceled" {
92 var cancel context.CancelFunc
93 ctx, cancel = context.WithCancel(ctx)
94 cancel()
95 }
96 got, err := settleFilesSeedRerun(ctx, rt, files, current.wake.Retries, f.read(), token)
97 if fault != "none" {
98 if err == nil {
99 t.Fatal("unproved settlement accepted")
100 }
101 if f.retry().State != "attempting" {
102 t.Fatal("failed settlement changed debt")
103 }
104 return
105 }
106 if err != nil {
107 t.Fatal(err)
108 }
109 retry := got.Claim.Holder.WakeRetry
110 if retry.State != "open" || retry.AttemptsReserved != 1 || retry.Attempt != nil {
111 t.Fatal("not settled without refund", retry)
112 }
113 if len(f.receipts()) != 1 || f.receipts()[0].ControllerID != "controller-1" {
114 t.Fatal("wrong stop tuple", f.receipts())
115 }
116 if _, err = settleFilesSeedRerun(ctx, rt, files, current.wake.Retries, got, token); err != nil {
117 t.Fatal(err)
118 }
119 if _, err = settleFilesSeedRerun(ctx, rt, files, current.wake.Retries, o, token); !errors.Is(err, hostbox.ErrChanged) {
120 t.Fatal("stale rerun", err)
121 }
122 })
123 }
124}
125