carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostlife
2
3import (
4 "crypto/sha256"
5 "fmt"
6 "os"
7 "regexp"
8 "strings"
9 "testing"
10)
11
12// TestOneBoxCreateInterruptionTrace is a deterministic trace of the
13// interruptions a one-box create recovers from (two-box plan rev 4,
14// Astra round 1 finding 1): the create's record persists, then its
15// selected box stops, then recovery runs for longer than its 15-step
16// wait; the box starts again (stopped) or the region's group replaces
17// it (destroyed). It writes the whole trace to $HOSTLIFE_TRACE_OUT when
18// set, so the trace at the baseline and after each task can be compared
19// byte for byte; the one-box shape must not change it.
20func TestOneBoxCreateInterruptionTrace(t *testing.T) {
21 saved := boxesPerRegion
22 boxesPerRegion = 1 // the one-box shape, whatever HOSTLIFE_BOXES says (final review minor 5)
23 defer func() { boxesPerRegion = saved }()
24 var out []string
25 for _, how := range []string{"restarted", "replaced"} {
26 w := newWitness()
27 w.console = append(w.console, &consolePlan{Kind: "create", Host: "h", App: app0, OpID: w.newID("cr"), Inc: 1, Region: 0})
28 w.admit[app0].Reg[w.console[0].OpID] = regEntry{Until: w.now + 1000}
29 w.drive(60, func() bool { return w.rec != nil && w.claim != nil && w.claim.Op.Kind == "creating" }, w.runConsole)
30 b := w.boxes[0]
31 b.Destroyed, b.Procs = true, nil
32 w.logf("trace: box %d stopped after the record persisted", b.ID)
33 w.drive(40, func() bool { return false }, w.runConsole, w.recoveryPass)
34 if how == "restarted" {
35 b.Destroyed = false
36 b.forget()
37 } else {
38 w.replaceDestroyed()
39 }
40 w.logf("trace: box %s", how)
41 w.drive(200, func() bool { return w.claim != nil && w.claim.Op.Kind == "serving" }, w.runConsole, w.recoveryPass, w.actAll())
42 out = append(out, "== "+how)
43 out = append(out, w.trace...)
44 c := w.claim
45 out = append(out, fmt.Sprintf("final: op=%s/%s exec=%d holder=%+v rec=%+v lost=%v obl=%d", c.Op.Kind, c.Op.ID, c.Op.Exec, c.Holder, w.rec, c.Lost, len(c.Obl)))
46 }
47 if p := os.Getenv("HOSTLIFE_TRACE_OUT"); p != "" {
48 if err := os.WriteFile(p, []byte(strings.Join(out, "\n")+"\n"), 0o644); err != nil {
49 t.Fatal(err)
50 }
51 }
52}
53
54// TestOneBoxSeedTraces writes one line per seed of the one-box sweep,
55// the SHA-256 of its whole trace, to $HOSTLIFE_TRACE_OUT_SEEDS (and is
56// skipped without it): the per-seed evidence that a task leaves every
57// one-box trace as the baseline's, beyond the aggregate COUNTERS line.
58// Map-ordered fields in state dumps are masked.
59func TestOneBoxSeedTraces(t *testing.T) {
60 p := os.Getenv("HOSTLIFE_TRACE_OUT_SEEDS")
61 if p == "" {
62 t.Skip("HOSTLIFE_TRACE_OUT_SEEDS is not set")
63 }
64 saved := boxesPerRegion
65 boxesPerRegion = 1 // the one-box shape, whatever HOSTLIFE_BOXES says (final review minor 5)
66 defer func() { boxesPerRegion = saved }()
67 mask := regexp.MustCompile(`admission=\[[^\]]*\]`)
68 var out []string
69 for seed := int64(1); seed <= int64(seedsFromEnv(300)); seed++ { // the gate's seeds, 1..n (rev 11, Astra round 8)
70 w := runSeed(seed, true)
71 sum := sha256.Sum256([]byte(mask.ReplaceAllString(strings.Join(w.trace, "\n"), "admission=[masked]")))
72 out = append(out, fmt.Sprintf("%d %x %d", seed, sum[:8], len(w.trace)))
73 }
74 if err := os.WriteFile(p, []byte(strings.Join(out, "\n")+"\n"), 0o644); err != nil {
75 t.Fatal(err)
76 }
77}
78