package broker import "testing" // The operator-channel seat as the messenger declares it once it takes a module's condition: copied from // mesh-catalog modules/messenger/module.json at 5b235a6e (issue 1217), the seat's accepts, emits and by-caller verbs. func operatorChannelWithCondition() Seat { return Seat{Name: "operator-channel", Scope: "mesh", Accepts: []string{"ask", "cancel", "condition"}, Emits: []string{"decided"}, Serves: []string{"open", "history", "notify", "tell", "asks"}, ByCaller: []string{"ask", "cancel", "condition", "decided"}, Records: []string{"asks"}} } // 1216/AC1: a module that uses the seat may publish its condition under its own name. func TestAModuleUsingTheOperatorChannelMayPublishItsConditionUnderItsOwnName(t *testing.T) { x := perms(t, Principal{Kind: KindModule, Node: "anchor", Module: "web-app", Uses: []Seat{operatorChannelWithCondition()}}) if !allowed(x.Publish, "mesh.seat.operator-channel.accept.condition.web-app") { t.Errorf("web-app may not say a condition as itself: %v", x.Publish) } } // 1216/AC2: it may not publish a condition under another module's name, nor on the wildcard. func TestAModuleMayNotSayAConditionUnderAnotherName(t *testing.T) { x := perms(t, Principal{Kind: KindModule, Node: "anchor", Module: "web-app", Uses: []Seat{operatorChannelWithCondition()}}) for _, subject := range []string{ "mesh.seat.operator-channel.accept.condition.other-app", "mesh.seat.operator-channel.accept.condition.*", "mesh.seat.operator-channel.accept.condition.>", "mesh.seat.operator-channel.accept.condition", } { if allowed(x.Publish, subject) { t.Errorf("web-app may publish %s", subject) } } } // 1216/AC3: the seat's holder may take accept.condition. from the work queue SEAT_OPERATOR_CHANNEL. func TestTheHolderOfTheOperatorChannelTakesEveryModulesCondition(t *testing.T) { seat := operatorChannelWithCondition() holder := perms(t, Principal{Kind: KindModule, Node: "anchor", Module: "messenger", Holds: []Seat{seat}}) if !allowed(holder.Subscribe, "mesh.seat.operator-channel.accept.condition.web-app") || !allowed(holder.Subscribe, "mesh.seat.operator-channel.accept.condition.other-app") { t.Errorf("the holder does not take accept.condition.*: %v", holder.Subscribe) } if !allowed(holder.Publish, "$JS.API.CONSUMER.MSG.NEXT.SEAT_OPERATOR_CHANNEL.SEAT_OPERATOR_CHANNEL_worker") { t.Errorf("the holder may not pull the seat's work queue: %v", holder.Publish) } users, _ := Users(Records{Nodes: []string{"anchor"}, Assigned: map[string][]Declared{"anchor": { {Module: "messenger", Holds: []Seat{seat}}, {Module: "web-app", Uses: []Seat{seat}}, }}}) streams, workers := SeatTrafficObjects(users) kept := false for _, s := range streams { if s.Name == "SEAT_OPERATOR_CHANNEL" { for _, subject := range s.Subjects { kept = kept || subjectMatches(subject, "mesh.seat.operator-channel.accept.condition.web-app") } } } if !kept { t.Error("the work queue SEAT_OPERATOR_CHANNEL does not keep accept.condition.") } taken := false for _, w := range workers { if w.Name == "SEAT_OPERATOR_CHANNEL_worker" { for _, f := range w.Filters { taken = taken || subjectMatches(f, "mesh.seat.operator-channel.accept.condition.web-app") } } } if !taken { t.Error("the seat's worker does not take accept.condition.") } }