97 lines
4.4 KiB
Go
97 lines
4.4 KiB
Go
package catalogue
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func passSeat(t *testing.T) {
|
|
t.Helper()
|
|
was := Seats()
|
|
t.Cleanup(func() { UseSeats(was) })
|
|
UseSeats([]Seat{
|
|
{Name: "mesh-broker", Scope: ScopeMesh, Delivers: "mesh-bus", Decision: "test"},
|
|
{Name: "mesh-dns-resolver", Scope: ScopeMesh, Replicated: true, Decision: "test"},
|
|
})
|
|
}
|
|
|
|
func broker(module string) Manifest {
|
|
return Manifest{Module: module, Provides: []Offer{{Name: "mesh-bus", Scope: ScopeMesh}},
|
|
Claims: []Claim{{Name: "mesh-broker", Scope: ScopeMesh}}}
|
|
}
|
|
|
|
// A module that still runs but no longer claims the seat.
|
|
func dropped(module string) Manifest { return Manifest{Module: module} }
|
|
|
|
func recorded(node, module string) []Held {
|
|
return []Held{{Claim: "mesh-broker", Scope: ScopeMesh, Node: node, Module: module}}
|
|
}
|
|
|
|
// novox/hq ADR 0660 "How it is checked", and ADR 0449 §4's original case.
|
|
func TestSeatsToPassOn(t *testing.T) {
|
|
passSeat(t)
|
|
rec := recorded("novox", "old")
|
|
cases := []struct {
|
|
name string
|
|
rec []Held
|
|
as []Assignment
|
|
to string // "node/module" of the one pass, "" for none
|
|
saidW []string
|
|
}{
|
|
{"holder assigned nowhere, one claimant (ADR 0449 §4)", rec,
|
|
[]Assignment{{Node: "novox", Manifest: broker("new")}}, "novox/new", nil},
|
|
{"holder assigned but its manifest dropped the claim", rec,
|
|
[]Assignment{{Node: "novox", Manifest: dropped("old")}, {Node: "novox", Manifest: broker("new")}}, "novox/new", nil},
|
|
{"holder claims but cannot hold the seat", rec,
|
|
[]Assignment{{Node: "novox", Manifest: Manifest{Module: "old", Claims: []Claim{{Name: "mesh-broker", Scope: ScopeMesh}}}},
|
|
{Node: "ace", Manifest: broker("new")}}, "ace/new", nil},
|
|
{"the running build still claims: the holder keeps the seat", rec,
|
|
[]Assignment{{Node: "novox", Manifest: broker("old")}, {Node: "novox", Manifest: broker("new")}}, "", nil},
|
|
{"one of the holder's two nodes still claims it", rec,
|
|
[]Assignment{{Node: "novox", Manifest: dropped("old")}, {Node: "ace", Manifest: broker("old")},
|
|
{Node: "g14", Manifest: broker("new")}}, "", nil},
|
|
{"holder's manifest unread: still assigned", rec,
|
|
[]Assignment{{Node: "novox", Manifest: Manifest{Module: "old"}, Unread: true}, {Node: "novox", Manifest: broker("new")}}, "", nil},
|
|
{"an unread assignment is no claimant", rec,
|
|
[]Assignment{{Node: "novox", Manifest: dropped("old")}, {Node: "ace", Manifest: Manifest{Module: "new"}, Unread: true}}, "", nil},
|
|
{"a claimant whose running manifest does not claim is not counted", rec,
|
|
[]Assignment{{Node: "novox", Manifest: dropped("old")}, {Node: "ace", Manifest: dropped("new")}}, "", nil},
|
|
{"no claimant keeps the record", rec,
|
|
[]Assignment{{Node: "novox", Manifest: dropped("old")}, {Node: "novox", Manifest: dropped("other")}}, "", nil},
|
|
{"holder gone, no claimant keeps the record", rec, nil, "", nil},
|
|
{"one module on two nodes is two claimants: none passed, said", rec,
|
|
[]Assignment{{Node: "novox", Manifest: dropped("old")}, {Node: "ace", Manifest: broker("new")}, {Node: "novox", Manifest: broker("new")}},
|
|
"", []string{"old", "new on ace", "new on novox", "seat mesh-broker --to <node>/<module>"}},
|
|
{"two claimants, holder gone: said", rec,
|
|
[]Assignment{{Node: "novox", Manifest: broker("a")}, {Node: "ace", Manifest: broker("b")}},
|
|
"", []string{"a on novox", "b on ace", "seat mesh-broker --to <node>/<module>"}},
|
|
{"a seat with two holders on record is not read", append(rec[:1:1], Held{Claim: "mesh-broker", Scope: ScopeMesh, Node: "ace", Module: "x"}),
|
|
[]Assignment{{Node: "novox", Manifest: broker("new")}}, "", nil},
|
|
{"a replicated seat is never passed",
|
|
[]Held{{Claim: "mesh-dns-resolver", Scope: ScopeMesh, Node: "novox", Module: "gone"}},
|
|
[]Assignment{{Node: "novox", Manifest: Manifest{Module: "r", Claims: []Claim{{Name: "mesh-dns-resolver", Scope: ScopeMesh}}}}}, "", nil},
|
|
}
|
|
for _, c := range cases {
|
|
t.Run(c.name, func(t *testing.T) {
|
|
passes, said := SeatsToPassOn(c.rec, c.as)
|
|
if c.to == "" && len(passes) != 0 || c.to != "" && len(passes) != 1 {
|
|
t.Fatalf("passes=%+v said=%v", passes, said)
|
|
}
|
|
if c.to != "" {
|
|
p := passes[0]
|
|
if p.Seat.Name != "mesh-broker" || p.From.Module != "old" || p.To.Node+"/"+p.To.Module != c.to {
|
|
t.Fatalf("the pass is %+v", p)
|
|
}
|
|
}
|
|
if (len(c.saidW) == 0) != (len(said) == 0) {
|
|
t.Fatalf("said=%v, want %v", said, c.saidW)
|
|
}
|
|
for _, w := range c.saidW {
|
|
if !strings.Contains(said[0], w) {
|
|
t.Fatalf("the answer does not say %q: %s", w, said[0])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|