Files
mesh-catalog/modules/mesh-delivery/cmd/mesh-delivery/issue443_test.go
T
jschoubben 30788c46a1
mesh/merge-gate pass: builds mesh-delivery → 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 fix/443-a-stalled-lines-times-are-local delivered: every member is delivered
mesh-delivery: give an unanswered line's checks as data, so the controller says their times in the operator's zone (novox/hq issue 443)
2026-10-11 03:10:22 +02:00

67 lines
3.0 KiB
Go

package main
import (
"encoding/json"
"slices"
"strings"
"testing"
"time"
)
// **An unanswered line gives the checks it waits on as data** (novox/hq issue 443): each check's context, its state
// and, for a pending one, since when in RFC 3339 — so the controller says the time in the operator's own zone. A time
// inside a finished sentence cannot be said again in another zone, and the operator read "since
// 2026-10-11T00:11:39Z". The finished words stay beside the data, for a controller that does not read it yet.
func TestAnUnansweredLineGivesItsChecksAsData(t *testing.T) {
w := newWorldOver(t, newMemStore(), newFakeController(), newFakeForge(), time.Date(2026, 10, 11, 0, 12, 5, 0, time.UTC))
w.forge.open = openPullsOf(t, strings.Replace(startedNeverAnswered, "2026-10-11T00:11:39Z", "2026-10-11T02:11:39+02:00", 1))
w.h.SeeOpenPulls()
w.later(Bounds[Proposed].For + time.Minute)
lines := w.h.Stalled()
if len(lines) != 1 {
t.Fatalf("the head is not said: %+v", lines)
}
want := []WaitingCheck{{Context: "mesh/merge-gate", State: CheckPending, Since: "2026-10-11T00:11:39Z"},
{Context: "mesh/repo-check", State: CheckNeverSet}}
if !slices.Equal(lines[0].Checks, want) {
t.Fatalf("the line's checks are %+v, not %+v", lines[0].Checks, want)
}
if words := []string{"mesh/merge-gate pending since 2026-10-11T00:11:39Z", "mesh/repo-check never set"}; !slices.Equal(lines[0].Waiting, words) {
t.Fatalf("the finished words a controller of before reads are gone: %q", lines[0].Waiting)
}
raw, _ := json.Marshal(lines[0])
t.Logf("the line as the controller reads it: %s", raw)
if !strings.Contains(string(raw), `"checks":[{"context":"mesh/merge-gate","state":"pending","since":"2026-10-11T00:11:39Z"},{"context":"mesh/repo-check","state":"never-set"}]`) {
t.Fatalf("the line's checks are not in the shape the controller reads: %s", raw)
}
}
// The data and the words never disagree: for every head the words are made from, the checks give the same contexts
// in the same order, and a pending time the forge did not say, or said unreadably, is given as no time at all.
func TestAnUnansweredLinesChecksAgreeWithItsWords(t *testing.T) {
for _, tc := range []struct {
name, at string
since string
}{{"a time in UTC", "2026-10-11T00:11:39Z", "2026-10-11T00:11:39Z"},
{"a time with an offset", "2026-10-11T02:11:39+02:00", "2026-10-11T00:11:39Z"},
{"no time", "", ""},
{"an unreadable time", "yesterday", ""}} {
t.Run(tc.name, func(t *testing.T) {
p := openPullsOf(t, strings.Replace(startedNeverAnswered, "2026-10-11T00:11:39Z", tc.at, 1))[0]
words, _, _ := p.unanswered()
checks := p.waitingChecks()
if len(words) != len(checks) {
t.Fatalf("words %q, checks %+v", words, checks)
}
for i, c := range checks {
if !strings.HasPrefix(words[i], c.Context+" ") {
t.Fatalf("word %q is not of check %+v", words[i], c)
}
}
if checks[0].State != CheckPending || checks[0].Since != tc.since {
t.Fatalf("the pending check is %+v, not since %q", checks[0], tc.since)
}
})
}
}