Files
mesh-sdk/go/catalogue/streams_test.go
T
jschoubben 68aaf235d4 Take the judge out of mesh-sdk: it is mesh-delivery's now (ADR 0578 §4, §7)
Issue 1585, S19: the strict parser, every manifest problem function and the judge's tables (192 declarations,
about 5,200 lines) and their 244 tests leave; composition keeps its own refusals and the helpers it uses. The
catalogue's tests decode the manifests they build. ParseManifest, ParseManifestWith, ParseManifestForInputs,
CatalogueProblems and the rest are gone; mesh-delivery-indexer/judge holds them.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-01 02:36:24 +01:00

155 lines
6.7 KiB
Go

package catalogue
import (
"encoding/json"
"slices"
"testing"
)
// mailManifest is a module owning a restricted stream, as mesh-mail declares it (novox/hq ADR 0363), with
// the trusted mergeable file that takes its grants setting; extra is spliced in at the top.
func mailManifest(t *testing.T, streams, extra string) string {
t.Helper()
return `{"module":"mesh-mail","version":"1",` + extra + `"streams":` + streams + `,` +
`"resources":[{"id":"state","type":"directory","mode":"0700","place":"."},` +
`{"id":"grants","trusted":true,"type":"file","path":"${dir:state}/grants.json","mode":"0600",` +
`"merge":"json","takes-settings":["grants"],"content":"{\"grants\": {}}"}]}`
}
const mailStream = `[{"name":"mail","events":["mail.*.message.added","mail.*.message.changed",` +
`"mail.*.message.removed"],"max-age-days":7,"grant":{"config":"grants","events":"mail.{key}.**"}}]`
// A module declares a stream of its own (ADR 0363 §1): its events with a variable name (§3), its age and
// size with defaults, and a grant by a trusted setting of its own (§4).
func TestAModuleDeclaresAStreamOfItsOwn(t *testing.T) {
m, err := decodeForTest([]byte(mailManifest(t, mailStream, "")))
if err != nil {
t.Fatal(err)
}
if len(m.Streams) != 1 {
t.Fatalf("streams not read: %+v", m.Streams)
}
s := m.Streams[0]
if s.BusName() != "MAIL" || s.Days() != 7 || s.Cap() != StreamDefaultMiB || s.Grant == nil ||
s.Grant.Config != "grants" || s.Grant.Granted("mesh") != "mail.mesh.**" {
t.Fatalf("stream read as %+v", s)
}
if !s.Carries("mail.work.message.added") || s.Carries("mail.work.body") || !s.Carries("mail.*.message.removed") {
t.Fatal("the stream's patterns do not say what it carries")
}
plain, err := decodeForTest([]byte(`{"module":"feed","version":"1","streams":[{"name":"feed-items","events":["item.**"]}]}`))
if err != nil {
t.Fatalf("a stream without a grant was refused: %v", err)
}
if got := plain.Streams[0]; got.BusName() != "FEED_ITEMS" || got.Days() != StreamDefaultDays || got.Grant != nil {
t.Fatalf("defaults read as %+v", got)
}
}
// The setting's value names who hears each key: a module wherever it runs, or on one machine (ADR 0363 §4).
func TestARestrictingSettingNamesAModuleOrAModuleOnAMachine(t *testing.T) {
var value any
if err := json.Unmarshal([]byte(`{"mesh":["reader","person.jochen"],"work":["ace.reader"],"home":["other"],`+
`"Bad.Key":["reader"]}`), &value); err != nil {
t.Fatal(err)
}
if got := GrantedKeys(value, "reader", "ace"); !slices.Equal(got, []string{"mesh", "work"}) {
t.Fatalf("on ace reader is granted %v", got)
}
if got := GrantedKeys(value, "reader", "shanks"); !slices.Equal(got, []string{"mesh"}) {
t.Fatalf("on shanks reader is granted %v", got)
}
if got := GrantedKeys(`{"mesh":["reader"]}`, "reader", "ace"); !slices.Equal(got, []string{"mesh"}) {
t.Fatalf("a value held as its JSON text grants %v", got)
}
if got := GrantedKeys([]any{"reader"}, "reader", "ace"); len(got) != 0 {
t.Fatalf("a value of another shape granted %v", got)
}
}
// A consumer hears a restricted stream only where its consumes asks and the setting grants it, and only
// by naming the emitter (ADR 0363 §5); what a stream carries whole leaves EVENTS.
func TestAConsumerHearsOnlyWhatItAsksAndIsGranted(t *testing.T) {
provider, err := decodeForTest([]byte(mailManifest(t, mailStream, `"emits":["account.added"],`)))
if err != nil {
t.Fatal(err)
}
shelf := map[string]Manifest{"mesh-mail": provider}
var value any
_ = json.Unmarshal([]byte(`{"mesh":["reader"],"work":["shanks.reader"]}`), &value)
values := func(module, setting string) []any {
if module == "mesh-mail" && setting == "grants" {
return []any{value}
}
return nil
}
reader := Manifest{Module: "reader", Consumes: []string{"mesh-mail.mail.**", "mesh-mail.account.added", "billing.paid"}}
parts, touches, onEvents := Hearing(reader, shelf, "ace", values)
if !touches || len(parts) != 1 || parts[0].Stream.BusName() != "MAIL" {
t.Fatalf("heard %+v", parts)
}
want := []string{"mail.mesh.message.added", "mail.mesh.message.changed", "mail.mesh.message.removed"}
if !slices.Equal(parts[0].Patterns, want) {
t.Fatalf("on ace reader hears %v, want %v", parts[0].Patterns, want)
}
if !slices.Equal(onEvents, []string{"mesh-mail.account.added", "billing.paid"}) {
t.Fatalf("left on EVENTS: %v", onEvents)
}
parts, _, _ = Hearing(reader, shelf, "shanks", values)
if len(parts) != 1 || len(parts[0].Patterns) != 6 {
t.Fatalf("on shanks reader hears %+v", parts)
}
narrow := Manifest{Module: "reader", Consumes: []string{"mesh-mail.mail.*.message.added"}}
parts, _, _ = Hearing(narrow, shelf, "ace", values)
if len(parts) != 1 || !slices.Equal(parts[0].Patterns, []string{"mail.mesh.message.added"}) {
t.Fatalf("a narrower consumes heard %+v", parts)
}
stranger := Manifest{Module: "stranger", Consumes: []string{"mesh-mail.mail.**"}}
parts, touches, onEvents = Hearing(stranger, shelf, "ace", values)
if len(parts) != 0 || !touches || len(onEvents) != 0 {
t.Fatalf("a module not granted heard %+v (touches %v, on EVENTS %v)", parts, touches, onEvents)
}
everything := Manifest{Module: "audit", Consumes: []string{"**", "*.mail.**"}}
parts, touches, _ = Hearing(everything, shelf, "ace", values)
if len(parts) != 0 || touches {
t.Fatalf("a wildcard emitter reached a module's stream: %+v", parts)
}
parts, _, _ = Hearing(reader, shelf, "ace", func(string, string) []any { return nil })
if len(parts) != 0 {
t.Fatalf("with no setting reader heard %+v", parts)
}
}
// A stream without a grant is heard by whoever asks, within its patterns.
func TestAnUnrestrictedStreamIsHeardByWhoeverAsks(t *testing.T) {
feed := Manifest{Module: "feed", Streams: []StreamDeclaration{{Name: "items", Events: []string{"item.*.added", "item.*.gone"}}}}
reader := Manifest{Module: "reader", Consumes: []string{"feed.item.**", "feed.item.x.added"}}
parts, touches, onEvents := Hearing(reader, map[string]Manifest{"feed": feed}, "ace", nil)
if !touches || len(onEvents) != 0 || len(parts) != 1 ||
!slices.Equal(parts[0].Patterns, []string{"item.*.added", "item.*.gone"}) {
t.Fatalf("heard %+v, on EVENTS %v", parts, onEvents)
}
}
func TestNarrowingTwoPatterns(t *testing.T) {
for _, c := range []struct{ a, b, want string }{
{"mail.**", "mail.*.message.added", "mail.*.message.added"},
{"mail.*.message.added", "mail.mesh.**", "mail.mesh.message.added"},
{"a.*", "*.b", "a.b"},
{"**", "a.**", "a.**"},
{"a.b", "a.c", ""},
{"a", "a.**", ""},
} {
got, ok := narrow(c.a, c.b)
if (c.want == "") == ok || got != c.want {
t.Errorf("narrow(%s, %s) = %q, %v; want %q", c.a, c.b, got, ok, c.want)
}
}
if got := uncovered([]string{"a.**", "a.b", "a.b", "c"}); !slices.Equal(got, []string{"a.**", "c"}) {
t.Fatalf("uncovered: %v", got)
}
}