Name no node in mesh-issues's fixtures (issue 1838)
This commit is contained in:
@@ -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 := ¬ified{}
|
||||
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 := ¬ified{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 := ¬ified{}
|
||||
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 := ¬ified{}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -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)
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user