Files
mesh-delivery/modules/mesh-grants/internal/buscompose/orderedread_test.go
T
jschoubben 019a7ab9f7 A-233 (grants): a hearer of a seat's kept event is granted the ordered consumer of its whole read
As STREAM.INFO is, for every heard SEAT_ stream whatever its keep, so a part hearing an event kept by age
reads it whole from its first message at each start (mesh-sdk process.FromFirst); no manifest word.

Builds: design 47 G A-233, A-189

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 06:21:30 +01:00

50 lines
2.6 KiB
Go

package buscompose
import (
"slices"
"testing"
)
// A reader of a stream kept last per subject is granted what an ordered consumer of that stream uses, and a reader of
// another stream only its own durable (design 47 G §556, A-4).
func TestAReaderOfAStreamKeptLastPerSubjectIsGrantedItsOrderedConsumer(t *testing.T) {
p := Principal{Module: "m", Node: "a"}
ordered := []string{"$JS.API.CONSUMER.CREATE.S", "$JS.API.CONSUMER.MSG.NEXT.S.*", "$JS.API.CONSUMER.INFO.S.*", "$JS.API.CONSUMER.DELETE.S.*"}
last := heardGrants(p, []Heard{{Stream: "S", Filters: []string{"f"}, LastPerSubject: true}})
for _, w := range ordered {
if !slices.Contains(last, w) {
t.Errorf("a last-per-subject reader is not granted %s: %v", w, last)
}
}
plain := heardGrants(p, []Heard{{Stream: "S", Filters: []string{"f"}}})
if slices.Contains(plain, ordered[0]) {
t.Errorf("a reader of another stream is granted an ordered consumer: %v", plain)
}
// A seat's kept event kept by age is read whole from its first message (process.FromFirst, A-233): its ordered consumer too.
byAge := heardGrants(p, []Heard{{Stream: "SEAT_mesh-catalog_version-released", Filters: []string{"f"}}})
for _, w := range []string{"$JS.API.CONSUMER.CREATE.SEAT_mesh-catalog_version-released", "$JS.API.CONSUMER.MSG.NEXT.SEAT_mesh-catalog_version-released.*",
"$JS.API.CONSUMER.INFO.SEAT_mesh-catalog_version-released.*", "$JS.API.CONSUMER.DELETE.SEAT_mesh-catalog_version-released.*"} {
if !slices.Contains(byAge, w) {
t.Errorf("a reader of a seat's event kept by age is not granted %s: %v", w, byAge)
}
}
}
// A reader of a seat's kept event is granted the info of that stream, which process.HearSeatEvents reads to see whether the
// stream is kept last per subject, and no stream's info besides (design 47 G §641, A-19).
func TestAReaderOfASeatsKeptEventIsGrantedItsStreamInfo(t *testing.T) {
p := Principal{Module: "m", Node: "a"}
kept := heardGrants(p, []Heard{{Stream: "SEAT_mesh-delivery_owed", Filters: []string{"f"}}})
if !slices.Contains(kept, "$JS.API.STREAM.INFO.SEAT_mesh-delivery_owed") {
t.Errorf("a reader of a seat's kept event is not granted its stream's info: %v", kept)
}
own := heardGrants(p, []Heard{{Stream: "BUILDER_BUILDS", Filters: []string{"f"}, LastPerSubject: true}})
if !slices.Contains(own, "$JS.API.STREAM.INFO.BUILDER_BUILDS") {
t.Errorf("a reader of a module's stream kept last per subject is not granted its info: %v", own)
}
other := heardGrants(p, []Heard{{Stream: "mesh-x-events", Filters: []string{"f"}}})
if slices.Contains(other, "$JS.API.STREAM.INFO.mesh-x-events") {
t.Errorf("a reader of a module's stream is granted its info: %v", other)
}
}