mesh/repo-check head d6db334840a5 merged into trunk 98155e327b6d beside mesh-host#129@09c77d57 — pass: its merge-check.sh passed
mesh/merge-gate head d6db334840a5 merged into trunk 98155e327b6d — pass: group fix/1732-held-moves-asked composed: every machine composes with the change a…
mesh/delivery delivered
mesh/delivery-group group fix/1732-held-moves-asked delivered: every member is delivered
93 lines
3.9 KiB
Go
93 lines
3.9 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
func inventoryUpgrade(why string) inventory.Upgrade { return inventory.Upgrade{Why: why, By: "jochen"} }
|
|
|
|
func mustMoveFacts(t *testing.T, rm *recordedMesh) moveFacts {
|
|
t.Helper()
|
|
f, err := readMoveFacts(t.Context(), rm.open.inventory)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return f
|
|
}
|
|
|
|
// 1732/AC8 (integration): a mesh running mailu at c1 on two machines, whose registered c2 recreates a container, is read
|
|
// as two machines each holding mailu's move for a person; a bundle-only c3 on top changes nothing of it; after a machine
|
|
// is sent c2 (as a push records it) it is no longer among them, and plans that carried c2 say nothing more of it.
|
|
func TestMachinesHoldingAMoveForAPersonAreReadFromTheRecords(t *testing.T) {
|
|
rm := aRecordedMesh(t, aMailu(true))
|
|
c2 := aMailu(true)
|
|
resourceOf(&c2, "imap")["image"] = "registry.invalid/imap@sha256:2"
|
|
rm.register(t, c2, "c2", time.Now().Add(-time.Minute))
|
|
ctx := t.Context()
|
|
held, err := gatherHeldMoves(ctx, rm.open.inventory)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(held) != 2 || held[0].node != "anchor" || held[1].node != "laptop" || len(held[0].moves) != 1 ||
|
|
held[0].moves[0].Module != "mailu" || held[0].moves[0].To != "c2" || !strings.Contains(held[0].moves[0].Why, "recreates") {
|
|
t.Fatalf("held %+v", held)
|
|
}
|
|
if err := rm.open.inventory.RecordSent(ctx, nodeID(t, rm.open, "anchor"), "d-anchor-c2", map[string]string{"mailu": "c2"}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
held, err = gatherHeldMoves(ctx, rm.open.inventory)
|
|
if err != nil || len(held) != 1 || held[0].node != "laptop" {
|
|
t.Fatalf("after anchor was sent c2: %+v (%v)", held, err)
|
|
}
|
|
}
|
|
|
|
// 1732/AC9 (integration): a module a person set to record is no ask: they chose the hold.
|
|
func TestAHoldAPersonChoseIsNotAsked(t *testing.T) {
|
|
rm := aRecordedMesh(t, aMailu(false))
|
|
c2 := aMailu(false)
|
|
c2.Bundles[0].Digest = "sha256:bbb"
|
|
rm.register(t, c2, "c2", time.Now().Add(-time.Minute))
|
|
if err := rm.open.inventory.SetUpgradeOf(t.Context(), "mailu", inventoryUpgrade("the migration week")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
held, err := gatherHeldMoves(t.Context(), rm.open.inventory)
|
|
if err != nil || len(held) != 0 {
|
|
t.Fatalf("a machine holding only a person's own hold is asked: %+v (%v)", held, err)
|
|
}
|
|
if moves, _ := heldMovesOn(t.Context(), rm.open.inventory, mustMoveFacts(t, rm), "anchor"); len(moves) != 1 || !moves[0].Chosen {
|
|
t.Fatalf("status still names it, marked as chosen: %+v", moves)
|
|
}
|
|
}
|
|
|
|
// 1742/AC4 (integration): a registered build naming an image of the store that the store lacks is read as a missing
|
|
// image on each machine that runs the module; one the store holds is not; and what the store holds is not asked twice.
|
|
func TestARegisteredBuildNamingAnImageTheStoreLacksIsRead(t *testing.T) {
|
|
m := aMailu(true)
|
|
resourceOf(&m, "imap")["image"] = "artifact-store://mailu/imap@sha256:" + strings.Repeat("e", 64)
|
|
rm := aRecordedMesh(t, m)
|
|
asked := 0
|
|
lacking := func(_ context.Context, reference string) (bool, error) { asked++; return false, nil }
|
|
imagesHeld.Lock()
|
|
imagesHeld.held = map[string]bool{}
|
|
imagesHeld.Unlock()
|
|
got, err := gatherMissingImages(t.Context(), rm.open.inventory, lacking)
|
|
if err != nil || len(got) != 2 || got[0].Module != "mailu" || got[0].Node != "anchor" || got[1].Node != "laptop" {
|
|
t.Fatalf("missing %+v (%v)", got, err)
|
|
}
|
|
holding := func(_ context.Context, reference string) (bool, error) { asked++; return true, nil }
|
|
if got, err := gatherMissingImages(t.Context(), rm.open.inventory, holding); err != nil || len(got) != 0 {
|
|
t.Fatalf("an image the store holds is missing: %+v (%v)", got, err)
|
|
}
|
|
before := asked
|
|
if _, err := gatherMissingImages(t.Context(), rm.open.inventory, lacking); err != nil || asked != before {
|
|
t.Fatalf("an image the store was found to hold was asked about again (%d, %v)", asked-before, err)
|
|
}
|
|
}
|