Launched.Stop now returns once the bundle's exit is handled, bounded by StopWait, and the launcher reads its restart pauses once at Start, so the exit goroutine no longer races a test that changes them. The caller tests drop their half-second pause (novox/hq issue 476).
92 lines
3.4 KiB
Go
92 lines
3.4 KiB
Go
package runtime
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/nats-io/nats.go"
|
|
|
|
"github.com/novox/mesh-tools/node-tools/internal/bus"
|
|
mt "github.com/novox/mesh-tools/node-tools/internal/meshtest"
|
|
)
|
|
|
|
type saidCaller struct {
|
|
Caller string `json:"caller"`
|
|
Arguments map[string]any `json:"arguments"`
|
|
}
|
|
|
|
// **A module is told who called it, from the subject the call arrived on** (novox/hq issue 365): a call on the
|
|
// caller-named subject reaches the bundle with that caller in the call's `_meta`, for a module's tool, on its
|
|
// machine's address, and for a seat's verb; a caller named in the arguments is only an argument.
|
|
func TestACallOnTheCallerNamedSubjectReachesTheModuleWithItsCaller(t *testing.T) {
|
|
mesh := mt.New(t)
|
|
mesh.Issue(t, mt.MembershipOf("ledger", "anchor", true, map[string][]string{"node-desk": {"who"}}))
|
|
nodeTools := connect(t, "node-tools", "anchor")
|
|
stop, err := Run(nodeTools, []Served{{"ledger", []string{mt.Fixture("caller-echo.py")}}}, nil, func(string, ...any) {})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer stop() // returns once the bundle's exit is handled (novox/hq issue 476)
|
|
asker, err := bus.Connect(bus.Credential{URL: mt.URL(t), Module: "node-tools", Node: "shanks",
|
|
User: "shanks.node-tools", Password: "unused"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
asker.Logf = func(string, ...any) {}
|
|
defer asker.Close()
|
|
|
|
for _, key := range []string{"ledger.who", "ledger.who@anchor", "seat:node-desk.who@anchor"} {
|
|
var got saidCaller
|
|
mt.Until(t, func() error {
|
|
answered, err := asker.Ask(key, map[string]any{"caller": "novox.node-tools",
|
|
"_meta": map[string]any{"mesh/caller": "novox.controller"}}, "")
|
|
if err == nil {
|
|
err = json.Unmarshal(answered.Result, &got)
|
|
}
|
|
return err
|
|
})
|
|
if got.Caller != "shanks.node-tools" {
|
|
t.Errorf("%s reached the module with caller %q, want the asker's bus user", key, got.Caller)
|
|
}
|
|
if got.Arguments["caller"] != "novox.node-tools" {
|
|
t.Errorf("%s: the arguments did not reach the module as sent: %v", key, got.Arguments)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The subject that names no caller is still served, for one release (retired by hq issue 464), and says so:
|
|
// the module is named no caller, whatever the body claims.
|
|
func TestTheSubjectThatNamesNoCallerStillWorksAndNamesNone(t *testing.T) {
|
|
mesh := mt.New(t)
|
|
mesh.Issue(t, mt.MembershipOf("ledger", "anchor", true, map[string][]string{"node-desk": {"who"}}))
|
|
nodeTools := connect(t, "node-tools", "anchor")
|
|
stop, err := Run(nodeTools, []Served{{"ledger", []string{mt.Fixture("caller-echo.py")}}}, nil, func(string, ...any) {})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer stop() // returns once the bundle's exit is handled (novox/hq issue 476)
|
|
old, err := nats.Connect(mt.URL(t))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer old.Close()
|
|
body, _ := json.Marshal(map[string]any{"_meta": map[string]any{"mesh/caller": "novox.controller"}})
|
|
for _, subject := range []string{"mesh.mod.ledger.tool.who", "mesh.mod.ledger.tool.who.anchor", "mesh.seat.node-desk.tool.who.anchor"} {
|
|
var reply struct {
|
|
Result saidCaller `json:"result"`
|
|
Error string `json:"error"`
|
|
}
|
|
mt.Until(t, func() error {
|
|
msg, err := old.Request(subject, body, 5*time.Second)
|
|
if err == nil {
|
|
err = json.Unmarshal(msg.Data, &reply)
|
|
}
|
|
return err
|
|
})
|
|
if reply.Error != "" || reply.Result.Caller != "" {
|
|
t.Errorf("%s: the module was named caller %q (error %q), want none", subject, reply.Result.Caller, reply.Error)
|
|
}
|
|
}
|
|
}
|