The three tests of the controller's own module.json (process, claimed seat, addresses), the Dockerfile and Makefile pin test, the build-agent registry test and the manifest-in-use seat test move with their old package, as tests of mesh-sdk's exported API; a moved test is exempt from failing first.
177 lines
6.5 KiB
Go
177 lines
6.5 KiB
Go
//go:build integration
|
|
|
|
package inventory
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// A seat's holder is a row, changed as one act (novox/hq ADR 0131). What these pin is the shape of
|
|
// that row's life: it needs an assignment to point at, it is replaced rather than added to, and it
|
|
// goes when the assignment does — so a seat never points at something that is not running anywhere.
|
|
|
|
func twoBrokersOnTwoNodes(t *testing.T) (*Inventory, context.Context) {
|
|
t.Helper()
|
|
old := catalogue.Manifest{Module: "old-broker", Version: "1",
|
|
Provides: []catalogue.Offer{{Name: "mesh-bus", Scope: catalogue.ScopeMesh}},
|
|
Claims: []catalogue.Claim{{Name: "mesh-broker", Scope: catalogue.ScopeMesh}}}
|
|
new := catalogue.Manifest{Module: "new-broker", Version: "1",
|
|
Provides: []catalogue.Offer{{Name: "mesh-bus", Scope: catalogue.ScopeMesh}},
|
|
Claims: []catalogue.Claim{{Name: "mesh-broker", Scope: catalogue.ScopeMesh}}}
|
|
inv, ctx := aMeshWith(t, old, new)
|
|
// The holding references the seat's row, which `migrate` seeds on a real mesh.
|
|
if _, err := inv.SeedSeats(ctx, catalogue.DefaultSeats()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, n := range []string{"anchor", "laptop"} {
|
|
if _, err := inv.AddNode(ctx, n); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if _, err := inv.Assign(ctx, "anchor", "old-broker"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := inv.Assign(ctx, "laptop", "new-broker"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return inv, ctx
|
|
}
|
|
|
|
func TestAHandoverIsOneRowReplacedNotOneAdded(t *testing.T) {
|
|
inv, ctx := twoBrokersOnTwoNodes(t)
|
|
|
|
if err := inv.HoldSeat(ctx, "mesh-broker", catalogue.ScopeMesh, "anchor", "old-broker"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := inv.HoldSeat(ctx, "mesh-broker", catalogue.ScopeMesh, "laptop", "new-broker"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
held, err := inv.Holdings(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(held) != 1 || held[0].Node != "laptop" || held[0].Module != "new-broker" || held[0].Scope != catalogue.ScopeMesh {
|
|
t.Fatalf("after a handover the seat is not held by exactly the new holder: %+v", held)
|
|
}
|
|
}
|
|
|
|
func TestASeatCannotBeHandedToSomethingNotAssigned(t *testing.T) {
|
|
inv, ctx := twoBrokersOnTwoNodes(t)
|
|
// new-broker is assigned to laptop, not anchor.
|
|
if err := inv.HoldSeat(ctx, "mesh-broker", catalogue.ScopeMesh, "anchor", "new-broker"); err == nil {
|
|
t.Fatal("a seat was handed to a module not assigned where it was named")
|
|
}
|
|
}
|
|
|
|
func TestUnassigningTheHolderTakesTheHoldingWithIt(t *testing.T) {
|
|
inv, ctx := twoBrokersOnTwoNodes(t)
|
|
if err := inv.HoldSeat(ctx, "mesh-broker", catalogue.ScopeMesh, "laptop", "new-broker"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := inv.Unassign(ctx, "laptop", "new-broker"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
held, err := inv.Holdings(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(held) != 0 {
|
|
t.Fatalf("the holding outlived the assignment it pointed at: %+v", held)
|
|
}
|
|
}
|
|
|
|
func TestAMachinesMembershipIsOneRowReplacedAndGoesWithTheMachine(t *testing.T) {
|
|
inv, ctx := twoBrokersOnTwoNodes(t)
|
|
if err := inv.PutBusMembership(ctx, "anchor", "first"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := inv.PutBusMembership(ctx, "anchor", "second"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := inv.BusMemberships(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got["anchor"] != "second" || len(got) != 1 {
|
|
t.Fatalf("a re-told membership did not replace the first: %v", got)
|
|
}
|
|
}
|
|
|
|
// A replicated seat has several holders on record (novox/hq ADR 0223): each is added beside the
|
|
// others, adding one twice changes nothing, a handover still leaves exactly one, and unassigning one
|
|
// takes only its own row.
|
|
func TestAReplicatedSeatHasSeveralHoldersOnRecord(t *testing.T) {
|
|
resolver := catalogue.Manifest{Module: "resolver", Version: "1",
|
|
Provides: []catalogue.Offer{{Name: "wildcard-resolution", Scope: catalogue.ScopeMesh}},
|
|
Claims: []catalogue.Claim{{Name: "mesh-dns-resolver", Scope: catalogue.ScopeMesh}}}
|
|
inv, ctx := aMeshWith(t, resolver)
|
|
if _, err := inv.SeedSeats(ctx, catalogue.DefaultSeats()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, n := range []string{"anchor", "home"} {
|
|
if _, err := inv.AddNode(ctx, n); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := inv.Assign(ctx, n, "resolver"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if err := inv.HoldSeat(ctx, "mesh-dns-resolver", catalogue.ScopeMesh, "anchor", "resolver"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for range 2 {
|
|
if err := inv.AddSeatHolder(ctx, "mesh-dns-resolver", catalogue.ScopeMesh, "home", "resolver"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
held, err := inv.Holdings(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(held) != 2 || held[0].Node != "anchor" || held[1].Node != "home" {
|
|
t.Fatalf("the two holders are not both on record, once each: %+v", held)
|
|
}
|
|
if err := inv.Unassign(ctx, "home", "resolver"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if held, _ = inv.Holdings(ctx); len(held) != 1 || held[0].Node != "anchor" {
|
|
t.Fatalf("unassigning one holder took more or less than its own row: %+v", held)
|
|
}
|
|
if _, err := inv.Assign(ctx, "home", "resolver"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := inv.AddSeatHolder(ctx, "mesh-dns-resolver", catalogue.ScopeMesh, "home", "resolver"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := inv.HoldSeat(ctx, "mesh-dns-resolver", catalogue.ScopeMesh, "home", "resolver"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if held, _ = inv.Holdings(ctx); len(held) != 1 || held[0].Node != "home" {
|
|
t.Fatalf("a handover left other holders on record: %+v", held)
|
|
}
|
|
}
|
|
|
|
// A pass is a compare-and-set: it moves the record only while the holder it was read with is still on it.
|
|
func TestPassingASeatMovesTheRecordOnceAndOnlyFromTheHolderRead(t *testing.T) {
|
|
inv, ctx := twoBrokersOnTwoNodes(t)
|
|
if err := inv.HoldSeat(ctx, "mesh-broker", catalogue.ScopeMesh, "anchor", "old-broker"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
from := catalogue.Held{Claim: "mesh-broker", Scope: catalogue.ScopeMesh, Node: "anchor", Module: "old-broker"}
|
|
to := catalogue.Held{Claim: "mesh-broker", Scope: catalogue.ScopeMesh, Node: "laptop", Module: "new-broker"}
|
|
passed, err := inv.PassSeat(ctx, "mesh-broker", catalogue.ScopeMesh, from, to)
|
|
if err != nil || !passed {
|
|
t.Fatalf("the seat was not passed: %v %v", passed, err)
|
|
}
|
|
held, _ := inv.Holdings(ctx)
|
|
if len(held) != 1 || held[0].Node != "laptop" || held[0].Module != "new-broker" {
|
|
t.Fatalf("the record does not name the new holder alone: %+v", held)
|
|
}
|
|
if passed, err = inv.PassSeat(ctx, "mesh-broker", catalogue.ScopeMesh, from, to); err != nil || passed {
|
|
t.Fatalf("a second pass from the same read moved the record again: %v %v", passed, err)
|
|
}
|
|
}
|