Files
mesh-sdk/go/operatorask/operatorask_test.go
T
jschoubben 5fa64be894 Revert the revert of G's mesh-sdk merge (#191): G's sdk stands again over reader release 3
Main reverted G's half merge (#189, reverted by 8afc3eb in #191) and then took the reader release's S1-S5, which
copied G's code. G's form holds where they differ (process_bus.go, seats.go, state.go and their tests); the
release's kept names stay so main's callers keep building: SeatViewPrefix beside SeatReadPrefix, and QueueInvoke's
empty strings on not-ok (with its test TestQueueInvoke). The tree differs from G's head f30dee54 only by those and
the release's two tests (objects cap option, seat states and stream kinds).

Builds: design 47 G (the milestone's sdk part, as at f30dee54)

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 12:49:56 +01:00

61 lines
2.6 KiB
Go

package operatorask
import (
"encoding/json"
"strings"
"testing"
stdio "git.novox.be/novox/mesh-sdk/go"
)
type warrant struct {
Ask string `json:"ask"`
Choice string `json:"choice"`
}
// Design 47 G A-101: one asker finds the seat's holder, publishes, reads the warrant and hears decided.
func TestTheAskerFindsTheHolderPublishesReadsTheWarrantAndHearsDecided(t *testing.T) {
var asked []string
call := func(key string, body any) (json.RawMessage, error) {
asked = append(asked, key)
return json.RawMessage(`{"seats":[{"seat":"other","holders":[{"module":"x"}]},{"seat":"router-seat","holders":[{"module":"holder"}]}]}`), nil
}
var bucket, id, subject string
var published any
var heard func(stdio.Envelope) error
a := &Asker[warrant]{
Module: "me", Contract: Contract{Seat: "router-seat", StateAsks: "asks"},
Call: call,
Record: func(b, i string) (*stdio.StateEntry, error) {
bucket, id = b, i
return &stdio.StateEntry{Value: json.RawMessage(`{"state":"chosen","warrant":{"ask":"a1","choice":"go"}}`)}, nil
},
Publish: func(s string, body any, _ string) error { subject, published = s, body; return nil },
Subscribe: func(_ string, h func(stdio.Envelope) error) error { heard = h; return nil },
AskSubject: func(m string) string { return "ask." + m },
DecidedSubject: func(m string) string { return "decided." + m },
}
if err := a.Ask("a1", "q"); err != nil || subject != "ask.me" || published != "q" {
t.Errorf("Ask published %v on %q: %v", published, subject, err)
}
state, w, err := a.Where("a1")
if err != nil || state != "chosen" || w == nil || w.Choice != "go" || bucket != "holder_asks" || id != "a1" || len(asked) != 1 || asked[0] != "seat:mesh-module-assigner.assignments" {
t.Errorf("Where = %q %+v %v, read %q %q after %v", state, w, err, bucket, id, asked)
}
var got []warrant
if err := a.Hear(func(w warrant) error { got = append(got, w); return nil }); err != nil {
t.Fatal(err)
}
if err := heard(stdio.Envelope{Key: "decided.me", Body: []byte(`{"ask":"a1","choice":"go"}`)}); err != nil || len(got) != 1 || got[0].Ask != "a1" {
t.Errorf("heard %v: %v", got, err)
}
if err := heard(stdio.Envelope{Key: "decided.me", Body: []byte(`nope`)}); err == nil {
t.Errorf("a body that is no warrant was taken")
}
// No holder: nothing is read and the reason is said.
a.Call = func(string, any) (json.RawMessage, error) { return json.RawMessage(`{"seats":[]}`), nil }
if _, _, err := a.Where("a1"); err == nil || !strings.Contains(err.Error(), "no module holds the seat router-seat") {
t.Errorf("with no holder Where answered %v", err)
}
}