package main import ( "strings" "testing" "time" "github.com/novox/mesh-controller/internal/conditions" "github.com/novox/mesh-controller/internal/link" ) // A failed unit is never silent (novox/hq issue 315, "how it is checked"): a module's failed unit raises // the module's condition on the second statement, naming the unit; the machine's own failed units raise // one finding for the machine, listing them, cleared when none is listed; an engine that says nothing of // its units raises and clears nothing; and the gate never holds a send on the machine's own. // desktop is the workstation as found on 2026-10-08, with the mesh's names: the Razer daemon's packaged // user unit, the module's; two mounts of the machine's own table and a unit a removed package left // behind, the machine's. func desktop(at time.Time) link.Health { return link.Health{Contract: link.ReadinessContract, At: at, Resources: []link.ResourceHealth{{Module: "openrazer", Resource: "openrazer.daemon", Kind: link.KindUnit, Target: "openrazer-daemon.service", State: link.StateUnhealthy, Reason: "failed in the account's own service manager (exit-code)", Since: h0, Streak: 2}}, Units: &link.UnitsHealth{State: link.UnitsDegraded, Failed: []link.FailedUnit{ {Unit: "mnt-recalbox.mount", Scope: "system", Load: "loaded", Result: "exit-code", Since: h0}, {Unit: "storage-media.mount", Scope: "system", Load: "loaded", Result: "timeout", Since: h0}, {Unit: "greenclip.service", Scope: "user", Load: "not-found", Result: "start-limit-hit", Since: h0}, }}} } func TestAFailedUnitIsTheModulesConditionAndTheMachinesOwnAreOneFinding(t *testing.T) { open := aMesh(t) ctx := t.Context() inv, k := open.inventory, conditionsFrom openConditions := func() map[string]conditions.Condition { t.Helper() list, err := k.Open(ctx) if err != nil { t.Fatal(err) } out := map[string]conditions.Condition{} for _, c := range list { out[c.Key] = c } return out } say := func(at time.Time, h link.Health) { t.Helper() if err := stateHealth(ctx, inv, k, "laptop", h, at); err != nil { t.Fatal(err) } } say(h0, desktop(h0)) got := openConditions() machine, raised := got["machine.laptop.units"] if !raised || len(got) != 1 { t.Fatalf("the machine's own failed units are one finding at once (the engine looked twice): %v", got) } for _, unit := range []string{"mnt-recalbox.mount", "storage-media.mount", "greenclip.service"} { if !strings.Contains(machine.Summary, unit) { t.Errorf("the finding names %s: %s", unit, machine.Summary) } } if strings.Contains(machine.Summary, "openrazer") || machine.Severity != conditions.Warning { t.Errorf("the module's unit is the module's, and the machine's a warning: %+v", machine) } say(h0.Add(time.Minute), desktop(h0.Add(time.Minute))) got = openConditions() module, raised := got["module.openrazer.laptop.unhealthy"] if !raised || !strings.Contains(module.Summary, "openrazer-daemon.service") || !strings.Contains(module.Summary, "account's own service manager") { t.Fatalf("the module's failed unit raises its condition on the second statement, naming the unit: %+v", got) } kept, had, err := inv.HealthOf(ctx, "laptop") if err != nil || !had || kept.Units == nil || len(kept.Units.Failed) != 3 { t.Fatalf("the statement's units were not kept: %+v %v", kept.Units, err) } lines := strings.Join(unitsLines(kept, had, h0), "\n") for _, want := range []string{"degraded", "storage-media.mount (system) — no module places it", "openrazer-daemon.service — openrazer's"} { if !strings.Contains(lines, want) { t.Errorf("node show does not say %q:\n%s", want, lines) } } // An older engine says nothing of its units: nothing cleared on its word. older := desktop(h0.Add(2 * time.Minute)) older.Units = nil say(h0.Add(2*time.Minute), older) if _, still := openConditions()["machine.laptop.units"]; !still { t.Fatal("a statement saying nothing of units cleared the machine's finding") } // The operator mends the mounts and removes the leftover link; the module's unit still fails. mended := desktop(h0.Add(3 * time.Minute)) mended.Units.Failed = []link.FailedUnit{} say(h0.Add(3*time.Minute), mended) got = openConditions() if _, still := got["machine.laptop.units"]; still { t.Fatalf("no failed unit of the machine's own, still open: %v", got) } if _, still := got["module.openrazer.laptop.unhealthy"]; !still { t.Fatalf("the module's unit still fails, and its condition stands: %v", got) } // And the module's unit mended: running, nothing open. well := link.Health{Contract: link.ReadinessContract, At: h0.Add(4 * time.Minute), Units: &link.UnitsHealth{State: link.UnitsRunning, Failed: []link.FailedUnit{}}} say(h0.Add(4*time.Minute), well) if got = openConditions(); len(got) != 0 { t.Fatalf("a running service manager leaves nothing open: %v", got) } } func TestTheGateNeverHoldsASendOnTheMachinesOwnUnits(t *testing.T) { since := h0 units := conditions.Condition{Key: "machine.laptop.units", Kind: kindMachineUnits, Subject: conditions.Subject{Scope: conditions.ScopeMachine, ID: "laptop", Machine: "laptop"}, Summary: "laptop's service manager is degraded", Raised: since.Add(time.Minute), Source: sourceUnits} if w := aboutTheMachine("laptop", []string{"openrazer"}, since, gateFacts{judged: true, open: []conditions.Condition{units}}); w.whole != "" || w.waiting != "" || len(w.on) != 0 { t.Fatalf("the machine's own failed units held a send: %+v", w) } }