list, show and orphans answer meshbroker.ListAnswer, Held and OrphansAnswer; check answers CheckAnswer with each differing entry's settings asked and held by stream and whether the difference only grows; show takes the contract's local-name. Built against mesh-contracts' seats/meshbroker module in the workspace; the group pin adds its require. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
90 lines
4.1 KiB
Go
90 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
|
|
"nats-tools/internal/keeper"
|
|
)
|
|
|
|
// The seat's reading verbs and nats_history (design 25 § 12.3; CAT-N7): list and show answer every entry the keeper
|
|
// made with its settings asked and held and its fill against its cap; check names what is missing or differs; orphans
|
|
// what no manifest asks for; history one entry's events in order. Each from the keeper's own state and the bus's
|
|
// monitoring endpoint.
|
|
func TestTheSeatsReadingVerbsAnswerFromTheKeeperAndTheBus(t *testing.T) {
|
|
plan := func(local, storage, template string, options string) keeper.Plan {
|
|
e := catalogue.BusStateEntry{Name: local, Storage: storage, Template: template}
|
|
if options != "" {
|
|
_ = json.Unmarshal([]byte(options), &e.Options)
|
|
}
|
|
p, err := keeper.PlanOf("m", e)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return p
|
|
}
|
|
held := map[string]keeper.Asked{"m": {Module: "m", Made: map[string]keeper.Made{
|
|
"drafts": {Plan: plan("drafts", "key-value", "state", ""), Created: true},
|
|
"log": {Plan: plan("log", "stream", "log", `{"max-mib":16}`), Created: true, Drift: "m_log: max-bytes asked 16777216, held 33554432"},
|
|
"old": {Plan: plan("old", "stream", "events", ""), Created: true, Orphaned: true},
|
|
}}}
|
|
jsz := `{"account_details":[{"stream_detail":[
|
|
{"name":"KV_m_drafts","config":{"name":"KV_m_drafts","retention":"limits","discard":"new","max_bytes":67108864,"max_msgs_per_subject":1,"max_msg_size":262144},"state":{"messages":3,"bytes":1048576}},
|
|
{"name":"m_log","config":{"name":"m_log","retention":"limits","discard":"new","max_bytes":33554432,"max_msg_size":262144},"state":{"messages":9,"bytes":9000}}]}]}`
|
|
tools := map[string]stdio.Tool{}
|
|
for _, tl := range brokerTools(func() (map[string]keeper.Asked, error) { return held, nil },
|
|
func() ([]byte, error) { return []byte(jsz), nil },
|
|
func(module, local string, limit int) ([]keeper.Event, error) {
|
|
return []keeper.Event{{Module: module, Local: local, Why: "first"}, {Module: module, Local: local, Why: "second"}}[:limit], nil
|
|
}) {
|
|
tools[tl.Name] = tl
|
|
}
|
|
for _, row := range []struct {
|
|
tool string
|
|
args map[string]any
|
|
want []string
|
|
err string
|
|
}{
|
|
// Each answers the seat's contract (mesh-contracts meshbroker ListAnswer, Held, CheckAnswer, OrphansAnswer).
|
|
{"mesh-broker.list", nil, []string{`{"entries":[`, `"bus-name":"m_drafts"`, `"local-name":"drafts"`, `"storage-type":"key-value"`,
|
|
`"KV_m_drafts":{"max-bytes":67108864`, `"fill":{"bytes":1048576,"cap":67108864,"count":3}`, `"options":{"max-mib":16}`}, ""},
|
|
{"mesh-broker.show", map[string]any{"module": "m", "local-name": "log"}, []string{`"bus-name":"m_log"`, `"template":"log"`,
|
|
`"m_log":{"max-bytes":33554432`}, ""},
|
|
{"mesh-broker.show", map[string]any{"module": "m", "local-name": "none"}, nil, `made no entry "none" of "m"`},
|
|
{"mesh-broker.check", nil, []string{`{"differences":[{`, `"local-name":"log"`, `"asked":{"m_log":{"max-bytes":16777216`,
|
|
`"held":{"m_log":{"max-bytes":33554432`}, ""},
|
|
{"mesh-broker.check", map[string]any{"module": "x"}, []string{`{"differences":[]}`}, ""},
|
|
{"mesh-broker.orphans", nil, []string{`{"entries":[{`, `"local-name":"old"`}, ""},
|
|
{"nats_history", map[string]any{"module": "m", "local": "log", "limit": float64(1)}, []string{`"why":"first"`}, ""},
|
|
{"nats_history", map[string]any{"module": "m"}, nil, "names one entry"},
|
|
} {
|
|
t.Run(fmt.Sprintf("%s %v", row.tool, row.args), func(t *testing.T) {
|
|
args := row.args
|
|
if args == nil {
|
|
args = map[string]any{}
|
|
}
|
|
out, err := tools[row.tool].Run(args)
|
|
if row.err != "" {
|
|
if err == nil || !strings.Contains(err.Error(), row.err) {
|
|
t.Fatalf("answered %v (%v): refused, naming %q", out, err, row.err)
|
|
}
|
|
return
|
|
}
|
|
raw, _ := json.Marshal(out)
|
|
for _, w := range row.want {
|
|
if !strings.Contains(string(raw), w) {
|
|
t.Errorf("%s lacks %s", raw, w)
|
|
}
|
|
}
|
|
if row.tool == "mesh-broker.check" && strings.Contains(string(raw), `"local-name":"drafts"`) {
|
|
t.Errorf("check names drafts, which the bus holds as asked: %s", raw)
|
|
}
|
|
})
|
|
}
|
|
}
|