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 hostexec
4
5import (
6 "context"
7 "fmt"
8 "testing"
9
10 "github.com/carlosframework/platform/internal/rootstate"
11)
12
13func TestPlan14ExecutionReplayWindowLongSequence(t *testing.T) {
14 for _, manyOps := range []bool{false, true} {
15 t.Run(fmt.Sprint(manyOps), func(t *testing.T) {
16 b, d, remote, _, base, peer := brokerFixture(t)
17 original := b.cfg.Authority
18 current := base
19 b.cfg.Authority = func(ctx context.Context, q ExecutionRequest, p ControllerProcess) (ExecutionAuthority, error) {
20 if !sameExecution(q, ExecutionRecord{Request: current}) {
21 return ExecutionAuthority{}, ErrLost
22 }
23 q.Op = base.Op
24 return original(ctx, q, p)
25 }
26 var stale ExecutionRequest
27 var staleSettle ExecutionRequest
28 begin := func(q ExecutionRequest) ExecutionResponse {
29 t.Helper()
30 r, err := b.Execute(t.Context(), peer, q)
31 if err != nil {
32 t.Fatal(err)
33 }
34 return r
35 }
36 permit := begin(current)
37 for i := 0; i < 4200; i++ {
38 q := current
39 q.Operation = "executionRenew"
40 q.ID = fmt.Sprintf("renew-%d", i)
41 q.Token = permit.Token
42 permit = begin(q)
43 if i == 0 {
44 stale = q
45 }
46 again := begin(q)
47 if again != permit {
48 t.Fatal("latest request replay changed")
49 }
50 if manyOps {
51 settle := current
52 settle.Operation = "executionSettle"
53 settle.ID = fmt.Sprintf("settle-%d", i)
54 settle.Token = permit.Token
55 begin(settle)
56 if i == 0 {
57 staleSettle = settle
58 }
59 // A different ID cannot reopen a just-settled operation.
60 repeat := current
61 repeat.ID = "reopen"
62 if _, err := b.Execute(t.Context(), peer, repeat); err == nil {
63 t.Fatal("settled operation reopened")
64 }
65 current.Op = fmt.Sprintf("operation-%d", i)
66 current.ID = fmt.Sprintf("begin-%d", i)
67 permit = begin(current)
68 if _, err := b.Execute(t.Context(), peer, settle); err != nil {
69 t.Fatal("previous settlement lost", err)
70 }
71 }
72 raw, err := d.Read(current.Host + ".json")
73 if err != nil {
74 t.Fatal(err)
75 }
76 if len(raw) >= rootstate.MaxRecord/16 {
77 t.Fatal("unbounded execution record", len(raw))
78 }
79 r, err := b.read(current.Host)
80 if err != nil || len(r.Replay) > 2 {
81 t.Fatal("unbounded replay", len(r.Replay), err)
82 }
83 }
84 calls := remote.calls
85 for _, q := range []ExecutionRequest{stale, base, staleSettle} {
86 if q.ID == "" {
87 continue
88 }
89 if _, err := b.Execute(t.Context(), peer, q); err == nil {
90 t.Fatal("stale request accepted", q.Operation)
91 }
92 }
93 if remote.calls != calls {
94 t.Fatal("stale request made remote write")
95 }
96 // Persisted bounds survive reconstruction of the broker.
97 if err := b.Close(t.Context()); err != nil {
98 t.Fatal(err)
99 }
100 fresh, err := NewRootBroker(b.cfg)
101 if err != nil {
102 t.Fatal(err)
103 }
104 defer fresh.Close(t.Context())
105 if r, err := fresh.read(current.Host); err != nil || len(r.Replay) > 2 {
106 t.Fatal("reload lost bounds", err)
107 }
108 })
109 }
110}
111