109 lines
4.4 KiB
Go
109 lines
4.4 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
// An unrelated closed batch is cut into a walk beside an open one, and that walk asks its first tier at once
|
|
// (issue 973, novox/hq ADR 0407 decision 4): a hotfix is never held by an unrelated delivery.
|
|
func TestAnUnrelatedBatchWalksBesideAnOpenWalk(t *testing.T) {
|
|
open := windowed(t)
|
|
asksWithPaths(t)
|
|
ctx := t.Context()
|
|
hear(t, open, repoMerge("one", "c1", t0), t0)
|
|
cutAt(t, open, t0.Add(90*time.Second))
|
|
if ws, _ := walks(t, open); len(ws) != 1 || !ws[0].Open() {
|
|
t.Fatalf("the first walk is not open: %+v", ws)
|
|
}
|
|
heard := t0.Add(100 * time.Second)
|
|
hear(t, open, lone(repoMerge("two", "c2", heard)), heard)
|
|
advanceHeld(ctx, open)
|
|
ws, bs := walks(t, open)
|
|
if len(ws) != 2 || len(bs) != 0 {
|
|
t.Fatalf("%d walk(s) and %d batch(es); want the unrelated batch cut beside the open walk", len(ws), len(bs))
|
|
}
|
|
for _, w := range ws {
|
|
if !w.Open() || w.Waiting() || deferred(w) || !askedAny(w) {
|
|
t.Errorf("%s (%s) is not walking: open %v, deferred %v, asked %v, note %q", w.ID, w.Named(), w.Open(),
|
|
deferred(w), askedAny(w), w.Note)
|
|
}
|
|
}
|
|
}
|
|
|
|
// A closed batch related to an open walk is queued behind it with the reason, while one that shares nothing is
|
|
// cut beside it; the walk that started is never superseded (ADR 0276 decision 4, issue 973).
|
|
func TestARelatedBatchWaitsBehindTheOpenWalk(t *testing.T) {
|
|
open := windowed(t)
|
|
asksWithPaths(t)
|
|
ctx := t.Context()
|
|
hear(t, open, repoMerge("one", "c1", t0), t0)
|
|
cutAt(t, open, t0.Add(90*time.Second))
|
|
first := func() inventory.Plan { ws, _ := walks(t, open); return ws[len(ws)-1] }()
|
|
heard := t0.Add(100 * time.Second)
|
|
hear(t, open, lone(repoMerge("one", "c2", heard)), heard)
|
|
hear(t, open, lone(repoMerge("three", "c3", heard.Add(time.Second))), heard.Add(time.Second))
|
|
ws, bs := walks(t, open)
|
|
if len(ws) != 2 || len(bs) != 1 {
|
|
t.Fatalf("%d walk(s) and %d batch(es); want the unrelated merge walking and the related one queued", len(ws), len(bs))
|
|
}
|
|
b := bs[0]
|
|
words := batchWords(b, heard)
|
|
if b.State != inventory.PlanQueued || b.Delivery.Batch.Behind != first.ID || b.CommitOf("novox/one") != "c2" ||
|
|
!strings.Contains(words, "queued behind "+first.ID) || !strings.Contains(words, "both change novox/one") {
|
|
t.Fatalf("the related batch is %s, behind %q, reading %q", b.State, b.Delivery.Batch.Behind, words)
|
|
}
|
|
if got, _ := open.inventory.PlanByID(ctx, first.ID); !got.Open() {
|
|
t.Fatalf("the started walk was %s by the related merge", got.State)
|
|
}
|
|
first.State = inventory.PlanDone
|
|
if err := open.inventory.SavePlan(ctx, &first); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cutAt(t, open, heard.Add(2*time.Second))
|
|
if _, bs := walks(t, open); len(bs) != 0 {
|
|
t.Fatalf("the queued batch was not cut once the walk it waited for ended: %+v", bs)
|
|
}
|
|
}
|
|
|
|
// A batch on the controller's own path never walks beside another walk, and nothing walks beside it, whatever
|
|
// the two share (issue 973): it replaces the controller, so it goes alone.
|
|
func TestAnOwnPathBatchNeverWalksBeside(t *testing.T) {
|
|
open := windowed(t)
|
|
asksWithPaths(t)
|
|
ctx := t.Context()
|
|
hear(t, open, repoMerge("one", "c1", t0), t0)
|
|
cutAt(t, open, t0.Add(90*time.Second))
|
|
ws, _ := walks(t, open)
|
|
first := ws[0]
|
|
heard := t0.Add(100 * time.Second)
|
|
hear(t, open, lone(repoMerge("mesh-controller", "k1", heard)), heard)
|
|
ws, bs := walks(t, open)
|
|
if len(ws) != 1 || len(bs) != 1 || !bs[0].OwnPath() || bs[0].State != inventory.PlanQueued ||
|
|
bs[0].Delivery.Batch.Behind != first.ID || !strings.Contains(batchWords(bs[0], heard), "own path") {
|
|
t.Fatalf("an own-path batch beside an open walk: %d walk(s), batches %+v", len(ws), bs)
|
|
}
|
|
first.State = inventory.PlanDone
|
|
if err := open.inventory.SavePlan(ctx, &first); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cutAt(t, open, heard.Add(time.Second))
|
|
ws, _ = walks(t, open)
|
|
if len(ws) != 2 || !ws[0].Open() || ws[0].CommitOf("novox/mesh-controller") != "k1" {
|
|
t.Fatalf("the own-path batch was not cut once the walk ended: %+v", ws)
|
|
}
|
|
own := ws[0]
|
|
// Unrelated to the own-path walk by every footprint, a merge still waits for it.
|
|
later := heard.Add(time.Minute)
|
|
hear(t, open, lone(repoMerge("two", "c2", later)), later)
|
|
ws, bs = walks(t, open)
|
|
if len(ws) != 2 || len(bs) != 1 || bs[0].State != inventory.PlanQueued || bs[0].Delivery.Batch.Behind != own.ID {
|
|
t.Fatalf("a merge beside the own-path walk: %d walk(s), batches %+v", len(ws), bs)
|
|
}
|
|
}
|