carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostclaim
2
3import (
4 "encoding/json"
5 "errors"
6 "testing"
7 "time"
8)
9
10func TestAcknowledgeExecutionWritesExactJournalValue(t *testing.T) {
11 expires := time.Date(2026, 10, 5, 12, 0, 0, 0, time.UTC)
12 ack := ExecutionAcknowledgement{Op: "op-move", Enrollment: "enrollment-1", BootID: "boot-1", ControllerID: "controller-1", LeaseETag: `"lease-etag"`, Expires: expires}
13 c := &Claim{Op: Op{Kind: KindMoving, ID: "op-move", Participants: []string{"box-a"}}}
14 if err := AcknowledgeExecution("box-a", ack)(c); err != nil {
15 t.Fatal(err)
16 }
17 want, _ := json.Marshal(ack)
18 if got := c.Op.Journal["exec_ack.box-a"]; got != string(want) {
19 t.Fatalf("journal = %q, want %q", got, want)
20 }
21 if err := AcknowledgeExecution("box-a", ack)(c); !errors.Is(err, ErrAckAlreadyApplied) {
22 t.Fatalf("idempotent retry = %v", err)
23 }
24 changed := ack
25 changed.LeaseETag = `"other"`
26 if err := AcknowledgeExecution("box-a", changed)(c); !errors.Is(err, ErrWrongState) {
27 t.Fatalf("conflicting ack = %v", err)
28 }
29}
30
31func TestAcknowledgeExecutionRefusesServingAndNonparticipants(t *testing.T) {
32 ack := ExecutionAcknowledgement{Op: "op", Enrollment: "e", BootID: "b", ControllerID: "c", LeaseETag: "tag", Expires: time.Now()}
33 for name, c := range map[string]*Claim{
34 "serving": {Op: Op{Kind: KindServing, Participants: []string{"box"}}},
35 "nonparticipant": {Op: Op{Kind: KindMoving, ID: "op", Participants: []string{"other"}}},
36 } {
37 t.Run(name, func(t *testing.T) {
38 if err := AcknowledgeExecution("box", ack)(c); !errors.Is(err, ErrWrongState) {
39 t.Fatalf("error = %v", err)
40 }
41 })
42 }
43}
44
45// An acknowledgement may only be extended by the controller that wrote it.
46// The console's completion check reads the latest expiry, so a participant
47// keeps it fresh while a create, delete or purge waits for recovery.
48func TestAcknowledgeExecutionExtendsOnlyTheSameLease(t *testing.T) {
49 expires := time.Date(2026, 10, 20, 12, 0, 0, 0, time.UTC)
50 first := ExecutionAcknowledgement{Op: "op", Enrollment: "enrollment-1", BootID: "boot-1", ControllerID: "controller-1", LeaseETag: `"lease-1"`, Expires: expires}
51 acked := func(t *testing.T) *Claim {
52 t.Helper()
53 c := &Claim{Op: Op{Kind: KindCreating, ID: "op", Participants: []string{"box-a"}}}
54 if err := AcknowledgeExecution("box-a", first)(c); err != nil {
55 t.Fatal(err)
56 }
57 return c
58 }
59 t.Run("extension replaces", func(t *testing.T) {
60 c := acked(t)
61 next := first
62 next.LeaseETag, next.Expires = `"lease-2"`, expires.Add(20*time.Second)
63 if err := AcknowledgeExecution("box-a", next)(c); err != nil {
64 t.Fatal(err)
65 }
66 want, _ := json.Marshal(next)
67 if got := c.Op.Journal["exec_ack.box-a"]; got != string(want) {
68 t.Fatalf("journal = %q, want %q", got, want)
69 }
70 if err := AcknowledgeExecution("box-a", next)(c); !errors.Is(err, ErrAckAlreadyApplied) {
71 t.Fatalf("replayed extension = %v", err)
72 }
73 if err := AcknowledgeExecution("box-a", first)(c); !errors.Is(err, ErrWrongState) {
74 t.Fatalf("older acknowledgement after an extension = %v", err)
75 }
76 })
77 for name, edit := range map[string]func(*ExecutionAcknowledgement){
78 "other boot": func(a *ExecutionAcknowledgement) { a.BootID = "boot-2" },
79 "other controller": func(a *ExecutionAcknowledgement) { a.ControllerID = "controller-2" },
80 "other enrollment": func(a *ExecutionAcknowledgement) { a.Enrollment = "enrollment-2" },
81 "equal expiry": func(a *ExecutionAcknowledgement) { a.Expires = expires },
82 "earlier expiry": func(a *ExecutionAcknowledgement) { a.Expires = expires.Add(-time.Second) },
83 } {
84 t.Run(name, func(t *testing.T) {
85 c := acked(t)
86 before := c.Op.Journal["exec_ack.box-a"]
87 next := first
88 next.LeaseETag, next.Expires = `"lease-2"`, expires.Add(20*time.Second)
89 edit(&next)
90 if err := AcknowledgeExecution("box-a", next)(c); !errors.Is(err, ErrWrongState) {
91 t.Fatalf("error = %v", err)
92 }
93 if c.Op.Journal["exec_ack.box-a"] != before {
94 t.Fatal("refused acknowledgement replaced the journal")
95 }
96 })
97 }
98 t.Run("other op", func(t *testing.T) {
99 // The journal entry belongs to the claim's current op; an
100 // acknowledgement naming another op is refused before any comparison.
101 c := acked(t)
102 next := first
103 next.Op, next.Expires = "other-op", expires.Add(20*time.Second)
104 if err := AcknowledgeExecution("box-a", next)(c); !errors.Is(err, ErrWrongState) {
105 t.Fatalf("error = %v", err)
106 }
107 // A journalled acknowledgement for another op (a stale entry) is never extended.
108 stale := first
109 stale.Op = "older-op"
110 raw, _ := json.Marshal(stale)
111 c.Op.Journal["exec_ack.box-a"] = string(raw)
112 next.Op = "op"
113 if err := AcknowledgeExecution("box-a", next)(c); !errors.Is(err, ErrWrongState) {
114 t.Fatalf("stale op entry = %v", err)
115 }
116 })
117 t.Run("missing lease etag", func(t *testing.T) {
118 c := acked(t)
119 next := first
120 next.LeaseETag, next.Expires = "", expires.Add(20*time.Second)
121 if err := AcknowledgeExecution("box-a", next)(c); !errors.Is(err, ErrWrongState) {
122 t.Fatalf("error = %v", err)
123 }
124 })
125 for name, previous := range map[string]string{
126 "undecodable": "{not json",
127 "unknown field": `{"op":"op","enrollment":"enrollment-1","boot_id":"boot-1","controller_id":"controller-1","lease_etag":"x","expires":"2026-10-20T12:00:00Z","extra":1}`,
128 "trailing data": `{"op":"op","enrollment":"enrollment-1","boot_id":"boot-1","controller_id":"controller-1","lease_etag":"x","expires":"2026-10-20T12:00:00Z"} {}`,
129 } {
130 t.Run(name, func(t *testing.T) {
131 c := &Claim{Op: Op{Kind: KindCreating, ID: "op", Participants: []string{"box-a"}, Journal: map[string]string{"exec_ack.box-a": previous}}}
132 next := first
133 next.LeaseETag, next.Expires = `"lease-2"`, expires.Add(20*time.Second)
134 if err := AcknowledgeExecution("box-a", next)(c); !errors.Is(err, ErrWrongState) {
135 t.Fatalf("error = %v", err)
136 }
137 if c.Op.Journal["exec_ack.box-a"] != previous {
138 t.Fatal("refused acknowledgement replaced the journal")
139 }
140 })
141 }
142}
143