package inventory import ( "context" "testing" "github.com/novox/mesh-controller/internal/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) } }