Files
mesh-controller/internal/broker/announced_test.go
T
jschoubben 3ae2d6e17c Grant release 6's compositions, wants and backups ahead of its switch (issue 1945)
The switch to release 6 is today's controller's last plan, and the bus runs the user list it composes until the new
controller writes one: so the new controller's writes of each node's compositions and their digests, each new
node-engine's reads of its own compositions and wants and its backup holder's verbs and word, and the assigner's read
of the digests must be granted by this controller already (ADR 0539 clauses 2, 6, 9 and 16; the review's A1).
2026-10-24 18:14:45 +02:00

87 lines
3.4 KiB
Go

package broker
import (
"slices"
"testing"
"git.novox.be/novox/mesh-sdk/go/announce"
)
// D3 (ADR 0495 clause 3, ADR 0513 §3; issue 1790): a reader's `reads` is granted where the owner announced the state
// readable, refused where it announced and did not, and granted as before where the owner announced nothing yet.
func TestAReadIsGrantedFromItsOwnersAnnouncement(t *testing.T) {
announced := map[string]announce.States{
"owner": {Module: "owner", States: []announce.State{{Name: "open", Readable: true}, {Name: "closed"}}},
}
granted, refused := ReadsAnnounced([]string{"owner.open", "owner.closed", "owner.unsaid", "quiet.any"}, announced)
if !slices.Equal(granted, []string{"owner.open", "quiet.any"}) || !slices.Equal(refused, []string{"owner.closed", "owner.unsaid"}) {
t.Fatalf("granted %v, refused %v", granted, refused)
}
r := Records{Announced: announced, Assigned: map[string][]Declared{"one": {{Module: "reader", Reads: granted,
ReadsRefused: refused}}}}
if got := NotAnnounced(r); !slices.Equal(got, []string{"quiet"}) {
t.Fatalf("not yet announced: %v", got)
}
}
// D1 (ADR 0495 clause 2): the controller announces every bucket of its own, and readable exactly the record mirrors (the
// declared packages the pacman module reads among them, ADR 0507 §5), the chain's buckets, the checks running and the
// plans building.
func TestTheControllerAnnouncesWhatItKeeps(t *testing.T) {
s := ControllerAnnouncement("novox")
if _, err := announce.Encode(s); err != nil {
t.Fatal(err)
}
var readable []string
for _, k := range s.States {
if k.Readable {
readable = append(readable, k.Name)
}
}
want := []string{ChainBuilds, MirrorDeclaredConfig, MirrorPredefined, ChainRollouts,
MirrorAssignments, MirrorDeclaredPackages, ControllerGrants, ControllerComposed}
slices.Sort(want)
if !slices.Equal(readable, want) {
t.Fatalf("readable %v, want %v", readable, want)
}
for _, name := range []string{"lease", "calls", "states-announced", "merge-window"} {
if !s.Keeps(name) || s.Readable(name) {
t.Errorf("%s: kept %v, readable %v", name, s.Keeps(name), s.Readable(name))
}
}
perms, err := PermissionsFor(Principal{Kind: KindController})
if err != nil {
t.Fatal(err)
}
if !slices.Contains(perms.Publish, announce.Subject(ControllerSeat)) {
t.Fatal("the controller may not say what it keeps")
}
}
// D2: every account that keeps state may say so on its own subject, a process account included, and no other's.
func TestAnAccountKeepingStateMaySayWhatItKeeps(t *testing.T) {
keeper, err := PermissionsFor(Principal{Kind: KindModule, Node: "one", Module: "keeper", PasswordHash: "x",
State: []string{"things"}})
if err != nil {
t.Fatal(err)
}
if !slices.Contains(keeper.Publish, announce.Subject("keeper")) || slices.Contains(keeper.Publish, announce.Subject("other")) {
t.Fatalf("the keeper's announcement grants: %v", keeper.Publish)
}
process, err := PermissionsFor(Principal{Kind: KindProcess, Node: "one", Module: "keeper", Process: "send",
PasswordHash: "x", State: []string{"sends"}})
if err != nil {
t.Fatal(err)
}
if !slices.Contains(process.Publish, announce.Subject("keeper")) {
t.Fatal("a process keeping state may not say what it keeps")
}
none, err := PermissionsFor(Principal{Kind: KindModule, Node: "one", Module: "stateless", PasswordHash: "x"})
if err != nil {
t.Fatal(err)
}
if slices.Contains(none.Publish, announce.Subject("stateless")) {
t.Fatal("a module keeping nothing may say it keeps something")
}
}