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
199 lines
8.5 KiB
Go
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)
|
|
}
|
|
}
|
|
}
|