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 unix
2
3package hostguard
4
5import (
6 "bytes"
7 "context"
8 "errors"
9 "github.com/carlosframework/platform/internal/hostclaim"
10 "testing"
11 "time"
12)
13
14func TestPlan14Fix2LegacyLockCannotStallRoot(t *testing.T) {
15 f, target, captured := fenceFixture(t)
16 f.obs.Claim.Holder.Account, f.obs.Claim.Holder.App = "bab", "console"
17 f.g.Root = NewRootAuthority(&rootTestStore{dir: t.TempDir()})
18 in := RootInstallation{Host: target.Host, Incarnation: captured.Incarnation, Stamp: captured.Stamp, Account: "bab", App: "console", Record: "record", Box: target.Box, Enrollment: target.Enrollment, Migration: 1}
19 if err := f.g.EstablishRoot(t.Context(), in, allow); err != nil {
20 t.Fatal(err)
21 }
22 unlock, err := acquire(t.Context(), f.g.LockDir, target.Host)
23 if err != nil {
24 t.Fatal(err)
25 }
26 defer func() {
27 if unlock != nil {
28 unlock()
29 }
30 }()
31 before, err := f.g.Root.store.Read(target.Host + ".json")
32 if err != nil {
33 t.Fatal(err)
34 }
35 ctx, cancel := context.WithTimeout(t.Context(), time.Second)
36 defer cancel()
37 if _, err := f.g.PendingFences(ctx); err != nil {
38 t.Fatal("read waited for legacy lock", err)
39 }
40 if _, err := f.g.BeginFence(ctx, target); err == nil {
41 t.Fatal("mutation crossed held legacy lock")
42 }
43 r, err := f.g.Root.read(target.Host)
44 if err != nil || r.quarantined {
45 t.Fatalf("honest contention quarantined: %+v %v", r, err)
46 }
47 after, err := f.g.Root.store.Read(target.Host + ".json")
48 if err != nil || !bytes.Equal(before, after) {
49 t.Fatal("contention wrote durable state", err)
50 }
51 if _, err := f.g.Root.View(ctx, target.Host, captured); err != nil {
52 t.Fatal("contention fenced running installation", err)
53 }
54 unlock()
55 unlock = nil
56 if _, err := f.g.BeginFence(ctx, target); err != nil {
57 t.Fatal("released contention did not retry", err)
58 }
59}
60func TestPlan14Fix2PendingIntentCanBeAbandoned(t *testing.T) {
61 f, target, captured := fenceFixture(t)
62 f.obs.Claim.Holder.Account, f.obs.Claim.Holder.App = "bab", "console"
63 f.g.Root = NewRootAuthority(&rootTestStore{dir: t.TempDir()})
64 in := RootInstallation{Host: target.Host, Incarnation: captured.Incarnation, Stamp: captured.Stamp, Account: "bab", App: "console", Record: "record", Box: target.Box, Enrollment: target.Enrollment, Migration: 1, InventoryRevision: 1}
65 intent := []byte("pending")
66 failure := errors.New("commit failed")
67 if err := f.g.CommitRootInventory(t.Context(), in, intent, allow, nil, func(RootInstallation) error { return failure }); !errors.Is(err, failure) {
68 t.Fatal(err)
69 }
70 if err := f.g.AbandonRootInventory(t.Context(), target.Host, intent, func(*hostclaim.Claim) bool { return false }, unlanded); !errors.Is(err, ErrFenced) {
71 t.Fatal("abandoned committable intent", err)
72 }
73 if err := f.g.AbandonRootInventory(t.Context(), target.Host, intent, func(*hostclaim.Claim) bool { return true }, unlanded); err != nil {
74 t.Fatal(err)
75 }
76 pending, err := f.g.Root.PendingInstallations()
77 if err != nil || len(pending) != 0 {
78 t.Fatal(pending, err)
79 }
80 if _, err := f.g.Root.View(t.Context(), target.Host, captured); !errors.Is(err, ErrFenced) {
81 t.Fatal("abandon discarded deny", err)
82 }
83 if err := f.g.CommitRootInventory(t.Context(), in, []byte("new"), allow, nil, func(RootInstallation) error { return nil }); err != nil {
84 t.Fatal("fresh intent refused", err)
85 }
86 if _, err := f.g.Root.View(t.Context(), target.Host, captured); err != nil {
87 t.Fatal(err)
88 }
89}
90
91func TestPlan14Fix2SupersededColdBarrierAbandoned(t *testing.T) {
92 f, prior, captured := fenceFixture(t)
93 f.obs.Claim.Holder.Account, f.obs.Claim.Holder.App = "bab", "console"
94 f.g.Root = NewRootAuthority(&rootTestStore{dir: t.TempDir()})
95 in := RootInstallation{Host: prior.Host, Incarnation: captured.Incarnation, Stamp: captured.Stamp, Account: "bab", App: "console", Record: "record", Box: prior.Box, Enrollment: prior.Enrollment, Migration: 1}
96 if err := f.g.EstablishRoot(t.Context(), in, allow); err != nil {
97 t.Fatal(err)
98 }
99 f.obs.Claim.Op.Kind = hostclaim.KindMoving
100 if _, err := f.g.BeginFence(t.Context(), prior); err != nil {
101 t.Fatal(err)
102 }
103 if err := f.g.CompleteFence(t.Context(), prior, []byte("receipt"), time.Now(), func(context.Context, FenceTarget, []byte, time.Time) error { return nil }); err != nil {
104 t.Fatal(err)
105 }
106 barrier := prior
107 barrier.FenceID = "barrier"
108 barrier.Stamp = 17
109 barrier.Session = 17
110 f.obs.Claim.Holder.Stamp, f.obs.Claim.Holder.Session = 17, 17
111 if err := f.g.BeginColdHandover(t.Context(), prior, barrier, allow); err != nil {
112 t.Fatal(err)
113 }
114 if err := f.g.AbandonColdHandover(t.Context(), barrier); !errors.Is(err, ErrFenced) {
115 t.Fatal("abandoned live admission", err)
116 }
117 f.obs.Claim.Holder.Stamp, f.obs.Claim.Holder.Session = 18, 18
118 if err := f.g.AbandonColdHandover(t.Context(), barrier); err != nil {
119 t.Fatal(err)
120 }
121 r, err := f.g.Root.read(prior.Host)
122 if err != nil || r.barrier != nil || len(r.FenceJournal) != 1 || r.FenceJournal[0].Target != prior {
123 t.Fatalf("barrier/receipt: %+v %v", r, err)
124 }
125}
126