A registered replay asked now outranked newer asks of its module, and a plan took any later outcome as its answer. A replay is now refused while the module is asked anywhere, a plan module asked under an id is answered by that id alone, and a rebuild of a commit asks what the module follows. An ask handed back after a restart no longer reads as dead; a cancel that meets a start is withdrawn; pause holds for an ask fetched as it lands; kill removes containers before and after the build ends and says whether its outcome went out; a holder may say only its own machine is paused.
74 lines
3.3 KiB
Go
74 lines
3.3 KiB
Go
package broker
|
|
|
|
import "testing"
|
|
|
|
// A build agent reads its seat's cancelled set by key and nothing more, answers its verbs on its own
|
|
// machine's subjects, and says whether it is paused under its own machine's name; the controller may
|
|
// ask any machine's holder its verbs (novox/hq ADR 0219).
|
|
func TestTheBuildQueueIsControlledWithTheGrantsItNeedsAndNoMore(t *testing.T) {
|
|
seat := Seat{Name: "node-build-agent", Scope: "node", Accepts: []string{"build"},
|
|
Emits: []string{"started", "built", "log.*", "paused.*"},
|
|
Serves: []string{"current", "kill", "pause", "resume"}}
|
|
holder, err := PermissionsFor(Principal{Kind: KindModule, Node: "ace", Module: "build-agent",
|
|
Holds: []Seat{seat}, PasswordHash: "x"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
has(t, holder.Publish, "$JS.API.DIRECT.GET.KV_SEAT_NODE_BUILD_AGENT_cancelled.$KV.SEAT_NODE_BUILD_AGENT_cancelled.>")
|
|
hasNot(t, holder.Publish, "$KV.SEAT_NODE_BUILD_AGENT_cancelled.>")
|
|
has(t, holder.Publish, "mesh.seat.node-build-agent.event.paused.ace")
|
|
hasNot(t, holder.Publish, "mesh.seat.node-build-agent.event.paused.*")
|
|
has(t, holder.Publish, "mesh.seat.node-build-agent.event.log.*")
|
|
has(t, holder.Subscribe, "mesh.seat.node-build-agent.tool.kill.ace")
|
|
hasNot(t, holder.Subscribe, "mesh.seat.node-build-agent.tool.kill.g14")
|
|
|
|
// A module's own seat's queue is its own affair: no cancelled set, no grant for one.
|
|
other, _ := PermissionsFor(Principal{Kind: KindModule, Node: "ace", Module: "telegram",
|
|
Holds: []Seat{{Name: "telegram-sender", Accepts: []string{"send"}}}, PasswordHash: "x"})
|
|
hasNot(t, other.Publish, "$JS.API.DIRECT.GET.KV_SEAT_TELEGRAM_SENDER_cancelled.$KV.SEAT_TELEGRAM_SENDER_cancelled.>")
|
|
|
|
controller, _ := PermissionsFor(Principal{Kind: KindController, PasswordHash: "x"})
|
|
has(t, controller.Publish, "mesh.seat.node-build-agent.tool.>")
|
|
|
|
if CancelledSetName("node-build-agent") != "SEAT_NODE_BUILD_AGENT_cancelled" ||
|
|
!IsCancelledSet("SEAT_NODE_BUILD_AGENT_cancelled") || IsCancelledSet("build-agent_cancelled") {
|
|
t.Error("the cancelled set is not named as its seat's family")
|
|
}
|
|
}
|
|
|
|
// Only the work queues the controller asks get a cancelled set.
|
|
func TestOnlyTheControllersQueuesHaveACancelledSet(t *testing.T) {
|
|
var asserted []string
|
|
a := asserterFunc(func(seat string) error { asserted = append(asserted, seat); return nil })
|
|
if err := RaiseCancelledSets(a, []DeclaredSeat{
|
|
{Name: "node-build-agent", Accepts: []string{"build"}},
|
|
{Name: "telegram-sender", Accepts: []string{"send"}},
|
|
{Name: "mesh-controller"},
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(asserted) != 1 || asserted[0] != "node-build-agent" {
|
|
t.Fatalf("asserted %v", asserted)
|
|
}
|
|
}
|
|
|
|
type asserterFunc func(string) error
|
|
|
|
func (f asserterFunc) EnsureCancelledSet(seat string) error { return f(seat) }
|
|
|
|
// A seat's cancelled set is never reported as state nothing declares.
|
|
func TestACancelledSetIsNotUndeclaredState(t *testing.T) {
|
|
undeclared, err := RaiseBuckets(fakeBuckets{names: []string{"SEAT_NODE_BUILD_AGENT_cancelled", "gone_state"}}, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(undeclared) != 1 || undeclared[0] != "gone_state" {
|
|
t.Fatalf("undeclared %v", undeclared)
|
|
}
|
|
}
|
|
|
|
type fakeBuckets struct{ names []string }
|
|
|
|
func (f fakeBuckets) EnsureBucket(Bucket) error { return nil }
|
|
func (f fakeBuckets) BucketNames() ([]string, error) { return f.names, nil }
|