package broker import ( "slices" "strings" "testing" ) // The writers table, checked (novox/hq to-be 45 §1, ADR 0227 rule 1, "how it is checked"): it is the // design's table row for row; every row that writes on the bus names its writer; a whole mesh composes // with one writer per piece of state; and a grant that would make a second writer is refused, naming // the state and whose it is. // designRows are the states of to-be 45 §1, in its order. A row added to the design is added here and // to the table; one dropped from either fails. var designRows = []string{ "a machine's declaration", "a machine's applied state and its report", "the controller lease", "plans and their tiers", "conditions", "calls and their outcomes", "the hand-act log", "the healers' acts and their brake", "stream definitions and bus permissions", "builds and their outcomes", "a merge announced", "a provider's standing", "the operator-channel's open messages", "the facts snapshot", } func TestTheWritersTableIsTheDesigns(t *testing.T) { var states []string for _, row := range WritersTable { states = append(states, row.State) if row.Writer == "" || row.KeptIn == "" || row.Others == "" { t.Errorf("%q does not say who writes it, where it is kept and what others do", row.State) } if len(row.Subjects) > 0 && row.Writes == nil { t.Errorf("%q is written on the bus and names no writer among the principals", row.State) } } if !slices.Equal(states, designRows) { t.Fatalf("the writers table is not to-be 45 §1's:\n have %q\n want %q", states, designRows) } } // A mesh of every kind of principal composes: nobody is granted a second writer's subject. func TestAWholeMeshComposesWithOneWriterPerState(t *testing.T) { builder := Seat{Name: "node-build-agent", Scope: "node", Accepts: []string{"build"}, Emits: []string{"built", "started"}} principals := []Principal{ {Kind: KindController, PasswordHash: "x"}, {Kind: KindNode, Node: "one", PasswordHash: "x"}, {Kind: KindEnrolment, Node: "two", PasswordHash: "x"}, {Kind: KindPerson, Module: "jochen", Invokes: []string{"*"}, PasswordHash: "x"}, {Kind: KindModule, Node: "one", Module: "gitea", Emits: []string{"pull.merged"}, PasswordHash: "x"}, {Kind: KindModule, Node: "one", Module: "postgres", Emits: []string{"provisioner.failing", "provisioner.recovered"}, PasswordHash: "x"}, {Kind: KindModule, Node: "one", Module: "build-agent", Holds: []Seat{builder}, PasswordHash: "x"}, {Kind: KindNodeTools, Node: "one", Module: RuntimeModule, PasswordHash: "x", Carries: []Declared{ {Module: "gitea", Emits: []string{"pull.merged"}}, {Module: "build-agent", Holds: []Seat{builder}}}}, } for _, p := range principals { if _, err := PermissionsFor(p); err != nil { t.Errorf("%s does not compose: %v", p.Username(), err) } } if _, err := ComposeAccounts(principals); err != nil { t.Fatalf("the mesh does not compose: %v", err) } } func TestASecondWriterIsRefusedAtComposition(t *testing.T) { for _, c := range []struct { name string p Principal publish []string state string }{ {"the controller publishing what machines say", Principal{Kind: KindController}, []string{"mesh.control.>"}, "a machine's applied state and its report"}, {"a machine publishing another's report", Principal{Kind: KindNode, Node: "one"}, []string{"mesh.control.two.report"}, "a machine's applied state and its report"}, {"a machine publishing every machine's", Principal{Kind: KindNode, Node: "one"}, []string{"mesh.control.*.>"}, "a machine's applied state and its report"}, {"a module writing the lease", Principal{Kind: KindModule, Module: "shop"}, []string{"$KV.mesh-controller_lease.>"}, "the controller lease"}, {"a module sending a declaration", Principal{Kind: KindModule, Module: "shop"}, []string{"mesh.node.one.declare"}, "a machine's declaration"}, {"a module defining a stream", Principal{Kind: KindModule, Module: "shop"}, []string{"$JS.API.>"}, "stream definitions and bus permissions"}, {"a module announcing another forge's merge", Principal{Kind: KindModule, Module: "shop"}, []string{"mesh.mod.gitea.event.pull.merged"}, "a merge announced"}, {"a module saying a build it did not do", Principal{Kind: KindModule, Module: "shop"}, []string{"mesh.seat.node-build-agent.event.built"}, "builds and their outcomes"}, } { t.Run(c.name, func(t *testing.T) { err := CheckWriters(c.p, c.publish) if err == nil { t.Fatalf("%v granted to %s was not refused", c.publish, c.p.Username()) } if !strings.Contains(err.Error(), c.state) { t.Fatalf("the refusal does not name %q: %v", c.state, err) } }) } // And the writers themselves are not refused. for _, ok := range []struct { p Principal publish []string }{ {Principal{Kind: KindNode, Node: "one"}, []string{"mesh.control.one.>"}}, {Principal{Kind: KindController}, []string{"mesh.node.>", "$JS.API.>", "$KV.mesh-controller_lease.>"}}, {Principal{Kind: KindModule, Module: "gitea"}, []string{"mesh.mod.gitea.event.pull.merged"}}, {Principal{Kind: KindModule, Module: "shop"}, []string{"$JS.API.CONSUMER.CREATE.KV_shop_carts.>"}}, } { if err := CheckWriters(ok.p, ok.publish); err != nil { t.Errorf("a writer was refused its own: %v", err) } } } func TestSubjectsOverlap(t *testing.T) { for _, c := range []struct { a, b string want bool }{ {"mesh.control.>", "mesh.control.*.report", true}, {"mesh.control.one.>", "mesh.control.*.report", true}, {"mesh.control.one.alive", "mesh.control.*.report", false}, {"mesh.control.*", "mesh.control.*.report", false}, {"$JS.API.>", "$JS.API.STREAM.CREATE.>", true}, {"$JS.API.CONSUMER.CREATE.KV_x.>", "$JS.API.STREAM.CREATE.>", false}, {"a.b", "a.b", true}, {"a.b", "a.b.c", false}, {"a.>", "a", false}, } { if got := SubjectsOverlap(c.a, c.b); got != c.want || SubjectsOverlap(c.b, c.a) != c.want { t.Errorf("%s ~ %s: %v, want %v", c.a, c.b, got, c.want) } } }