Name no node in mesh-issues's fixtures (issue 1838)

This commit is contained in:
jochen
2026-10-22 21:48:39 +02:00
parent 0a398579e2
commit c88b75a822
12 changed files with 114 additions and 114 deletions
@@ -651,7 +651,7 @@ func TestAnIssueIsOpenedNotedLinkedMovedAndListedOverTheBus(t *testing.T) {
t.Fatal("resolved without located-in")
}
must(i.call("move", map[string]any{"number": 365, "status": "located", "located-in": []string{"mesh-controller internal/gate"}}))
must(i.call("move", map[string]any{"number": 365, "status": "fixing", "by": "fix-365@g14"}))
must(i.call("move", map[string]any{"number": 365, "status": "fixing", "by": "fix-365@node-b"}))
if _, err := i.call("move", map[string]any{"number": 365, "status": "resolved", "fixed-by": []string{"mesh-controller#300"}}); err == nil {
t.Fatal("a core issue resolved without a replay")
}
@@ -674,7 +674,7 @@ func TestAnIssueIsOpenedNotedLinkedMovedAndListedOverTheBus(t *testing.T) {
// The move to fixing carries who works on it; every other change, who acted (ADR 0284 §6).
want := Unproven
if e.Key == EventMoved && e.Body["to"] == StatusFixing {
want = "fix-365@g14"
want = "fix-365@node-b"
}
if e.Body["by"] != want || e.Body["number"] != float64(365) {
t.Fatalf("event %+v", e)
@@ -80,7 +80,7 @@ func (s *served) call(t *testing.T, verb, caller string, args map[string]any) (m
func TestWhoActedIsTheCallerTheRuntimeProved(t *testing.T) {
h, _ := reserveHarness(t)
s := serve(t, h)
const who = "shanks.node-tools"
const who = "node-d.node-tools"
opened, refused := s.call(t, "open", who, map[string]any{"title": "a title", "report": "a report"})
if refused != "" || opened["by"] != who {
t.Fatalf("open answered %v %q, want by %s", opened, refused, who)
@@ -100,7 +100,7 @@ func TestWhoActedIsTheCallerTheRuntimeProved(t *testing.T) {
if _, refused := s.call(t, "set", who, map[string]any{"number": n, "severity": "minor"}); refused != "" {
t.Errorf("set refused: %s", refused)
}
if _, refused := s.call(t, "move", who, map[string]any{"number": n, "status": "fixing", "by": "fix-1@g14"}); refused != "" {
if _, refused := s.call(t, "move", who, map[string]any{"number": n, "status": "fixing", "by": "fix-1@node-b"}); refused != "" {
t.Errorf("move refused: %s", refused)
}
if reserved, refused := s.call(t, "reserve", who, map[string]any{"kind": "decision", "for": "a decision"}); refused != "" || reserved["by"] != who {
@@ -125,11 +125,11 @@ func TestACallerInTheArgumentsIsRefusedAndAnUnprovenCallSaysSo(t *testing.T) {
h := newHarness(t)
s := serve(t, h)
for _, args := range []map[string]any{
{"title": "t", "report": "r", "caller": "novox.node-tools"},
{"title": "t", "report": "r", "_meta": map[string]any{stdio.MetaCaller: "novox.node-tools"}},
{"title": "t", "report": "r", "by": "novox.node-tools"},
{"title": "t", "report": "r", "caller": "node-c.node-tools"},
{"title": "t", "report": "r", "_meta": map[string]any{stdio.MetaCaller: "node-c.node-tools"}},
{"title": "t", "report": "r", "by": "node-c.node-tools"},
} {
if out, refused := s.call(t, "open", "shanks.node-tools", args); refused == "" || !strings.Contains(refused, "does not take") {
if out, refused := s.call(t, "open", "node-d.node-tools", args); refused == "" || !strings.Contains(refused, "does not take") {
t.Errorf("an open naming a caller in its arguments %v was answered %v", args, out)
}
}
@@ -55,7 +55,7 @@ func TestALinkedFixDeliveredIsNotedOnceNamingItsWorker(t *testing.T) {
h := newHarness(t)
now := clocked(h)
n := h.open(t, "a build fails during the registry's clean-up", "mesh-controller")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-457@shanks"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-457@node-d"}); err != nil {
t.Fatal(err)
}
linkPR(t, h, n, "mesh-catalog#225")
@@ -84,12 +84,12 @@ func TestALinkedFixDeliveredIsNotedOnceNamingItsWorker(t *testing.T) {
t.Fatalf("want one note, got %q", said)
}
for _, want := range []string{"mesh-catalog#225", "mesh-catalog#226", delivered.Format(time.RFC3339),
delivered.Add(time.Minute).Format(time.RFC3339), "fix-457@shanks"} {
delivered.Add(time.Minute).Format(time.RFC3339), "fix-457@node-d"} {
if !strings.Contains(said[0], want) {
t.Fatalf("the note does not say %q: %s", want, said[0])
}
}
if is.Status != StatusFixing || is.Worker == nil || is.Worker.By != "fix-457@shanks" {
if is.Status != StatusFixing || is.Worker == nil || is.Worker.By != "fix-457@node-d" {
t.Fatalf("the tracker's own note changed the issue's work: %+v", is)
}
var ev map[string]any
@@ -98,7 +98,7 @@ func TestALinkedFixDeliveredIsNotedOnceNamingItsWorker(t *testing.T) {
ev = e.Body
}
}
if countEvents(h, EventReadyToVerify) != 1 || ev["worker"] != "fix-457@shanks" {
if countEvents(h, EventReadyToVerify) != 1 || ev["worker"] != "fix-457@node-d" {
t.Fatalf("%d ready-to-verify, last %v", countEvents(h, EventReadyToVerify), ev)
}
// The tracker's own note keeps no worker current: the worker's activity is still its own last act.
@@ -115,7 +115,7 @@ func TestDeliveredNotResolvedIsWarnedAfterTheBoundAndClearedWhenItLeavesFixing(t
note := &notified{}
h.Notify = note.notify
n := h.open(t, "x", "mesh-catalog modules/records")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-x@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-x@node-b"}); err != nil {
t.Fatal(err)
}
linkPR(t, h, n, "mesh-catalog#9")
@@ -125,7 +125,7 @@ func TestDeliveredNotResolvedIsWarnedAfterTheBoundAndClearedWhenItLeavesFixing(t
t.Fatalf("warned under the bound: %q %v", note.said, err)
}
if rows := rowsOf(t, h, map[string]any{"flag": "delivered-not-resolved"}); len(rows) != 1 ||
rows[0]["delivered-not-resolved"] != true || rows[0]["worker"] != "fix-x@g14" {
rows[0]["delivered-not-resolved"] != true || rows[0]["worker"] != "fix-x@node-b" {
t.Fatalf("list flag delivered-not-resolved: %v", rows)
}
*now = now.Add(2 * time.Minute)
@@ -136,7 +136,7 @@ func TestDeliveredNotResolvedIsWarnedAfterTheBoundAndClearedWhenItLeavesFixing(t
}
key := "issue-tracker.delivered-not-resolved.365"
if len(note.said) != 1 || !strings.HasPrefix(note.said[0], key+" warning ") ||
!strings.Contains(note.said[0], "fixed and delivered, not resolved") || !strings.Contains(note.said[0], "fix-x@g14") ||
!strings.Contains(note.said[0], "fixed and delivered, not resolved") || !strings.Contains(note.said[0], "fix-x@node-b") ||
!strings.Contains(note.said[0], "365") {
t.Fatalf("said %q", note.said)
}
@@ -165,7 +165,7 @@ func TestDeliveredNotResolvedIsWarnedAfterTheBoundAndClearedWhenItLeavesFixing(t
t.Fatal(err)
}
m := h2.open(t, "y", "mesh-catalog modules/records")
if _, err := h2.Move(MoveAsk{Number: m, Status: StatusFixing, By: "fix-y@g14"}); err != nil {
if _, err := h2.Move(MoveAsk{Number: m, Status: StatusFixing, By: "fix-y@node-b"}); err != nil {
t.Fatal(err)
}
linkPR(t, h2, m, "mesh-catalog#9")
@@ -184,7 +184,7 @@ func TestDeliveredNotResolvedIsRetriedAndClearedAtTheSweep(t *testing.T) {
note := &notified{err: errStuck}
h.Notify = note.notify
n := h.open(t, "x", "mesh-catalog modules/records")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-x@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-x@node-b"}); err != nil {
t.Fatal(err)
}
linkPR(t, h, n, "mesh-catalog#9")
@@ -211,11 +211,11 @@ func TestAnAbandonedIssueIsFlaggedAndTakenOverWithoutAReason(t *testing.T) {
h := newHarness(t)
now := clocked(h)
n := h.open(t, "claimed and left", "hq")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "build-424@shanks"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "build-424@node-d"}); err != nil {
t.Fatal(err)
}
busy := h.open(t, "claimed, with a pull request in review", "hq")
if _, err := h.Move(MoveAsk{Number: busy, Status: StatusFixing, By: "fix-b@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: busy, Status: StatusFixing, By: "fix-b@node-b"}); err != nil {
t.Fatal(err)
}
linkPR(t, h, busy, "mesh-catalog#9")
@@ -226,7 +226,7 @@ func TestAnAbandonedIssueIsFlaggedAndTakenOverWithoutAReason(t *testing.T) {
}
*now = now.Add(2 * time.Hour)
rows := rowsOf(t, h, map[string]any{"flag": "abandoned"})
if len(rows) != 1 || rows[0]["number"] != float64(n) || rows[0]["worker"] != "build-424@shanks" || rows[0]["abandoned"] != true {
if len(rows) != 1 || rows[0]["number"] != float64(n) || rows[0]["worker"] != "build-424@node-d" || rows[0]["abandoned"] != true {
t.Fatalf("want only %d flagged naming its worker, got %v", n, rows)
}
if v := asJSON(t, mustView(t, h, n)); v["abandoned"] != true {
@@ -235,7 +235,7 @@ func TestAnAbandonedIssueIsFlaggedAndTakenOverWithoutAReason(t *testing.T) {
if v := asJSON(t, mustView(t, h, busy)); v["abandoned"] == true {
t.Fatal("an issue with an open pull request is flagged")
}
m, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-483@shanks"})
m, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-483@node-d"})
if err != nil {
t.Fatalf("an abandoned issue was not taken over without a reason: %v", err)
}
@@ -244,11 +244,11 @@ func TestAnAbandonedIssueIsFlaggedAndTakenOverWithoutAReason(t *testing.T) {
}
is := get(t, h, n)
last := is.Notes[len(is.Notes)-1].Text
if !strings.Contains(last, "abandoned") || !strings.Contains(last, "build-424@shanks") {
if !strings.Contains(last, "abandoned") || !strings.Contains(last, "build-424@node-d") {
t.Fatalf("the note does not say it was abandoned: %s", last)
}
for _, e := range h.said() {
if e.Event == EventMoved && e.Body["took-over-from"] == "build-424@shanks" && e.Body["abandoned"] != true {
if e.Event == EventMoved && e.Body["took-over-from"] == "build-424@node-d" && e.Body["abandoned"] != true {
t.Fatalf("the moved event does not say it was abandoned: %v", e.Body)
}
}
@@ -269,7 +269,7 @@ func TestTheSweepAsksALinkedPullRequestNeverHeardOf(t *testing.T) {
h := newHarness(t)
now := clocked(h)
n := h.open(t, "x", "mesh-catalog modules/records")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-x@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-x@node-b"}); err != nil {
t.Fatal(err)
}
linkPR(t, h, n, "mesh-catalog#209")
@@ -317,7 +317,7 @@ func TestAPullRequestClosedUnmergedIsWithdrawn(t *testing.T) {
note := &notified{}
h.Notify = note.notify
n := h.open(t, "x", "mesh-catalog modules/records")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-x@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-x@node-b"}); err != nil {
t.Fatal(err)
}
linkPR(t, h, n, "mesh-catalog#9")
@@ -370,7 +370,7 @@ func TestOnePullRequestLinkedToSeveralIssues(t *testing.T) {
note := &notified{}
h.Notify = note.notify
var ns []uint64
for _, w := range []string{"fix-a@g14", "fix-b@shanks"} {
for _, w := range []string{"fix-a@node-b", "fix-b@node-d"} {
n := h.open(t, "x "+w, "mesh-catalog modules/records")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: w}); err != nil {
t.Fatal(err)
@@ -386,8 +386,8 @@ func TestOnePullRequestLinkedToSeveralIssues(t *testing.T) {
if _, err := h.Sweep(); err != nil {
t.Fatal(err)
}
if len(note.said) != 2 || !strings.Contains(strings.Join(note.said, "\n"), "fix-a@g14") ||
!strings.Contains(strings.Join(note.said, "\n"), "fix-b@shanks") {
if len(note.said) != 2 || !strings.Contains(strings.Join(note.said, "\n"), "fix-a@node-b") ||
!strings.Contains(strings.Join(note.said, "\n"), "fix-b@node-d") {
t.Fatalf("said %q", note.said)
}
if _, err := h.Move(MoveAsk{Number: ns[0], Status: StatusResolved, FixedBy: []string{"mesh-catalog#9"}}); err != nil {
@@ -10,8 +10,8 @@ import (
// answered on 2026-10-11.
var realConditionKeys = []string{
"delivery.novox/mesh-controller_d2e9dc61590f.stalled", // a delivery's id carries its repository, owner/name
"machine.novox.telegram.telegram-token.secret-given",
"module.openrazer.shanks.relogin-needed",
"machine.node-c.telegram.telegram-token.secret-given",
"module.openrazer.node-d.relogin-needed",
"mesh.hand-acts.plans_go.healer-wanted", // a space in the id, made `_` by the controller
"delivery.leaf.over-budget",
}
@@ -37,15 +37,15 @@ func TestAConditionLinkTakesEveryKeyTheControllerRaises(t *testing.T) {
func TestAConditionLinkRefusesWhatTheControllerNeverRaises(t *testing.T) {
for _, k := range []string{
"",
"delivery.stalled", // no id: a key is scope, id and kind
"weather.novox.rain", // no scope the controller knows
"machine..secret-given", // an empty token
"machine.novox.secret given", // a space the controller makes `_`
"machine.novox:1.secret-given", // a colon the controller makes `_`
"delivery.stalled", // no id: a key is scope, id and kind
"weather.node-c.rain", // no scope the controller knows
"machine..secret-given", // an empty token
"machine.node-c.secret given", // a space the controller makes `_`
"machine.node-c:1.secret-given", // a colon the controller makes `_`
"delivery.novox/mesh-controller@d2e9dc61590f.stalled", // `@` too
"machine.*.silent", // a wildcard on the bus
"machine.>", // a wildcard on the bus
"machine.ace.silent\nmore", // a second line
"machine.*.silent", // a wildcard on the bus
"machine.>", // a wildcard on the bus
"machine.node-a.silent\nmore", // a second line
"machine." + strings.Repeat("a", 300) + ".silent",
} {
if _, err := checkTarget(LinkCondition, k); err == nil {
@@ -23,7 +23,7 @@ type notified struct {
func fixedAtFixing(t *testing.T, h *harness, n uint64, fixedBy ...string) {
t.Helper()
h.fixing(t, n)
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@g14", LocatedIn: []string{"mesh-catalog modules/records"},
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@node-b", LocatedIn: []string{"mesh-catalog modules/records"},
FixedBy: fixedBy}); err != nil {
t.Fatal(err)
}
@@ -77,7 +77,7 @@ func (c *fixClock) fixOne(t *testing.T, title string, pr int, class string, impl
t.Helper()
n := c.open(t, title)
c.fixing(t, n)
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@g14", FixedBy: []string{"mesh-catalog#" + itoa(pr)}}); err != nil {
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@node-b", FixedBy: []string{"mesh-catalog#" + itoa(pr)}}); err != nil {
t.Fatal(err)
}
opened := c.later(implementing)
@@ -101,23 +101,23 @@ func TestAFixTimeRunsFromTheFirstMoveToFixingAndAddsUpItsPhases(t *testing.T) {
n := c.open(t, "a fix measured")
c.later(time.Minute)
if _, err := c.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix@g14"}); err != nil {
if _, err := c.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix@node-b"}); err != nil {
t.Fatal(err)
}
c.later(10 * time.Minute) // finding the cause is not the fix's time
start := c.at
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@g14", FixedBy: []string{"mesh-catalog#31"}}); err != nil {
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@node-b", FixedBy: []string{"mesh-catalog#31"}}); err != nil {
t.Fatal(err)
}
c.later(30 * time.Second)
// A take-over, and a move away and back, restart nothing.
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "other@shanks", TakeOver: "the first worker's session ended"}); err != nil {
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "other@node-d", TakeOver: "the first worker's session ended"}); err != nil {
t.Fatal(err)
}
if _, err := c.Move(MoveAsk{Number: n, Status: StatusOpen}); err != nil {
t.Fatal(err)
}
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "other@shanks"}); err != nil {
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "other@node-d"}); err != nil {
t.Fatal(err)
}
opened := c.later(90 * time.Second) // implementing: 2m
@@ -147,7 +147,7 @@ func TestAFixTimeRunsFromTheFirstMoveToFixingAndAddsUpItsPhases(t *testing.T) {
got[PhaseRunning] != 2*time.Minute {
t.Fatalf("phases %v", got)
}
if ft.Class != ClassLeaf || !ft.Over || ft.Budget != "5m0s" || ft.Longest != "checks 3m0s" || ft.Worker != "other@shanks" {
if ft.Class != ClassLeaf || !ft.Over || ft.Budget != "5m0s" || ft.Longest != "checks 3m0s" || ft.Worker != "other@node-d" {
t.Fatalf("class %q over %v budget %q longest %q worker %q", ft.Class, ft.Over, ft.Budget, ft.Longest, ft.Worker)
}
// Over its budget: said once, naming the issue, its worker and its longest phase.
@@ -170,7 +170,7 @@ func TestAPhaseNotKnownIsCountedInTheNextAndOneEndedEarlyCountsZero(t *testing.T
opened := c.at
c.later(time.Minute)
c.fixing(t, n)
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@g14", FixedBy: []string{"mesh-catalog#32"}}); err != nil {
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@node-b", FixedBy: []string{"mesh-catalog#32"}}); err != nil {
t.Fatal(err)
}
merged := c.later(4 * time.Minute)
@@ -206,7 +206,7 @@ func TestAnIssuesClassIsItsSlowestFixAndOneMovingNothingHasNoBudget(t *testing.T
n := c.open(t, "two fixes, one core")
c.fixing(t, n)
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@g14", FixedBy: []string{"mesh-catalog#41", "mesh-catalog#42"}}); err != nil {
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@node-b", FixedBy: []string{"mesh-catalog#41", "mesh-catalog#42"}}); err != nil {
t.Fatal(err)
}
merged := c.later(time.Minute)
@@ -246,7 +246,7 @@ func TestAFixOverItsBudgetIsSaidOnceFinalAndClearedByTheNextWithin(t *testing.T)
n := c.open(t, "a slow fix")
c.fixing(t, n)
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@g14", FixedBy: []string{"mesh-catalog#51"}}); err != nil {
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@node-b", FixedBy: []string{"mesh-catalog#51"}}); err != nil {
t.Fatal(err)
}
merged := c.later(20 * time.Minute)
@@ -383,12 +383,12 @@ func TestACarriedIssueStartsAtTheMoveNotTheDiagnosis(t *testing.T) {
t.Fatal(err)
}
}
carry(900, Issue{Number: 900, Title: "x", Status: StatusDiagnosing, Worker: &Worker{By: "fix@g14", Since: diagnosed, Active: diagnosed}})
carry(900, Issue{Number: 900, Title: "x", Status: StatusFixing, Worker: &Worker{By: "fix@g14", Since: diagnosed, Active: moved}})
carry(900, Issue{Number: 900, Title: "x", Status: StatusDiagnosing, Worker: &Worker{By: "fix@node-b", Since: diagnosed, Active: diagnosed}})
carry(900, Issue{Number: 900, Title: "x", Status: StatusFixing, Worker: &Worker{By: "fix@node-b", Since: diagnosed, Active: moved}})
if got, fromLog := c.startOfFixing(&Issue{Number: 900}); !got.Equal(moved) || !fromLog {
t.Fatalf("start %s (from the log %v), want the move at %s, not the diagnosis at %s", got, fromLog, moved, diagnosed)
}
carry(901, Issue{Number: 901, Title: "y", Status: StatusFixing, Worker: &Worker{By: "fix@g14", Since: diagnosed, Active: moved}})
carry(901, Issue{Number: 901, Title: "y", Status: StatusFixing, Worker: &Worker{By: "fix@node-b", Since: diagnosed, Active: moved}})
if got, _ := c.startOfFixing(&Issue{Number: 901}); !got.Equal(diagnosed) {
t.Fatalf("a first value at fixing: %s, want its worker's since %s", got, diagnosed)
}
@@ -402,7 +402,7 @@ func TestAFixWhoseStartCameFromTheLogIsNeverWarnedOn(t *testing.T) {
c.Notify = note.notify
n := c.open(t, "fixed before the tracker measured")
c.fixing(t, n)
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@g14", FixedBy: []string{"mesh-catalog#81"}}); err != nil {
if _, err := c.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@node-b", FixedBy: []string{"mesh-catalog#81"}}); err != nil {
t.Fatal(err)
}
// As kept before this change: no fixing-from.
@@ -170,7 +170,7 @@ func TestAWriteWhoseAppendIsRefusedChangesNothing(t *testing.T) {
if _, err := h.Note(n, "a note the log refuses"); err == nil || !strings.Contains(err.Error(), "log did not take") {
t.Fatalf("a note whose append is refused answers %v", err)
}
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix@g14"}); err == nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix@node-b"}); err == nil {
t.Fatal("a move whose append is refused was answered as made")
}
if got := h.mem.snapshot(IssuesState); fmt.Sprint(got) != fmt.Sprint(bucket) {
@@ -279,7 +279,7 @@ func writeEverything(t *testing.T, h *harness) []uint64 {
if _, err := h.Set(SetAsk{Number: a, Severity: "major", Needs: "decision"}); err != nil {
t.Fatal(err)
}
if _, err := h.Move(MoveAsk{Number: a, Status: StatusFixing, By: "fix@g14", FixedBy: []string{"novox/mesh-catalog#1"}}); err != nil {
if _, err := h.Move(MoveAsk{Number: a, Status: StatusFixing, By: "fix@node-b", FixedBy: []string{"novox/mesh-catalog#1"}}); err != nil {
t.Fatal(err)
}
if _, err := h.Move(MoveAsk{Number: c, Status: StatusWontfix, Reason: "not ours"}); err != nil {
@@ -489,7 +489,7 @@ func TestASearchIsRankedAndTheIndexRebuiltOnStart(t *testing.T) {
t.Fatalf("a note's word: %+v", l.Rows)
}
// Another instance's write reaches this one's index through the watch of the bucket.
if _, err := h.Note(full, "seen again by the operator on shanks"); err != nil {
if _, err := h.Note(full, "seen again by the operator on node-d"); err != nil {
t.Fatal(err)
}
e, _ := h.mem.Get(IssuesState, keyOf(full))
@@ -546,7 +546,7 @@ func TestTheCarryIsIdempotentAndCarriesEveryValueKept(t *testing.T) {
if again.Issues != 0 || again.Values != 0 || again.Already != 2 || h.log.size() != 4 {
t.Fatalf("carried again %+v, %d entries", again, h.log.size())
}
if _, err := h.Move(MoveAsk{Number: 300, Status: StatusDiagnosing, By: "fix@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: 300, Status: StatusDiagnosing, By: "fix@node-b"}); err != nil {
t.Fatal(err)
}
if h.log.size() != 5 || h.log.ops(t, 300)[3].Op != EventMoved {
@@ -258,7 +258,7 @@ func (h *harness) open(t *testing.T, title string, located ...string) uint64 {
// fixing moves an issue to fixing, as the agent that starts its fix does (ADR 0284).
func (h *harness) fixing(t *testing.T, n uint64) {
t.Helper()
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix@node-b"}); err != nil {
t.Fatalf("move %d to fixing: %v", n, err)
}
}
@@ -10,8 +10,8 @@ fixed-by:
## What was observed
ace is adopted and runs `route-adapter` beside the predecessor's traefik (ADR 0104). The first web
module migrated there was searxng. `assign ace searxng` + `push ace` — the step that is supposed to
node-a is adopted and runs `route-adapter` beside the predecessor's traefik (ADR 0104). The first web
module migrated there was searxng. `assign node-a searxng` + `push node-a` — the step that is supposed to
change nothing on an adopted machine (ADR 0100, hq 125: assign holds, take replaces) — took
`searxng.zurag.be` down:
@@ -27,7 +27,7 @@ Assign held everything it found on the machine — the predecessor's `searxng` c
directories — exactly as designed. But the module's **route contribution** is not a resource on the
machine, so nothing held it: it reached `route-adapter` at once, which wrote
`mesh-searxng.zurag.be.yml` into traefik's file provider pointing at the mesh's assigned machine port
(`http://ace.internal:20000`) — where nothing listened, because the container that would was held.
(`http://node-a.internal:20000`) — where nothing listened, because the container that would was held.
traefik's file router for the name then won over the predecessor's docker-label router for the same
name, and the name served a dead backend.
@@ -260,7 +260,7 @@ func TestAnIssueWithAFolderIsNumberedTitledAndPointsAtItsFolder(t *testing.T) {
t.Fatalf("answer %+v", o)
}
// Since the import of slice 3, an issue with a folder is whole in the tracker: its status moves here.
if _, err := h.Move(MoveAsk{Number: 365, Status: StatusDiagnosing, By: "fix-365@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: 365, Status: StatusDiagnosing, By: "fix-365@node-b"}); err != nil {
t.Fatalf("a move of an issue with a folder: %v", err)
}
if _, err := h.Note(365, "notes are taken"); err != nil {
@@ -273,7 +273,7 @@ func TestAnIssueWithAFolderIsNumberedTitledAndPointsAtItsFolder(t *testing.T) {
}
// The cycle's rules at the write (to-be 53 §5, ADR 0284): one case per row, each refused case changing nothing.
// A case starts from open, or, with from, from that status reached first (fixing by fix@g14).
// A case starts from open, or, with from, from that status reached first (fixing by fix@node-b).
func TestTheCyclesRulesHoldAtTheWrite(t *testing.T) {
const fx = StatusFixing
cases := []struct {
@@ -304,19 +304,19 @@ func TestTheCyclesRulesHoldAtTheWrite(t *testing.T) {
{"wontfix without a reason", nil, "", MoveAsk{Status: StatusWontfix}, "without a reason"},
{"wontfix", nil, "", MoveAsk{Status: StatusWontfix, Reason: "the module is retired"}, ""},
{"wontfix from fixing", nil, fx, MoveAsk{Status: StatusWontfix, Reason: "the module is retired"}, ""},
{"a reason on another status", nil, "", MoveAsk{Status: StatusDiagnosing, By: "a@g14", Reason: "x"}, "what wontfix needs"},
{"a reason on another status", nil, "", MoveAsk{Status: StatusDiagnosing, By: "a@node-b", Reason: "x"}, "what wontfix needs"},
{"to the status it has", nil, "", MoveAsk{Status: StatusOpen}, "already open"},
{"diagnosing", nil, "", MoveAsk{Status: StatusDiagnosing, By: "fix-365@g14"}, ""},
{"diagnosing", nil, "", MoveAsk{Status: StatusDiagnosing, By: "fix-365@node-b"}, ""},
{"diagnosing without by", nil, "", MoveAsk{Status: StatusDiagnosing}, "needs by"},
{"fixing", nil, "", MoveAsk{Status: StatusFixing, By: "Jochen@shanks"}, ""},
{"fixing", nil, "", MoveAsk{Status: StatusFixing, By: "Jochen@node-d"}, ""},
{"fixing without by", nil, "", MoveAsk{Status: StatusFixing}, "needs by"},
{"fixing with a by that names no node", nil, "", MoveAsk{Status: StatusFixing, By: "an agent"}, "who@node"},
{"fixing with a by that carries a secret", nil, "", MoveAsk{Status: StatusFixing, By: "sk-ant-api03-abcdefghijklmnopqrstuvwxyz@g14"}, "carries no secret"},
{"by on another status", []string{"hq"}, "", MoveAsk{Status: StatusLocated, By: "a@g14"}, "only diagnosing and fixing"},
{"fixing with a by that carries a secret", nil, "", MoveAsk{Status: StatusFixing, By: "sk-ant-api03-abcdefghijklmnopqrstuvwxyz@node-b"}, "carries no secret"},
{"by on another status", []string{"hq"}, "", MoveAsk{Status: StatusLocated, By: "a@node-b"}, "only diagnosing and fixing"},
{"take-over on another status", []string{"hq"}, "", MoveAsk{Status: StatusLocated, TakeOver: "x"}, "take-over is for"},
{"take-over with nobody to take from", nil, "", MoveAsk{Status: StatusFixing, By: "a@g14", TakeOver: "x"}, "nobody works on"},
{"an amended design that is not one", nil, "", MoveAsk{Status: StatusDiagnosing, By: "a@g14", AmendedDesign: []string{"../etc/passwd"}}, "not a design document"},
{"a take-over reason that carries a secret", nil, StatusDiagnosing, MoveAsk{Status: StatusFixing, By: "b@ace", TakeOver: "the key is sk-ant-api03-abcdefghijklmnopqrstuvwxyz"}, "carries no secret"},
{"take-over with nobody to take from", nil, "", MoveAsk{Status: StatusFixing, By: "a@node-b", TakeOver: "x"}, "nobody works on"},
{"an amended design that is not one", nil, "", MoveAsk{Status: StatusDiagnosing, By: "a@node-b", AmendedDesign: []string{"../etc/passwd"}}, "not a design document"},
{"a take-over reason that carries a secret", nil, StatusDiagnosing, MoveAsk{Status: StatusFixing, By: "b@node-a", TakeOver: "the key is sk-ant-api03-abcdefghijklmnopqrstuvwxyz"}, "carries no secret"},
{"a fixed-by of two lines", []string{"hq"}, fx, MoveAsk{Status: StatusResolved, FixedBy: []string{"a\nb"}}, "one line"},
}
for _, c := range cases {
@@ -330,7 +330,7 @@ func TestTheCyclesRulesHoldAtTheWrite(t *testing.T) {
h.fixing(t, n)
from = StatusFixing
case StatusDiagnosing:
if _, err := h.Move(MoveAsk{Number: n, Status: c.from, By: "fix@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: c.from, By: "fix@node-b"}); err != nil {
t.Fatal(err)
}
from = c.from
@@ -404,7 +404,7 @@ func TestReopeningClearsWhenItClosed(t *testing.T) {
func TestAMoveOfAnIssueThatDoesNotExistIsRefused(t *testing.T) {
h := newHarness(t)
if _, err := h.Move(MoveAsk{Number: 9, Status: StatusDiagnosing, By: "a@g14"}); !errors.Is(err, ErrNoIssue) {
if _, err := h.Move(MoveAsk{Number: 9, Status: StatusDiagnosing, By: "a@node-b"}); !errors.Is(err, ErrNoIssue) {
t.Fatalf("%v", err)
}
if _, err := h.Get(9); err == nil || !strings.Contains(err.Error(), "there is no issue 9") {
@@ -507,7 +507,7 @@ func TestLinksAreTypedAddedOnceAndRemoved(t *testing.T) {
{LinkAsk{Kind: LinkDecision, Target: "275"}, "four-digit"},
{LinkAsk{Kind: LinkDesign, Target: "03-DESIGN/../../etc/passwd"}, "design document"},
{LinkAsk{Kind: LinkCondition, Target: "a key\nwith a line"}, "condition"},
{LinkAsk{Kind: LinkCondition, Target: "machine.ace.token=abcdefgh123.leaked"}, "secret"},
{LinkAsk{Kind: LinkCondition, Target: "machine.node-a.token=abcdefgh123.leaked"}, "secret"},
{LinkAsk{Kind: LinkRelatesTo, Target: keyOf(b), Remove: true}, ""},
{LinkAsk{Kind: LinkRelatesTo, Target: keyOf(b), Remove: true}, "no relates-to link"},
}
@@ -540,7 +540,7 @@ func TestListIsNewestFirstAndNarrows(t *testing.T) {
h.open(t, "the bus drops a message", "mesh-catalog modules/nats")
h.open(t, "a check passes and did nothing", "mesh-controller internal/catalogue")
n := h.open(t, "the console names a ghost")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "a@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "a@node-b"}); err != nil {
t.Fatal(err)
}
l, err := h.List(ListAsk{})
@@ -10,12 +10,12 @@ import (
// Which issues track which conditions (novox/hq issue 400, ADR 0285).
const mountsKey = "module.mounts.shanks.unhealthy"
const mountsKey = "module.mounts.node-d.unhealthy"
func TestTrackingAnswersTheIssuesThatLinkEachCondition(t *testing.T) {
h := newHarness(t)
now := clocked(h)
a := h.open(t, "mounts fail on shanks", "mesh-catalog")
a := h.open(t, "mounts fail on node-d", "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")
@@ -29,7 +29,7 @@ func TestTrackingAnswersTheIssuesThatLinkEachCondition(t *testing.T) {
t.Fatal(err)
}
}
if _, err := h.Move(MoveAsk{Number: b, Status: StatusFixing, By: "fix-386@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: b, Status: StatusFixing, By: "fix-386@node-b"}); err != nil {
t.Fatal(err)
}
if _, err := h.Set(SetAsk{Number: c, Needs: "operator"}); err != nil {
@@ -51,7 +51,7 @@ func TestTrackingAnswersTheIssuesThatLinkEachCondition(t *testing.T) {
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 {
if m[1].Worker != "fix-386@node-b" || 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" {
@@ -59,8 +59,8 @@ func TestTrackingAnswersTheIssuesThatLinkEachCondition(t *testing.T) {
}
// 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." {
only, err := h.Tracking([]string{"machine.node-a.silent"})
if err != nil || len(only.Conditions) != 0 || only.Said != "No issue tracks machine.node-a.silent." {
t.Fatalf("%+v %v", only, err)
}
if _, err := h.Tracking([]string{"a key\nwith a line"}); err == nil {
@@ -22,14 +22,14 @@ func TestAnotherWorkerIsRefusedNamingTheWorker(t *testing.T) {
h := newHarness(t)
now := clocked(h)
n := h.open(t, "the counter skips a number", "hq")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-a@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-a@node-b"}); err != nil {
t.Fatal(err)
}
*now = now.Add(23 * time.Hour)
before, _ := h.mem.Get(IssuesState, keyOf(n))
events := len(h.said())
_, err := h.Move(MoveAsk{Number: n, Status: to, By: "fix-b@ace"})
if err == nil || !strings.Contains(err.Error(), "fix-a@g14") || !strings.Contains(err.Error(), "take-over") {
_, err := h.Move(MoveAsk{Number: n, Status: to, By: "fix-b@node-a"})
if err == nil || !strings.Contains(err.Error(), "fix-a@node-b") || !strings.Contains(err.Error(), "take-over") {
t.Fatalf("want refused naming the worker, got %v", err)
}
after, _ := h.mem.Get(IssuesState, keyOf(n))
@@ -45,17 +45,17 @@ func TestTheWorkerMovesOn(t *testing.T) {
h := newHarness(t)
now := clocked(h)
n := h.open(t, "x", "hq")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-a@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-a@node-b"}); err != nil {
t.Fatal(err)
}
since := *now
*now = now.Add(time.Hour)
m, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "FIX-A@g14"})
m, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "FIX-A@node-b"})
if err != nil {
t.Fatal(err)
}
is, _ := h.Get(n)
if is.Worker.By != "fix-a@g14" || !is.Worker.Since.Equal(since) || !is.Worker.Active.Equal(*now) || m.By != "fix-a@g14" ||
if is.Worker.By != "fix-a@node-b" || !is.Worker.Since.Equal(since) || !is.Worker.Active.Equal(*now) || m.By != "fix-a@node-b" ||
m.Since == nil || !m.Since.Equal(since) || m.TookOverFrom != "" {
t.Fatalf("worker %+v, answer %+v", is.Worker, m)
}
@@ -64,13 +64,13 @@ func TestTheWorkerMovesOn(t *testing.T) {
!strings.Contains(err.Error(), "needs by") {
t.Fatalf("a move to fixing without by: %v", err)
}
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@ace", FixedBy: []string{"hq#1"}}); err == nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@node-a", FixedBy: []string{"hq#1"}}); err == nil {
t.Fatal("another named the fix while the worker was current")
}
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@g14", FixedBy: []string{"hq#1"}}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@node-b", FixedBy: []string{"hq#1"}}); err != nil {
t.Fatal(err)
}
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@g14", TakeOver: "mine"}); err == nil ||
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@node-b", TakeOver: "mine"}); err == nil ||
!strings.Contains(err.Error(), "already") {
t.Fatalf("a take-over of one's own work: %v", err)
}
@@ -81,22 +81,22 @@ func TestATakeOverNeedsAReasonAndIsNoted(t *testing.T) {
h := newHarness(t)
clocked(h)
n := h.open(t, "x", "hq")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@node-b"}); err != nil {
t.Fatal(err)
}
m, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "jochen@shanks", TakeOver: "the operator finishes it by hand"})
m, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "jochen@node-d", TakeOver: "the operator finishes it by hand"})
if err != nil {
t.Fatal(err)
}
is, _ := h.Get(n)
if is.Worker.By != "jochen@shanks" || m.TookOverFrom != "fix-a@g14" || len(is.Notes) != 1 ||
!strings.Contains(is.Notes[0].Text, "from fix-a@g14") || !strings.Contains(is.Notes[0].Text, "the operator finishes it by hand") ||
if is.Worker.By != "jochen@node-d" || m.TookOverFrom != "fix-a@node-b" || len(is.Notes) != 1 ||
!strings.Contains(is.Notes[0].Text, "from fix-a@node-b") || !strings.Contains(is.Notes[0].Text, "the operator finishes it by hand") ||
is.Notes[0].By != Unproven {
t.Fatalf("worker %+v, notes %+v, answer %+v", is.Worker, is.Notes, m)
}
ev := h.said()
last := ev[len(ev)-1]
if last.Event != EventMoved || last.Body["by"] != "jochen@shanks" || last.Body["took-over-from"] != "fix-a@g14" ||
if last.Event != EventMoved || last.Body["by"] != "jochen@node-d" || last.Body["took-over-from"] != "fix-a@node-b" ||
last.Body["take-over"] != "the operator finishes it by hand" || last.Body["caller"] != Unproven {
t.Fatalf("event %+v", last)
}
@@ -108,7 +108,7 @@ func TestAStaleWorkerIsShownAndMayBeTakenOverWithoutAReason(t *testing.T) {
h := newHarness(t)
now := clocked(h)
n := h.open(t, "x", "hq")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@node-b"}); err != nil {
t.Fatal(err)
}
since := *now
@@ -121,32 +121,32 @@ func TestAStaleWorkerIsShownAndMayBeTakenOverWithoutAReason(t *testing.T) {
t.Fatal(err)
}
l, _ := h.List(ListAsk{})
if r := l.Rows[0]; r.Worker != "fix-a@g14" || r.Since == nil || !r.Since.Equal(since) || r.Stale {
if r := l.Rows[0]; r.Worker != "fix-a@node-b" || r.Since == nil || !r.Since.Equal(since) || r.Stale {
t.Fatalf("row %+v: the worker's note keeps the worker current", r)
}
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@ace"}); err == nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@node-a"}); err == nil {
t.Fatal("a current worker was taken over without a reason")
}
*now = now.Add(15 * time.Hour) // 25 h after the worker's note; the tracker's note 15 h ago does not count
l, _ = h.List(ListAsk{})
if r := l.Rows[0]; !r.Stale || r.Worker != "fix-a@g14" {
if r := l.Rows[0]; !r.Stale || r.Worker != "fix-a@node-b" {
t.Fatalf("row %+v: want stale", r)
}
v, _ := h.View(n)
if !v.WorkerStale {
t.Fatalf("get %+v: want worker-stale", v)
}
m, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@ace"})
m, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@node-a"})
if err != nil {
t.Fatalf("a stale worker taken over from without a reason: %v", err)
}
is, _ := h.Get(n)
last := is.Notes[len(is.Notes)-1]
if m.TookOverFrom != "fix-a@g14" || is.Worker.By != "fix-b@ace" || !strings.Contains(last.Text, "stale") {
if m.TookOverFrom != "fix-a@node-b" || is.Worker.By != "fix-b@node-a" || !strings.Contains(last.Text, "stale") {
t.Fatalf("answer %+v, notes %+v", m, is.Notes)
}
l, _ = h.List(ListAsk{})
if r := l.Rows[0]; r.Stale || r.Worker != "fix-b@ace" {
if r := l.Rows[0]; r.Stale || r.Worker != "fix-b@node-a" {
t.Fatalf("row %+v after the take-over", r)
}
}
@@ -157,15 +157,15 @@ func TestTheStaleBoundIsTheSetting(t *testing.T) {
now := clocked(h)
h.settings.WorkerStaleAfter = "1h"
n := h.open(t, "x", "hq")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-a@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-a@node-b"}); err != nil {
t.Fatal(err)
}
*now = now.Add(59 * time.Minute)
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-b@ace"}); err == nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-b@node-a"}); err == nil {
t.Fatal("taken under the bound")
}
*now = now.Add(2 * time.Minute)
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-b@ace"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-b@node-a"}); err != nil {
t.Fatalf("past the bound: %v", err)
}
}
@@ -175,7 +175,7 @@ func TestAMoveOnEndsTheWork(t *testing.T) {
h := newHarness(t)
clocked(h)
n := h.open(t, "x", "hq")
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-a@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusDiagnosing, By: "fix-a@node-b"}); err != nil {
t.Fatal(err)
}
m, err := h.Move(MoveAsk{Number: n, Status: StatusLocated})
@@ -184,11 +184,11 @@ func TestAMoveOnEndsTheWork(t *testing.T) {
}
is, _ := h.Get(n)
ev := h.said()
if is.Worker != nil || m.Released != "fix-a@g14" || ev[len(ev)-1].Body["released"] != "fix-a@g14" || m.By != Unproven {
if is.Worker != nil || m.Released != "fix-a@node-b" || ev[len(ev)-1].Body["released"] != "fix-a@node-b" || m.By != Unproven {
t.Fatalf("worker %+v, answer %+v, event %+v", is.Worker, m, ev[len(ev)-1])
}
// Anyone may start on it now, without a take-over.
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@ace"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@node-a"}); err != nil {
t.Fatal(err)
}
}
@@ -205,7 +205,7 @@ func TestFixingIsNotClosed(t *testing.T) {
n := h.open(t, "x", "hq")
h.fixing(t, n)
l, _ := h.List(ListAsk{Status: StatusFixing})
if len(l.Rows) != 1 || l.Rows[0].Number != n || l.Rows[0].Worker != "fix@g14" {
if len(l.Rows) != 1 || l.Rows[0].Number != n || l.Rows[0].Worker != "fix@node-b" {
t.Fatalf("%+v", l)
}
}
@@ -216,13 +216,13 @@ func TestTheMoveVerbTakesByAndTakeOver(t *testing.T) {
h := newHarness(t)
clocked(h)
n := h.open(t, "x", "hq")
if _, err := h.call(t, "move", map[string]any{"number": n, "status": "fixing", "by": "fix-a@g14"}); err != nil {
if _, err := h.call(t, "move", map[string]any{"number": n, "status": "fixing", "by": "fix-a@node-b"}); err != nil {
t.Fatal(err)
}
if _, err := h.call(t, "move", map[string]any{"number": n, "status": "fixing", "by": "fix-b@ace"}); err == nil {
if _, err := h.call(t, "move", map[string]any{"number": n, "status": "fixing", "by": "fix-b@node-a"}); err == nil {
t.Fatal("taken without a reason over the verb")
}
if _, err := h.call(t, "move", map[string]any{"number": n, "status": "fixing", "by": "fix-b@ace", "take-over": "fix-a's session ended"}); err != nil {
if _, err := h.call(t, "move", map[string]any{"number": n, "status": "fixing", "by": "fix-b@node-a", "take-over": "fix-a's session ended"}); err != nil {
t.Fatal(err)
}
got, err := h.call(t, "get", map[string]any{"number": n})
@@ -230,7 +230,7 @@ func TestTheMoveVerbTakesByAndTakeOver(t *testing.T) {
t.Fatal(err)
}
raw, _ := json.Marshal(got)
if !strings.Contains(string(raw), `"worker":{"by":"fix-b@ace"`) {
if !strings.Contains(string(raw), `"worker":{"by":"fix-b@node-a"`) {
t.Fatalf("get %s", raw)
}
for _, tool := range Tools(h.Tracker) {
@@ -274,7 +274,7 @@ func TestALinkAndASetKeepTheWorkerCurrent(t *testing.T) {
t.Fatal(err)
}
}
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@g14"}); err != nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-a@node-b"}); err != nil {
t.Fatal(err)
}
*now = now.Add(20 * time.Hour)
@@ -291,7 +291,7 @@ func TestALinkAndASetKeepTheWorkerCurrent(t *testing.T) {
t.Fatal(err)
}
*now = now.Add(10 * time.Hour) // 30 h after the start, 10 h after the act
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@ace"}); err == nil {
if _, err := h.Move(MoveAsk{Number: n, Status: StatusFixing, By: "fix-b@node-a"}); err == nil {
t.Fatalf("the %s did not keep the worker current", act)
}
})