carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "context"
5 "testing"
6 "time"
7)
8
9// The probe owners' captured env pins live as long as their wake (home part
10// 2, Task 2b fix round 5). Select captures a pin (in Prerequisites, and
11// again in Admit); every start attempt of the wake materializes under the
12// activator start loop's context, which it cancels when the wake ends:
13// completed, terminally failed or abandoned. A retry of the same launch
14// finds the pin; the end of the wake drops it; a wake that never reaches
15// Materialize leaves nothing past its deadline.
16
17func (f *poFixture) hasEnvPin() bool {
18 f.owners.mu.Lock()
19 defer f.owners.mu.Unlock()
20 _, ok := f.owners.envPins[poHost]
21 return ok
22}
23
24// envPinGone waits for the wake's end to drop the pin (context.AfterFunc
25// runs in its own goroutine).
26func (f *poFixture) envPinGone(t *testing.T, why string) {
27 t.Helper()
28 for deadline := time.Now().Add(2 * time.Second); time.Now().Before(deadline); time.Sleep(5 * time.Millisecond) {
29 if !f.hasEnvPin() {
30 return
31 }
32 }
33 t.Fatalf("%s: the captured pin outlived its wake", why)
34}
35
36func TestCapturedEnvPinLivesWithItsWake(t *testing.T) {
37 t.Run("a completed wake, with a retry", func(t *testing.T) {
38 f := newPOFixture(t)
39 o := f.read()
40 in, err := f.owners.Select(t.Context(), f.route, o, poProbe)
41 if err != nil {
42 t.Fatal(err)
43 }
44 admitted := f.admit(o, in)
45 wake, end := context.WithCancel(t.Context())
46 for attempt := 0; attempt < 2; attempt++ {
47 // the second is a retry of the same launch: it finds the pin
48 if err := f.owners.Materialize(wake, admitted, in, poWork{action: "spawn", f: f}); err != nil {
49 t.Fatalf("attempt %d: %v", attempt, err)
50 }
51 if !f.hasEnvPin() {
52 t.Fatalf("attempt %d: the pin is gone while its wake runs", attempt)
53 }
54 }
55 end() // the start loop returns: the wake completed
56 f.envPinGone(t, "a completed wake")
57 })
58 t.Run("a failed wake", func(t *testing.T) {
59 f := newPOFixture(t)
60 o := f.read()
61 in, err := f.owners.Select(t.Context(), f.route, o, poProbe)
62 if err != nil {
63 t.Fatal(err)
64 }
65 admitted := f.admit(o, in)
66 // The held render no longer matches the pins: every attempt fails.
67 f.renderOverlay = "changed"
68 wake, end := context.WithCancel(t.Context())
69 for attempt := 0; attempt < 2; attempt++ {
70 if err := f.owners.Materialize(wake, admitted, in, poWork{action: "spawn", f: f}); err == nil {
71 t.Fatalf("attempt %d materialized changed inputs", attempt)
72 }
73 if !f.hasEnvPin() {
74 t.Fatalf("attempt %d: the pin is gone before the wake ends", attempt)
75 }
76 }
77 end() // the start loop gives up: the wake failed
78 f.envPinGone(t, "a failed wake")
79 })
80 t.Run("a wake abandoned before Materialize", func(t *testing.T) {
81 f := newPOFixture(t)
82 now := f.owners.Now()
83 policy := poProbe
84 policy.Deadline = now.Add(time.Minute)
85 if _, err := f.owners.Select(t.Context(), f.route, f.read(), policy); err != nil {
86 t.Fatal(err)
87 }
88 if !f.hasEnvPin() {
89 t.Fatal("Select captured no pin")
90 }
91 f.owners.Now = func() time.Time { return now.Add(time.Minute) }
92 if _, ok := f.owners.capturedPin(poHost, nil); ok || f.hasEnvPin() {
93 t.Fatal("a pin past its wake's deadline is still kept")
94 }
95 })
96 t.Run("an earlier wake's end keeps a later capture", func(t *testing.T) {
97 f := newPOFixture(t)
98 o := f.read()
99 in, err := f.owners.Select(t.Context(), f.route, o, poProbe)
100 if err != nil {
101 t.Fatal(err)
102 }
103 admitted := f.admit(o, in)
104 wake, end := context.WithCancel(t.Context())
105 if err := f.owners.Materialize(wake, admitted, in, poWork{action: "spawn", f: f}); err != nil {
106 t.Fatal(err)
107 }
108 // a later wake of the same host captures again before the first
109 // one's end is observed
110 if _, err := f.owners.Select(t.Context(), f.route, admitted, poProbe); err != nil {
111 t.Fatal(err)
112 }
113 end()
114 time.Sleep(50 * time.Millisecond)
115 if !f.hasEnvPin() {
116 t.Fatal("the end of an earlier wake dropped a later capture")
117 }
118 })
119}
120