Files
mesh-catalog/modules/mesh-issues/cmd/mesh-issues/report_test.go
T
jochen d05308a419
mesh/merge-gate pass: builds mesh-issues → 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-issues: import hq's issue folders at their own numbers, and an issue with a folder is whole in the tracker (hq ADR 0275, to-be 53 slice 3)
2026-10-10 16:00:19 +02:00

199 lines
8.5 KiB
Go

package main
import (
"os"
"path/filepath"
"reflect"
"strings"
"testing"
)
// The reports in testdata/hq are copies of real issue reports of novox/hq, as they stood on 2026-10-10,
// chosen for their shapes: a bracketed list with commas inside parentheses, quoted block items, an
// apostrophe in prose inside a bracketed list, a `resolved:` date, a replay, an empty list, a wontfix.
func readSample(t *testing.T, folder string) string {
t.Helper()
raw, err := os.ReadFile(filepath.Join("testdata", "hq", IssuesFolder, folder, "00-report.md"))
if err != nil {
t.Fatal(err)
}
return string(raw)
}
func TestTheFrontmatterOfRealReportsIsReadAsWritten(t *testing.T) {
cases := []struct {
folder string
want Report
}{
{"362-two-merges-seconds-apart-left-their-delivery-waiting-for-a-person", Report{
Number: 362, Status: StatusResolved, Opened: "2026-10-10",
Title: "Two catalogue merges seconds apart left their delivery waiting for a person",
// A bracketed list whose entries hold commas inside parentheses: two entries, not four.
LocatedIn: []string{"mesh-catalog modules/mesh-delivery (holder.go deliveryWalking)",
"mesh-controller cmd/mesh-controller (upgrades.go SourceMoved, release_plan.go laterOnTheBranch)"},
// A scalar is one entry, commas and all, as hq's own check reads it.
FixedBy: []string{"mesh-catalog#171, mesh-controller#197"},
AmendedDesign: []string{"03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md"},
Replay: "R362",
}},
{"007-an-installed-package-is-not-a-capability", Report{
Number: 7, Status: StatusResolved, Opened: "2026-08-23",
Title: "An installed package is not an available capability",
LocatedIn: []string{"hal (the instance)", "mesh-host internal/bootstrap (preflight asks the daemon)", "mesh-controller internal/catalogue (capabilities)"},
// Quoted block items, each holding colons and commas, taken whole and unquoted.
FixedBy: []string{
"the instance only: PR #962 — incus hook. Merged, ran on one node in 6s of a 60s budget; pipeline #6832 green in 48s. The class remains open.",
"partly, on the mesh: mesh-host 73c010e, 9d8239a — preflight and the profile detectors ask the daemon, not the package (installed-but-broken reports absent)",
"the class, on the mesh: a manifest declares capabilities, an action declares verify (ADR 0005), and a module's own assertions are the lab's verdict (design 01). The old arrangement is replaced module by module, so its count is never taken",
},
AmendedDesign: []string{"03-DESIGN/01-to-be/01-end-to-end-testing.md"},
}},
{"080-a-cache-grant-lets-the-consumer-flush-the-server", Report{
Number: 80, Status: StatusResolved, Opened: "2026-09-22",
Title: "A cache grant lets the consumer flush the server",
// An apostrophe inside prose in a bracketed list is no quote: the list closes on its own line.
LocatedIn: []string{"mesh-catalog modules/redis (the provisioner's ACL)"},
FixedBy: []string{"mesh-catalog multiple-fixes (the consumer's ACL user loses the dangerous command category); proven by " +
"the grant end-to-end bed, which now asserts a write outside the consumer's keys and FLUSHALL are refused"},
}},
{"043-a-module-cannot-be-given-the-meshs-own-queues", Report{
Number: 43, Status: StatusResolved, Opened: "2026-09-12", Closed: "2026-09-12",
Title: "A module cannot be given an account for the mesh's own queues",
LocatedIn: []string{"mesh-controller (the verb existed)"},
FixedBy: []string{"nothing — the capability already existed and the wrong verb was used"},
}},
{"236-the-catalogue-check-passes-a-manifest-the-host-refuses", Report{
Number: 236, Status: StatusResolved, Opened: "2026-10-04",
Title: "The catalogue check passes a manifest the host refuses",
LocatedIn: []string{"mesh-controller cmd/mesh-controller (the merge gate)"},
FixedBy: []string{"novox/mesh-controller PR #96 (bbd442c, the merge gate, ADR 0237)"},
Replay: "R236",
}},
{"345-a-reminder-window-shows-transparent-and-empty", Report{
Number: 345, Status: StatusDiagnosing, Opened: "2026-10-09",
Title: "A calendar reminder shows as a transparent, empty window, and the mesh had no tool to look at it",
}},
{"150-a-route-is-contributed-before-its-module-is-taken", Report{
Number: 150, Status: StatusWontfix, Opened: "2026-09-29",
Title: "A route is contributed before its module is taken",
LocatedIn: []string{"mesh-controller internal/catalogue/declaration.go (contributions are emitted for an assigned module, taken or not)"},
}},
}
for _, c := range cases {
got, err := ParseReport(c.folder, readSample(t, c.folder))
if err != nil {
t.Fatalf("%s: %v", c.folder, err)
}
if got.Folder != IssuesFolder+"/"+c.folder || got.Path != got.Folder+"/00-report.md" {
t.Fatalf("%s: folder %q path %q", c.folder, got.Folder, got.Path)
}
if got.Body == "" || strings.Contains(got.Body, "\n# ") || strings.HasPrefix(got.Body, "# ") || strings.HasPrefix(got.Body, "---") {
t.Fatalf("%s: the body keeps its frontmatter or title: %.80q", c.folder, got.Body)
}
if len(got.Odd) != 0 {
t.Fatalf("%s: odd %v", c.folder, got.Odd)
}
// The title's number and separator are stripped, whatever the separator: "362. ", "043 — ".
got.Folder, got.Path, got.Body, got.Issues, got.Decisions = "", "", "", nil, nil
if !reflect.DeepEqual(*got, c.want) {
t.Fatalf("%s:\n got %+v\n want %+v", c.folder, *got, c.want)
}
}
}
func TestAReportNamesTheIssuesAndDecisionsItCites(t *testing.T) {
r, err := ParseReport("362-two-merges-seconds-apart-left-their-delivery-waiting-for-a-person",
readSample(t, "362-two-merges-seconds-apart-left-their-delivery-waiting-for-a-person"))
if err != nil {
t.Fatal(err)
}
for _, n := range r.Issues {
if n == 362 {
t.Fatal("an issue names itself")
}
}
for _, d := range r.Decisions {
if len(d) != 4 {
t.Fatalf("decision %q", d)
}
}
text := "---\nstatus: open\nopened: 2026-10-10\n---\n# 9. t\n\nSee issue 155, 04-ISSUES/203-x/00-report.md and ADR 0275 " +
"(02-DECISIONS/0019-how.md), and issue 155 again, and issue 9 itself."
r, err = ParseReport("009-t", text)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(r.Issues, []uint64{155, 203}) || !reflect.DeepEqual(r.Decisions, []string{"0019", "0275"}) {
t.Fatalf("issues %v decisions %v", r.Issues, r.Decisions)
}
}
func TestWhatMakesAReportUnreadableAndWhatIsOnlyOdd(t *testing.T) {
refused := map[string]string{
"no frontmatter": "# 9. t\n\nbody",
"no status": "---\nopened: 2026-10-10\n---\n# 9. t\n",
"a sixth status": "---\nstatus: fixed\n---\n# 9. t\n",
"no title": "---\nstatus: open\n---\nbody only\n",
"an empty title": "---\nstatus: open\n---\n# 9.\n",
"no folder shape": "",
}
for what, text := range refused {
folder := "009-t"
if what == "no folder shape" {
folder, text = "nine-t", "---\nstatus: open\n---\n# t\n"
}
if _, err := ParseReport(folder, text); err == nil {
t.Errorf("%s was read", what)
}
}
r, err := ParseReport("009-t", "---\nstatus: open\nopened: yesterday\nseverity: high\nreplay: R1\nreplay: R2\n---\n# 12 — t\n\nbody")
if err != nil {
t.Fatal(err)
}
if r.Opened != "" || r.Replay != "R2" || r.Title != "t" {
t.Fatalf("%+v", r)
}
if r, _ := ParseReport("009-t", "---\nstatus: open\n---\n# 2 nodes share a name\n"); r.Title != "2 nodes share a name" {
t.Fatalf("a title starting with a number: %q", r.Title)
}
if r, _ := ParseReport("009-t", "---\nstatus: open\n---\n# 9 nodes share a name\n"); r.Title != "nodes share a name" {
t.Fatalf("a title starting with the folder's number: %q", r.Title)
}
odd := strings.Join(r.Odd, "\n")
for _, want := range []string{"opened: \"yesterday\" is not a date", "frontmatter keys not imported: severity", "numbered 12; the folder is 9"} {
if !strings.Contains(odd, want) {
t.Fatalf("odd %q lacks %q", odd, want)
}
}
}
func TestTheFrontmatterShapesHqUses(t *testing.T) {
front, body, ok := frontmatter("---\n" +
"a: [x, \"y, z\", (p, q) r]\n" +
"b:\n - one\n - \"two: 2\"\n" +
"c: plain scalar\n wrapped onto a line\n" +
"d:\n" +
"e: []\n" +
"f: [over,\n two lines]\n" +
"g: 'it''s'\n" +
"---\nbody\n")
if !ok || body != "body\n" {
t.Fatalf("ok %v body %q", ok, body)
}
want := map[string][]string{
"a": {"x", "y, z", "(p, q) r"},
"b": {"one", "two: 2"},
"c": {"plain scalar wrapped onto a line"},
"d": nil,
"e": nil,
"f": {"over", "two lines"},
"g": {"it's"},
}
for k, v := range want {
if !reflect.DeepEqual(front[k], v) {
t.Errorf("%s: %q, want %q", k, front[k], v)
}
}
}