mesh/merge-gate head c4176107f287 merged into trunk a3794ea156dd — pass: builds mesh-delivery-gate → novox; no bus step; every machine composes with the ch…
mesh/repo-check head c4176107f287 merged into trunk a3794ea156dd — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivering: 0 machine step(s) passed
127 lines
4.9 KiB
Go
127 lines
4.9 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// novox/hq issue 1786: two merges whose walks the controller folded, before they were cut, into a batch that was
|
|
// still queued (not yet cut into a walk) ended superseded: the batch is no walk that answers a merge, so the follow
|
|
// loop took the walk's taken_over_by off ("the walk that took its own over does not answer it") and the table's
|
|
// supersession then held ("names no walk that took it over"). Delivered by the batch's walk, they showed
|
|
// superseded for good. A batch that took a walk over is waited for; and one already ended so follows its taker.
|
|
|
|
const (
|
|
head1786 = "1786178617861786178617861786178617861786"
|
|
merge1786 = "a1786a1786a1786a1786a1786a1786a1786a17860"
|
|
)
|
|
|
|
// folded1786 is a delivery whose walk was folded into a batch that is still queued.
|
|
func folded1786(t *testing.T) (*world, string) {
|
|
t.Helper()
|
|
w := newWorld(t)
|
|
id := IDOf("novox/app", head1786)
|
|
w.h.PullUpdated(pr("novox/app", 7, head1786, "feat/x", "src/a.go"))
|
|
w.h.Checked(verdict("novox/app", 7, head1786, "pass"))
|
|
w.h.PullMerged(merged("novox/app", 7, head1786, merge1786))
|
|
w.h.WalkMoved(w.ctl.put(aWalk("plan-own", "novox/app", merge1786, true)))
|
|
w.settleAll()
|
|
if s := w.state(id); s != Delivering {
|
|
t.Fatalf("setup: %s, want delivering", s)
|
|
}
|
|
closes := w.now.Add(time.Minute)
|
|
batch := Walk{ID: "plan-batch", Repository: "novox/other", Branch: "main", Commit: "ffff", Created: w.now, State: walkQueued,
|
|
Delivery: &WalkDelivery{Awaits: "mesh-delivery", Batch: &WalkBatch{ClosesAt: &closes},
|
|
Merges: []WalkMerge{{Repository: "novox/app", Commit: merge1786}}}}
|
|
w.h.WalkMoved(w.ctl.put(batch))
|
|
folded := w.ctl.walk("plan-own")
|
|
folded.State = walkSuperseded
|
|
folded.Note = "folded into plan-batch before it was cut"
|
|
folded.Delivery.TakenOverBy = "plan-batch"
|
|
w.h.WalkMoved(w.ctl.put(folded))
|
|
w.settleAll()
|
|
return w, id
|
|
}
|
|
|
|
func cut1786(w *world, state string) {
|
|
b := w.ctl.walk("plan-batch")
|
|
b.State = state
|
|
b.Delivery.Batch = nil
|
|
b.Tiers, b.Modules = [][]string{{"app"}}, map[string]*WalkModule{"app": {}}
|
|
w.h.WalkMoved(w.ctl.put(b))
|
|
w.settleAll()
|
|
}
|
|
|
|
func TestAWalkFoldedIntoAQueuedBatchIsNotSupersededAndFollowsTheBatchWhenItIsCut(t *testing.T) {
|
|
w, id := folded1786(t)
|
|
if d := w.delivery(id); d.State.Final() || d.Walk.TakenOverBy != "plan-batch" {
|
|
t.Fatalf("folded into a queued batch it is %s, taken over by %q; wanted it still following plan-batch", d.State, d.Walk.TakenOverBy)
|
|
}
|
|
cut1786(w, walkBuilding)
|
|
cut1786(w, walkDone)
|
|
if s := w.state(id); s != Delivered {
|
|
t.Fatalf("the batch's walk is done and it is %s; wanted delivered", s)
|
|
}
|
|
}
|
|
|
|
func TestADeliverySupersededWhileItsTakerWasABatchIsHealedWhenTheTakerEndsDone(t *testing.T) {
|
|
w, id := folded1786(t)
|
|
d := w.h.deliveries[id]
|
|
// The state kept by the fault: superseded, its walk record naming the walk that took it over.
|
|
d.State = Superseded
|
|
d.Transitions = append(d.Transitions, Transition{At: w.now, From: Delivering, To: Superseded, Event: EvSuperseded})
|
|
if err := w.h.Store.PutDelivery(d); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cut1786(w, walkBuilding)
|
|
cut1786(w, walkDone)
|
|
w.later(time30s)
|
|
w.settleAll()
|
|
d = w.delivery(id)
|
|
// A final state stays final (ADR 0239 §5): the taker's end is kept as DeliveredBy, as issue 442 and 747 do.
|
|
if d.State != Superseded || d.DeliveredBy == "" || !memberReached(d) || !d.coveredStop() {
|
|
t.Fatalf("superseded by the fault and its taker done, it is %s, delivered by %q, reached %v; wanted superseded, delivered by the taker, reached",
|
|
d.State, d.DeliveredBy, memberReached(d))
|
|
}
|
|
if st, _ := statusOf(d); st != "success" {
|
|
t.Fatalf("its status is %s; wanted success", st)
|
|
}
|
|
}
|
|
|
|
func TestAFinalDeliveryWhoseTakerDoesNotAnswerItIsNeitherHealedNorLoggedEveryPass(t *testing.T) {
|
|
w, id := folded1786(t)
|
|
d := w.h.deliveries[id]
|
|
d.State = Superseded
|
|
d.Transitions = append(d.Transitions, Transition{At: w.now, From: Delivering, To: Superseded, Event: EvSuperseded})
|
|
other := aWalk("plan-batch", "novox/other", "ffff", false)
|
|
other.State = walkDone
|
|
w.h.WalkMoved(w.ctl.put(other))
|
|
w.settleAll()
|
|
before := w.logs()
|
|
w.later(time30s)
|
|
w.settleAll()
|
|
if d := w.delivery(id); d.DeliveredBy != "" || d.State != Superseded {
|
|
t.Fatalf("healed by a walk that does not answer it: %s %q", d.State, d.DeliveredBy)
|
|
}
|
|
if n := strings.Count(w.logs(), "does not answer its merge") - strings.Count(before, "does not answer its merge"); n != 0 {
|
|
t.Fatalf("logged %d times on a pass over a final record", n)
|
|
}
|
|
}
|
|
|
|
func TestASupersededDeliveryWithNoWalkThatTookItOverStaysSuperseded(t *testing.T) {
|
|
w := newWorld(t)
|
|
id := IDOf("novox/app", head1786)
|
|
w.h.PullUpdated(pr("novox/app", 7, head1786, "feat/x", "src/a.go"))
|
|
w.h.PullUpdated(pr("novox/app", 7, "b"+head1786[1:], "feat/x", "src/a.go"))
|
|
w.settleAll()
|
|
if s := w.state(id); s != Superseded {
|
|
t.Fatalf("a head superseded by a newer one is %s", s)
|
|
}
|
|
w.later(time30s)
|
|
w.settleAll()
|
|
if s := w.state(id); s != Superseded {
|
|
t.Fatalf("it moved: %s", s)
|
|
}
|
|
}
|