mesh/merge-gate head 612f493c4926 merged into trunk 5ba2ffe8e608 — pass: builds mesh-controller → novox; no bus step; every machine composes with the chang…
mesh/repo-check head 612f493c4926 merged into trunk 5ba2ffe8e608 — pass: its merge-check.sh passed
mesh/delivery delivered
128 lines
6.1 KiB
Go
128 lines
6.1 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
// novox/hq issue 296: a plan saved a few seconds ago that has stood in its tier for forty minutes says
|
|
// forty minutes, and LATE — the line counted from the last save, which every advance made.
|
|
func TestAPlansLineCountsFromItsTierNotFromItsLastSave(t *testing.T) {
|
|
now := time.Date(2026, 10, 7, 20, 30, 0, 0, time.UTC)
|
|
asked := now.Add(-40 * time.Minute)
|
|
p := inventory.Plan{ID: "plan-t", Repository: "novox/mesh-catalog", Commit: "3ad22356", State: inventory.PlanBuilding,
|
|
Created: now.Add(-40 * time.Minute), Updated: now.Add(-3 * time.Second), TierEntered: now.Add(-40 * time.Minute),
|
|
Tiers: [][]string{{"a"}}, Modules: map[string]*inventory.PlanModule{"a": {State: "asked", AskedAt: &asked}}}
|
|
|
|
line := planLine(p, now)
|
|
if !strings.Contains(line, "building for 40m0s") || !strings.Contains(line, "LATE") {
|
|
t.Fatalf("a plan in its tier for 40m, saved 3s ago, reads %q", line)
|
|
}
|
|
st := planStatuses([]inventory.Plan{p}, now, pauseView{}, nil)[0]
|
|
if !st.Late || !st.Since.Equal(p.TierEntered) {
|
|
t.Errorf("status --json says %+v", st)
|
|
}
|
|
if _, late := openPlans([]inventory.Plan{p}, now, pauseView{}, nil); late != 1 {
|
|
t.Errorf("status counted %d late", late)
|
|
}
|
|
|
|
// LATE is the stalled condition said on the line: the same start and the same bound, measured or not.
|
|
bounds := boundsOf([]inventory.Duration{{Subject: p.Repository, Took: 20 * time.Minute}})
|
|
if got := bounds.of(p.Repository); got != time.Hour {
|
|
t.Fatalf("a repository whose tiers took 20m is given %s", got)
|
|
}
|
|
if got := bounds.of("novox/other"); got != tierAtLeast {
|
|
t.Fatalf("a repository with nothing measured is given %s", got)
|
|
}
|
|
for _, in := range []time.Duration{40 * time.Minute, 70 * time.Minute} {
|
|
q := p
|
|
q.TierEntered = now.Add(-in)
|
|
bound := bounds.of(q.Repository)
|
|
late := strings.Contains(planLineWith(q, now, pauseView{}, bound), "LATE")
|
|
stalled := len(watchPlans(&signalFacts{now: now, plans: []planFacts{{id: q.ID, repository: q.Repository,
|
|
commit: q.Commit, tiers: 1, entered: inTierSince(q), bound: bound}}})) == 1
|
|
if late != stalled || late != (in > bound) {
|
|
t.Errorf("in its tier %s with a bound of %s: LATE %v, stalled %v", in, bound, late, stalled)
|
|
}
|
|
}
|
|
|
|
// A plan read without its tier's stamp counts from its last save, the only time it has.
|
|
old := p
|
|
old.TierEntered = time.Time{}
|
|
if line := planLine(old, now); !strings.Contains(line, "for 3s") || strings.Contains(line, "LATE") {
|
|
t.Errorf("a plan without its tier's stamp reads %q", line)
|
|
}
|
|
|
|
// A walk that waited for its delivery's word counts its wait from when it was opened, and its tier
|
|
// from the word.
|
|
waiting := p
|
|
waiting.Delivery = &inventory.PlanDelivery{Awaits: catalogue.DeliverySeat}
|
|
waiting.Modules = map[string]*inventory.PlanModule{}
|
|
if line := planLine(waiting, now); !strings.Contains(line, "for 40m0s") || strings.Contains(line, "LATE") {
|
|
t.Errorf("a walk waiting 40m reads %q", line)
|
|
}
|
|
if st := planStatuses([]inventory.Plan{waiting}, now, pauseView{}, nil)[0]; st.Late {
|
|
t.Errorf("a waiting walk is called late: %+v", st)
|
|
}
|
|
let := now.Add(-5 * time.Minute)
|
|
gone := p
|
|
gone.Delivery = &inventory.PlanDelivery{Awaits: catalogue.DeliverySeat, Go: &let}
|
|
if line := planLine(gone, now); !strings.Contains(line, "building for 5m0s") || strings.Contains(line, "LATE") {
|
|
t.Errorf("a walk let go 5m ago, opened 40m ago, reads %q", line)
|
|
}
|
|
}
|
|
|
|
// novox/hq issue 296: a plan whose tier stands still is not written again by every advance — its revision,
|
|
// its last save and its `plan-moved` stay where its last change left them.
|
|
|
|
// novox/hq issue 920: a building plan whose current tier is all built waits on its note (a send refused at the
|
|
// gate), and its line, `status` and the stalled condition say that, not "building for ... LATE".
|
|
func TestAPlanLineSaysTheRefusalOnceItsTierIsBuilt(t *testing.T) {
|
|
now := time.Date(2026, 10, 21, 19, 0, 0, 0, time.UTC)
|
|
built := now.Add(-time.Hour)
|
|
refusal := "tier 1: a build waits there for its gate: novox (mesh-delivery-indexer d68d7ef3→a5aa69a4) — tried again"
|
|
mk := func(second string) inventory.Plan {
|
|
return inventory.Plan{ID: "plan-r", Repository: "novox/mesh-sdk", Commit: "b2f5ebb2", State: inventory.PlanBuilding,
|
|
Tier: 1, Created: now.Add(-2 * time.Hour), Updated: now, TierEntered: now.Add(-time.Hour), Note: refusal,
|
|
Tiers: [][]string{{"a"}, {"b", "c"}},
|
|
Modules: map[string]*inventory.PlanModule{"a": {State: "built", BuiltAt: &built},
|
|
"b": {State: "built", BuiltAt: &built}, "c": {State: second}}}
|
|
}
|
|
|
|
// 920/AC1
|
|
p := mk("built")
|
|
line := planLine(p, now)
|
|
if !strings.Contains(line, "a build waits there for its gate: novox") || strings.Contains(line, "building for") {
|
|
t.Errorf("920/AC1: a plan with its tier built and a refusal reads %q", line)
|
|
}
|
|
st := planStatuses([]inventory.Plan{p}, now, pauseView{}, nil)
|
|
if len(st) != 1 || !st[0].Late {
|
|
t.Errorf("920/AC1: status: %+v", st)
|
|
}
|
|
|
|
// 920/AC2
|
|
if line := planLine(mk("asked"), now); !strings.Contains(line, "building for 1h0m0s") {
|
|
t.Errorf("920/AC2: a plan with a tier module not built reads %q", line)
|
|
}
|
|
}
|
|
|
|
// 920/AC3: a tier move writes the previous tier's summary into the note; with the new tier all built, the line still
|
|
// says "building for", for that note is no refusal.
|
|
func TestAPlanLineDoesNotHoldOnATiersSummary(t *testing.T) {
|
|
now := time.Date(2026, 10, 21, 19, 0, 0, 0, time.UTC)
|
|
built := now.Add(-time.Hour)
|
|
for _, note := range []string{"failed or refused its send (apply-failing says it): novox", "tier 0 built; sent mesh-sdk to novox first, in one send"} {
|
|
p := inventory.Plan{ID: "plan-s", Repository: "novox/mesh-sdk", Commit: "b2f5ebb2", State: inventory.PlanBuilding,
|
|
Tier: 1, Created: now.Add(-2 * time.Hour), Updated: now, TierEntered: now.Add(-time.Hour), Note: note,
|
|
Tiers: [][]string{{"a"}, {"b"}},
|
|
Modules: map[string]*inventory.PlanModule{"a": {State: "built", BuiltAt: &built}, "b": {State: "built", BuiltAt: &built}}}
|
|
if line := planLine(p, now); !strings.Contains(line, "building for 1h0m0s") || strings.Contains(line, "held") {
|
|
t.Errorf("920/AC3: a plan with the note %q reads %q", note, line)
|
|
}
|
|
}
|
|
}
|