Files
mesh-tools/node-tools/internal/bus/streams_internal_test.go
T
jschoubben 481a83e11c
mesh/delivery-group group feat/47-G-join11 checking: 15 of 17 member(s) ready
mesh/delivery closed: a newer head of the same pull request
mesh/check checking 481a83e11c4f on af8385495688 | novox/mesh-tools#69 in group feat/47-G-join11
Round 2 T2, T3, T4, T5: the tool runner ends G with its merge-base test count; the wait test runs its rows side by side
The tests G added fold into existing ones as subtests (design 47 G §626, A-306: 171 tests down to 154, integration 9
down to 7). TestMeshWaitRefusesLoudlyAndNeverLoops runs its groups of one-second rows as parallel subtests, each
on a runtime of its own, 15 s down to 5 s (A-311: the one-second floor of a wait's timeout stands, no clock is
injected). The go.mod no longer requires meshconditionsclient, which no package loads (T4). Node names in the
lines G adds are role names (T5).

Builds: design 47 G §626, design 34 every-event §19, A-306, A-311; review round 2 findings T2, T3, T4, T5
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 22:24:02 +01:00

72 lines
2.8 KiB
Go

package bus
import (
"strings"
"testing"
"git.novox.be/novox/mesh-sdk/go/buscalls"
)
// novox/hq ADR 0363 §2, §3: an event goes to the stream whose pattern carries it, as the bus matches subjects.
func TestAnEventFallsUnderAStreamsPatternAsTheBusMatchesIt(t *testing.T) {
for _, c := range []struct {
pattern, event string
want bool
}{
{"mail.*.message.added", "mail.home.message.added", true},
{"mail.*.message.added", "mail.home.message.removed", false},
{"mail.*.message.added", "mail.home.work.message.added", false},
{"mail.>", "mail.home.message.added", true},
{"mail.**", "mail.home", true},
{"mail.>", "mail", false},
{"status", "status", true},
{"status", "status.changed", false},
{"", "status", false},
} {
if got := eventMatches(c.pattern, c.event); got != c.want {
t.Errorf("%q under %q: %v, want %v", c.event, c.pattern, got, c.want)
}
}
// Design 47 G §347, §59, §462: a sent object is read by the reference that carried it, from a sender's sent store only; a
// state's objects, and a reference that is none are refused before the bus is asked.
t.Run("SentGetRefusesWhatIsNoSentObjectsReference", func(t *testing.T) {
digest := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
for _, c := range []struct {
name string
req buscalls.ObjectsSentGetRequest
want string
}{
{"no digest", buscalls.ObjectsSentGetRequest{Store: "m_sent-objects", Object: "o", Size: 3}, "named by the reference"},
{"a state's objects", buscalls.ObjectsSentGetRequest{Store: "m_asks-objects", Object: "o", Size: 3, Digest: digest}, "no sent store"},
} {
_, err := (&Conn{}).SentGet(c.req)
if err == nil || !strings.Contains(err.Error(), c.want) {
t.Errorf("%s: got %v, want an error containing %q", c.name, err, c.want)
}
}
})
}
// A membership naming no stream publishes every event on EVENTS, exactly as before (issue 725).
func TestAnEventNoStreamCarriesIsPublishedOnEvents(t *testing.T) {
mail := &Membership{Module: "mail", Streams: []StreamIssued{{Stream: "MAIL", Events: []string{"mail.*.message.added"},
Subject: "mesh.stream.mail.event.{event}"}}}
for _, c := range []struct {
m *Membership
event string
want string
}{
{nil, "mail.home.message.added", "mesh.mod.mail.event.mail.home.message.added"},
{&Membership{Module: "mail"}, "mail.home.message.added", "mesh.mod.mail.event.mail.home.message.added"},
{mail, "mail.home.message.added", "mesh.stream.mail.event.mail.home.message.added"},
{mail, "status", "mesh.mod.mail.event.status"},
} {
if got := eventSubject(c.m, "mail", c.event); got != c.want {
t.Errorf("%s: %s, want %s", c.event, got, c.want)
}
}
if got := keyOf("mesh.stream.mail.event.mail.home.message.added"); got != "mail.mail.home.message.added" {
t.Errorf("a stream's event reaches its consumer as %q, not as on EVENTS", got)
}
}