103 lines
3.5 KiB
Go
103 lines
3.5 KiB
Go
package link
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"log"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/broker"
|
|
)
|
|
|
|
// The controller hears a merge's announcement from whichever module claims the delivery seat, so the subject is a
|
|
// wildcard and the emitter is read from it (novox/hq ADR 0437 §3, issue 1211).
|
|
|
|
type keptMerges struct {
|
|
emitters []string
|
|
refuse bool
|
|
}
|
|
|
|
func (k *keptMerges) KeepDeliveryMerge(_ context.Context, emitter string, _ []byte) error {
|
|
if k.refuse {
|
|
return ErrNotTheDeliverysWord
|
|
}
|
|
k.emitters = append(k.emitters, emitter)
|
|
return nil
|
|
}
|
|
|
|
func mergeSays(t *testing.T, in *fakeInbound, to *settled, subject string) Control {
|
|
t.Helper()
|
|
m := in.sends(t, to, KindDeliveryMerged, map[string]any{"owner": "novox"}).(*fakeControl)
|
|
m.subject = subject
|
|
return m
|
|
}
|
|
|
|
// 1211/AC1: a merged announcement on the subject of the module claiming the seat is read as the delivery's word and
|
|
// kept, as today's module's is (3: unchanged).
|
|
func TestAMergedAnnouncementIsKeptWhicheverModuleSaidIt(t *testing.T) {
|
|
s, in := serving()
|
|
kept := &keptMerges{}
|
|
if err := s.KeepsDeliveryMerges(kept); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, module := range []string{"mesh-delivery-gate", "mesh-delivery"} { // 1211/AC1, 1211/AC3
|
|
subject := "mesh.mod." + module + ".event.merged"
|
|
if kind, ok := kindOfSubject(subject); !ok || kind != KindDeliveryMerged {
|
|
t.Errorf("%s decodes to %q %v", subject, kind, ok)
|
|
}
|
|
if got, ok := DeliveryMergedEmitter(subject); !ok || got != module {
|
|
t.Errorf("%s: emitter %q %v", subject, got, ok)
|
|
}
|
|
to := &settled{}
|
|
s.act(t.Context(), mergeSays(t, in, to, subject))
|
|
if !to.acked {
|
|
t.Errorf("%s: not taken: %+v", module, to)
|
|
}
|
|
}
|
|
if len(kept.emitters) != 2 || kept.emitters[0] != "mesh-delivery-gate" || kept.emitters[1] != "mesh-delivery" {
|
|
t.Errorf("the keeper was told the emitters %v", kept.emitters)
|
|
}
|
|
for _, subject := range []string{"mesh.mod.a.b.event.merged", "mesh.mod.x.event.merged.more", "mesh.seat.x.event.merged", "mesh.mod..event.merged"} {
|
|
if _, ok := DeliveryMergedEmitter(subject); ok {
|
|
t.Errorf("%s read as a merge announcement", subject)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 1211/AC2: an announcement from a module that claims no delivery seat is not the delivery's word: nothing is kept
|
|
// and the log names the module that said it.
|
|
func TestAMergedAnnouncementFromAModuleNotClaimingTheSeatIsNamedAndNotKept(t *testing.T) {
|
|
s, in := serving()
|
|
var said bytes.Buffer
|
|
s.log = log.New(&said, "", 0)
|
|
if err := s.KeepsDeliveryMerges(&keptMerges{refuse: true}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
to := &settled{}
|
|
s.act(t.Context(), mergeSays(t, in, to, "mesh.mod.gitea.event.merged"))
|
|
if !to.rejected || to.acked || len(in.held) != 0 {
|
|
t.Errorf("settled %+v, held %d", to, len(in.held))
|
|
}
|
|
if !strings.Contains(said.String(), "gitea") {
|
|
t.Errorf("the log does not name the module that said it: %q", said.String())
|
|
}
|
|
}
|
|
|
|
// 1211/AC4: the controller's consumer filter hears merged from any module, on one wildcard subject.
|
|
func TestTheControllerHearsMergedFromAnyModuleOnOneSubject(t *testing.T) {
|
|
if broker.DeliveryMergedSubject != "mesh.mod.*.event.merged" {
|
|
t.Errorf("the subject is %q", broker.DeliveryMergedSubject)
|
|
}
|
|
found := false
|
|
for _, s := range broker.ControllerHears {
|
|
found = found || s == broker.DeliveryMergedSubject
|
|
}
|
|
if !found {
|
|
t.Errorf("the controller hears %v", broker.ControllerHears)
|
|
}
|
|
if got := broker.DeliveryMergedSubjectOf("mesh-delivery-gate"); got != "mesh.mod.mesh-delivery-gate.event.merged" {
|
|
t.Errorf("a module's own subject is %q", got)
|
|
}
|
|
}
|