package buscompose import "testing" // Design 47 G §543, §544, §600: a build seat's ask names its asker, each queue has a named worker beside main's, an asker // is granted the queues of its kinds under its own seat's name alone, and main's subject is the checker's and the builder's. func TestNamedAsks(t *testing.T) { build := Seat{Name: "node-build-go", Scope: "node", Accepts: []string{"delivery", "check", "recheck"}, PulledByKind: true, AcceptCallers: map[string][]string{ "delivery": {"mesh-builds"}, "check": {"mesh-pipeline-runner", "mesh-catalog", "mesh-delivery-checker"}, "recheck": {"mesh-delivery-checker"}, }} asker := func(module string, held ...string) Principal { p := Principal{Kind: KindModule, Node: "one", Module: module, Uses: []Seat{build}} for _, h := range held { p.Holds = append(p.Holds, Seat{Name: h}) } return p } const base = "mesh.seat.node-build-go.accept." for _, c := range []struct { who Principal want map[string]bool }{ {asker("runner-module", "mesh-pipeline-runner"), map[string]bool{ base + "check.mesh-pipeline-runner": true, base + "delivery.mesh-pipeline-runner": false, base + "check.mesh-catalog": false, base + "check": false, base + "delivery": false}}, {asker("an-indexer", "mesh-catalog"), map[string]bool{ base + "check.mesh-catalog": true, base + "check.mesh-pipeline-runner": false, base + "recheck.mesh-catalog": false}}, {asker("the-builder", "mesh-builds"), map[string]bool{ base + "delivery.mesh-builds": true, base + "delivery": true, base + "check": true, base + "check.mesh-builds": false}}, {asker("the-checker", "mesh-delivery-checker"), map[string]bool{ base + "check.mesh-delivery-checker": true, base + "recheck.mesh-delivery-checker": true, base + "recheck": true, base + "delivery.mesh-delivery-checker": false}}, {asker("a-stranger"), map[string]bool{base + "check": false, base + "delivery": false, base + "check.a-stranger": false}}, } { perms, err := PermissionsFor(c.who) if err != nil { t.Fatal(err) } for subject, want := range c.want { if got := MayPublish(perms, subject); got != want { t.Errorf("%s may publish %s: %v, want %v", c.who.Module, subject, got, want) } } } // Each queue's workers: main's and the named one, filtered to subjects that overlap nothing. held := Seat{Name: "node-build-go", Scope: "node", Accepts: []string{"delivery", "check"}, PulledByKind: true} tr := SeatTrafficOf("go-module", []Seat{held}, nil, nil) filters := map[string]string{} for _, w := range tr.Workers { filters[w.Consumer] = w.Filter } for consumer, filter := range map[string]string{ "SEAT_NODE_BUILD_GO_CHECK_worker": base + "check", "SEAT_NODE_BUILD_GO_CHECK_named_worker": base + "check.*", "SEAT_NODE_BUILD_GO_DELIVERY_worker": base + "delivery", "SEAT_NODE_BUILD_GO_DELIVERY_named_worker": base + "delivery.*", } { if filters[consumer] != filter { t.Errorf("worker %s filters %q, want %q", consumer, filters[consumer], filter) } } _, consumers := SeatTrafficObjects([]Principal{{Kind: KindModule, Node: "one", Module: "go-module", Holds: []Seat{held}}}) if len(consumers) != 4 { t.Errorf("the work queue's consumers: %d, want 4 (a main and a named worker for each of two queues)", len(consumers)) } } // Design 47 G §610, A-179 (test 60's case of §271): a user of a seat is granted a verb's call subject only where the verb's // effective callers name it, so a kept-artifact call is composed for the module that invokes it and for no other user of // the build seat; `module:` and `seat:` entries name theirs, and a seat whose definition is unread grants its users no verb. func TestAVerbIsGrantedToItsEffectiveCallersAlone(t *testing.T) { build := Seat{Name: "node-build-go", Scope: "node", Serves: []string{"kept-artifact", "freed", "run"}, VerbCallers: map[string][]string{ "kept-artifact": {"invokers", "persons", "sessions"}, "freed": {"module:a-checker"}, "run": {"seat:mesh-pipeline-runner"}, }} user := func(module string, invokes []string, held ...string) Principal { p := Principal{Kind: KindModule, Node: "one", Module: module, Uses: []Seat{build}, Invokes: invokes} for _, h := range held { p.Holds = append(p.Holds, Seat{Name: h}) } return p } unread := build unread.VerbCallers = nil const base = "mesh.seat.node-build-go.tool." for _, c := range []struct { who Principal want map[string]bool }{ {user("an-invoker", []string{"seat:node-build-go.kept-artifact"}), map[string]bool{ base + "kept-artifact.ace": true, base + "freed.ace": false, base + "run.ace": false}}, {user("a-runner", nil, "mesh-pipeline-runner"), map[string]bool{ base + "kept-artifact.ace": false, base + "freed.ace": false, base + "run.ace": true}}, {user("a-checker", nil), map[string]bool{base + "kept-artifact.ace": false, base + "freed.ace": true}}, {Principal{Kind: KindModule, Node: "one", Module: "a-checker", Uses: []Seat{unread}}, map[string]bool{ base + "freed.ace": false, base + "kept-artifact.ace": false}}, } { perms, err := PermissionsFor(c.who) if err != nil { t.Fatal(err) } for subject, want := range c.want { if got := MayPublish(perms, subject); got != want { t.Errorf("%s may publish %s: %v, want %v", c.who.Module, subject, got, want) } } } } // Design 47 G §544: the grants part's account alone is granted the purge of a build seat's stream and the delete of its // named workers, for every queue of a build seat a composed user holds. func TestTheGrantsPartAlonePurgesTheNamedAsks(t *testing.T) { held := Seat{Name: "node-build-go", Scope: "node", Accepts: []string{"check"}, PulledByKind: true} users, err := Users(Records{Nodes: []string{"one"}, Assigned: map[string][]Declared{"one": { {Module: GrantsModule}, {Module: "go-module", Holds: []Seat{held}}}}}) if err != nil { t.Fatal(err) } for _, u := range users { perms, err := PermissionsFor(u) if err != nil { t.Fatal(err) } for _, subject := range []string{"$JS.API.STREAM.PURGE.SEAT_NODE_BUILD_GO", "$JS.API.CONSUMER.DELETE.SEAT_NODE_BUILD_GO.SEAT_NODE_BUILD_GO_CHECK_named_worker"} { if got, want := MayPublish(perms, subject), u.Module == GrantsModule && u.Kind == KindModule; got != want { t.Errorf("%s may publish %s: %v, want %v", u.Username(), subject, got, want) } } if u.Module == GrantsModule && MayPublish(perms, "$JS.API.CONSUMER.DELETE.SEAT_NODE_BUILD_GO.SEAT_NODE_BUILD_GO_CHECK_worker") { t.Errorf("the grants part may delete main's worker") } } }