90 lines
4.2 KiB
Go
90 lines
4.2 KiB
Go
package inventory
|
|
|
|
import (
|
|
"encoding/json"
|
|
"slices"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
)
|
|
|
|
// A machine's layer wins over the mesh's for the setting that restricts a stream (novox/hq ADR 0363 §5).
|
|
func TestARestrictingSettingIsReadMachineOverMesh(t *testing.T) {
|
|
layers := []catalogue.Layer{
|
|
{From: catalogue.MeshWideLayer, Values: map[string]any{"grants": "mesh", "other": 1}},
|
|
{From: "novox", Values: map[string]any{"grants": "novox"}},
|
|
}
|
|
if v, set := settingValue(layers, "grants"); !set || v != "novox" {
|
|
t.Fatalf("read %v, %v", v, set)
|
|
}
|
|
if _, set := settingValue(layers[:1], "absent"); set {
|
|
t.Fatal("a key no layer sets read as set")
|
|
}
|
|
}
|
|
|
|
// What a consumer hears is composed into the bus's subjects, and what a stream carries leaves EVENTS.
|
|
func TestWhatAModuleHearsIsComposedOntoTheStreamsSubjects(t *testing.T) {
|
|
provider := catalogue.Manifest{Module: "mesh-mail", Streams: []catalogue.StreamDeclaration{{Name: "mail",
|
|
Events: []string{"mail.*.message.added"}, Grant: &catalogue.StreamGrant{Config: "grants", Events: "mail.{key}.**"}}}}
|
|
var value any
|
|
_ = json.Unmarshal([]byte(`{"mesh":["reader"]}`), &value)
|
|
grants := grantValues{"mesh-mail/grants": {value}}
|
|
reader := catalogue.Manifest{Module: "reader"}
|
|
hears, touches, onEvents := hearsOf(reader, map[string]catalogue.Manifest{"mesh-mail": provider}, "ace", grants,
|
|
[]string{"mesh-mail.mail.**", "billing.paid"})
|
|
if !touches || len(hears) != 1 || hears[0].Stream != "MAIL" || !hears[0].Restricted ||
|
|
!slices.Equal(hears[0].Filters, []string{"mesh.stream.mesh-mail.event.mail.mesh.message.added"}) {
|
|
t.Fatalf("heard %+v", hears)
|
|
}
|
|
if !slices.Equal(onEvents, []string{"billing.paid"}) {
|
|
t.Fatalf("left on EVENTS: %v", onEvents)
|
|
}
|
|
if got := streamsOf(provider); len(got) != 1 || got[0].Name != "MAIL" || got[0].MaxAgeDays != 7 || !got[0].Restricted {
|
|
t.Fatalf("the provider's stream: %+v", got)
|
|
}
|
|
}
|
|
|
|
// 1177/AC1: a catalogue stream declaring retention work-queue is carried into the broker's ModuleStream as
|
|
// WorkQueue, with its duplicate window.
|
|
func TestAWorkQueueStreamIsCarriedIntoTheBrokersModuleStream(t *testing.T) {
|
|
sender := catalogue.Manifest{Module: "mesh-mail", Streams: []catalogue.StreamDeclaration{{Name: "mail-sends",
|
|
Events: []string{"mail.send.approved"}, MaxAgeDays: 1, MaxMiB: 64,
|
|
Retention: catalogue.StreamRetentionWorkQueue, MaxDeliveries: 5, Duplicates: 24}}}
|
|
got := streamsOf(sender)
|
|
if len(got) != 1 || got[0].Name != "MAIL_SENDS" || !got[0].WorkQueue || got[0].Duplicates != 24 {
|
|
t.Fatalf("the sender's stream: %+v", got)
|
|
}
|
|
}
|
|
|
|
// 1177/AC3: a catalogue stream with no retention is carried into the broker as not a work queue.
|
|
func TestANonWorkQueueStreamIsCarriedAsNotAWorkQueue(t *testing.T) {
|
|
plain := catalogue.Manifest{Module: "feed", Streams: []catalogue.StreamDeclaration{{Name: "items",
|
|
Events: []string{"item.**"}}}}
|
|
got := streamsOf(plain)
|
|
if len(got) != 1 || got[0].WorkQueue || got[0].Duplicates != 0 {
|
|
t.Fatalf("the plain stream: %+v", got)
|
|
}
|
|
}
|
|
|
|
// 1178/AC1: the process a work-queue stream's bus.queues names is read from the manifest, by its resource
|
|
// id, with the stream's own max-deliveries — what the broker composes the one durable consumer from.
|
|
func TestTheQueueOwnersOfAWorkQueueStreamAreReadFromItsProcess(t *testing.T) {
|
|
sender := catalogue.Manifest{Module: "mesh-mail", Emits: []string{"mail.send.sent", "mail.send.failed"},
|
|
Streams: []catalogue.StreamDeclaration{{Name: "mail-sends", Events: []string{"mail.send.approved"},
|
|
Retention: catalogue.StreamRetentionWorkQueue, MaxDeliveries: 5}},
|
|
Resources: []map[string]any{
|
|
{"id": "account", "type": "user", "name": "mesh-mail-send"},
|
|
{"id": "send", "type": "process", "run": []any{"./mesh-mail", "send"}, "user": "mesh-mail-send",
|
|
"bus": map[string]any{"emits": []any{"mail.send.sent", "mail.send.failed"},
|
|
"queues": []any{"mail-sends"}}},
|
|
}}
|
|
got := queueOwnersOf(sender)
|
|
if len(got) != 1 || got[0].Process != "send" || got[0].Stream != "MAIL_SENDS" || got[0].MaxDeliver != 5 {
|
|
t.Fatalf("the sender's queue owners: %+v", got)
|
|
}
|
|
// And a module with no process declaring bus has none.
|
|
if got := queueOwnersOf(catalogue.Manifest{Module: "feed"}); got != nil {
|
|
t.Fatalf("a module with no process bus has queue owners: %+v", got)
|
|
}
|
|
}
|