Files
mesh-catalog/modules/mesh-issues/cmd/mesh-issues/tracking_test.go
T
jochen 12619ec140
mesh/merge-gate pass: builds mesh-issues, messenger → novox; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery delivered
mesh/delivery-group group feat/400-alert-names-its-issue delivered: every member is delivered
Check that tracking says no event and writes nothing, as ADR 0285 states
2026-10-10 21:51:30 +02:00

166 lines
6.0 KiB
Go

package main
import (
"encoding/json"
"reflect"
"strings"
"testing"
"time"
)
// Which issues track which conditions (novox/hq issue 400, ADR 0285).
const mountsKey = "module.mounts.shanks.unhealthy"
func TestTrackingAnswersTheIssuesThatLinkEachCondition(t *testing.T) {
h := newHarness(t)
now := clocked(h)
a := h.open(t, "mounts fail on shanks", "mesh-catalog")
b := h.open(t, "a wait for the operator's secret", "mesh-controller")
c := h.open(t, "rolled-back is repaired by hand", "mesh-controller")
d := h.open(t, "unrelated", "hq")
for _, l := range []LinkAsk{
{Number: a, Kind: LinkCondition, Target: mountsKey},
{Number: b, Kind: LinkCondition, Target: mountsKey},
{Number: c, Kind: LinkCondition, Target: "mesh.hand-acts.rolled-back.healer-wanted"},
{Number: d, Kind: LinkRelatesTo, Target: "365"},
} {
if _, err := h.Link(l); err != nil {
t.Fatal(err)
}
}
if _, err := h.Move(MoveAsk{Number: b, Status: StatusFixing, By: "fix-386@g14"}); err != nil {
t.Fatal(err)
}
if _, err := h.Set(SetAsk{Number: c, Needs: "operator"}); err != nil {
t.Fatal(err)
}
*now = now.Add(25 * time.Hour)
got, err := h.Tracking(nil)
if err != nil {
t.Fatal(err)
}
if len(got.Conditions) != 2 || got.Said != "Issues track 2 conditions." {
t.Fatalf("%+v", got)
}
m := got.Conditions[mountsKey]
if len(m) != 2 || m[0].Number != a || m[1].Number != b {
t.Fatalf("mounts: %+v", m)
}
if m[0].Worker != "" || m[0].Status != StatusOpen {
t.Errorf("nobody works on %d: %+v", a, m[0])
}
if m[1].Worker != "fix-386@g14" || m[1].Since == nil || m[1].Active == nil || !m[1].Stale || m[1].Status != StatusFixing {
t.Errorf("the worker of %d, gone quiet a day: %+v", b, m[1])
}
if r := got.Conditions["mesh.hand-acts.rolled-back.healer-wanted"]; len(r) != 1 || r[0].Number != c || r[0].Needs != "operator" {
t.Errorf("rolled-back: %+v", r)
}
// Only the keys asked; one nobody links is said.
only, err := h.Tracking([]string{"machine.ace.silent"})
if err != nil || len(only.Conditions) != 0 || only.Said != "No issue tracks machine.ace.silent." {
t.Fatalf("%+v %v", only, err)
}
if _, err := h.Tracking([]string{"a key\nwith a line"}); err == nil {
t.Fatal("a key not of a condition key's shape was taken")
}
}
// A resolved issue comes after those not closed, and the answer holds at most MostTrackingPerCondition for a key.
func TestTrackingPutsOpenIssuesFirstAndIsBounded(t *testing.T) {
h := newHarness(t)
var numbers []uint64
for i := 0; i < MostTrackingPerCondition+2; i++ {
n := h.open(t, "one of many", "hq")
if _, err := h.Link(LinkAsk{Number: n, Kind: LinkCondition, Target: mountsKey}); err != nil {
t.Fatal(err)
}
numbers = append(numbers, n)
}
first := numbers[0]
h.fixing(t, first)
if _, err := h.Move(MoveAsk{Number: first, Status: StatusResolved, LocatedIn: []string{"hq"}, FixedBy: []string{"hq#1"}}); err != nil {
t.Fatal(err)
}
got, err := h.Tracking(nil)
if err != nil {
t.Fatal(err)
}
list := got.Conditions[mountsKey]
if len(list) != MostTrackingPerCondition {
t.Fatalf("%d issues, want %d", len(list), MostTrackingPerCondition)
}
for _, is := range list {
if is.Number == first {
t.Fatalf("the resolved issue was not put last: %+v", list)
}
}
if list[0].Number != numbers[1] {
t.Errorf("not by number: %+v", list)
}
}
// Where a fix stands, one word per case, in DeliveryLine's order.
func TestFixStateSaysWhereTheFixIs(t *testing.T) {
merged := true
cases := []struct {
name string
is Issue
want string
}{
{"no fix named", Issue{}, ""},
{"nothing heard", Issue{FixedBy: []string{"mesh-catalog#1"}}, "unheard"},
{"not merged", Issue{FixedBy: []string{"mesh-catalog#1"}, Fixes: []Fix{{PullRequest: "mesh-catalog#1", State: "open"}}}, "not-merged"},
{"merged", Issue{FixedBy: []string{"mesh-catalog#1"}, Fixes: []Fix{{PullRequest: "mesh-catalog#1", State: "merged", Merged: merged}}}, "merged"},
{"held", Issue{FixedBy: []string{"mesh-catalog#1"}, Fixes: []Fix{{PullRequest: "mesh-catalog#1", State: "held", Merged: merged}}}, "held"},
{"failed", Issue{FixedBy: []string{"mesh-catalog#1"}, Fixes: []Fix{{PullRequest: "mesh-catalog#1", State: "failed", Merged: merged}}}, "failed"},
{"delivered", Issue{FixedBy: []string{"mesh-catalog#1"}, Delivered: []string{"mesh-catalog#1"}}, "delivered"},
{"one of two failed", Issue{FixedBy: []string{"mesh-catalog#1", "mesh-controller#2"}, Delivered: []string{"mesh-catalog#1"},
Fixes: []Fix{{PullRequest: "mesh-controller#2", State: "stopped", Merged: merged}}}, "failed"},
}
for _, c := range cases {
if got := FixState(&c.is); got != c.want {
t.Errorf("%s: %q, want %q (its line: %q)", c.name, got, c.want, DeliveryLine(&c.is))
}
}
}
// The verb as the tool runner calls it; its answer carries no report, note or title (nothing the router does not
// need), and so no secret an issue's words might hold.
func TestTheTrackingVerb(t *testing.T) {
h := newHarness(t)
n := h.open(t, "mounts fail", "hq")
if _, err := h.Link(LinkAsk{Number: n, Kind: LinkCondition, Target: mountsKey}); err != nil {
t.Fatal(err)
}
if _, err := h.Note(n, "the share's password=hunter2 was typed here"); err != nil {
t.Fatal(err)
}
events, before := len(h.said()), h.mem.snapshot(IssuesState)
out, err := h.call(t, "tracking", map[string]any{})
if err != nil {
t.Fatal(err)
}
// A read: no event said, nothing written.
if len(h.said()) != events || !reflect.DeepEqual(h.mem.snapshot(IssuesState), before) {
t.Fatal("tracking said an event or wrote an issue")
}
raw, _ := json.Marshal(out)
if !strings.Contains(string(raw), `"`+mountsKey+`":[{"number":`) {
t.Fatalf("%s", raw)
}
for _, leak := range []string{"hunter2", "mounts fail", "seen:"} {
if strings.Contains(string(raw), leak) {
t.Errorf("the answer carries %q: %s", leak, raw)
}
}
if _, err := h.call(t, "tracking", map[string]any{"conditions": []string{mountsKey}}); err != nil {
t.Fatal(err)
}
if _, err := h.call(t, "tracking", map[string]any{"number": 1}); err == nil {
t.Fatal("an argument it does not take was accepted")
}
}