carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package activator
2
3import (
4 "context"
5 "errors"
6 "sync/atomic"
7 "testing"
8 "time"
9
10 "github.com/carlosframework/platform/internal/registry"
11)
12
13// Final review round 1, finding 6 (Astra): a failed wake's cleanup decides
14// whether to prove the host cgroup from the layout its launch used, not
15// from the layout the row reads at cleanup. A flat launch whose layout reads
16// fenced or conflicting by the time the cleanup runs is still proven, and so
17// is a nested launch whose layout no longer reads nested (unknown, fenced,
18// conflicting or flat): only a launch that was nested, and still reads
19// nested, keeps its own proof (ruling c). Here the host cgroup stays
20// populated, so a proven wake is retained and its lease kept.
21func TestAFailedWakeIsProvenByTheLayoutItsLaunchUsed(t *testing.T) {
22 t.Parallel()
23 for _, row := range []struct {
24 name string
25 launch, cleanup Layout
26 retained, killed bool
27 }{
28 {"flat, fenced at cleanup", LayoutFlat, LayoutFenced, true, true},
29 {"flat, conflicting at cleanup", LayoutFlat, LayoutConflict, true, true},
30 {"nested, fenced at cleanup", LayoutNested, LayoutFenced, true, true},
31 {"nested, flat at cleanup", LayoutNested, LayoutFlat, true, true},
32 {"nested, still nested", LayoutNested, LayoutNested, false, false},
33 } {
34 t.Run(row.name, func(t *testing.T) {
35 a, b, _, _ := testActivator(t, time.Hour)
36 a.gens = false
37 var launched atomic.Bool
38 b.layoutFn = func(registry.Route) (Layout, string) {
39 if launched.Load() {
40 return row.cleanup, "changed after the launch"
41 }
42 return row.launch, ""
43 }
44 leader := &sigtermIgnorer{}
45 leader.exited.Store(true)
46 kb := &killGenBackend{fakeBackend: b, err: errNoGenContainment}
47 ub := &unprovenStartBackend{killGenBackend: kb, fail: func(uint64) (Proc, error) {
48 launched.Store(true) // the layout changes once the launch has run
49 return leader, errors.New("health: no answer within 30s")
50 }}
51 hb := &uncontainedStartBackend{unprovenStartBackend: ub, populated: true}
52 a.backend = hb
53 rt := testRoute("f6-layout.example.com")
54 if _, err := a.beginRequest(context.Background(), rt); err == nil {
55 t.Fatal("the wake should have failed")
56 }
57 a.mu.Lock()
58 _, retained := a.unprovenWakes[rt.Host]
59 a.mu.Unlock()
60 if retained != row.retained {
61 t.Fatalf("retained = %v, want %v", retained, row.retained)
62 }
63 if asked := hb.hostKillCount() > 0; asked != row.killed {
64 t.Fatalf("KillHost asked = %v, want %v", asked, row.killed)
65 }
66 })
67 }
68}
69