The lease write asked seat:node-service-manager.stop@novox-be through Conn.Call, which published the '@' inside the subject: nobody served it and the call timed out after 30 s with nothing said (issue 774 notes 84-87). Every key now parses in one place, calladdress: Call routes '@node' as CallOn does, and stdio Ask refuses a key the runtime could not route, before anything is sent. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
57 lines
2.1 KiB
Go
57 lines
2.1 KiB
Go
package calladdress
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Issue 774 notes 84-87 (the lease write's stop asked of `seat:node-service-manager.stop@novox-be` published on a subject
|
|
// nobody serves and timed out after 30 s): a key names its machine after '@', and every other malformed key is refused
|
|
// before anything is published, naming why.
|
|
func TestAKeyIsParsedOrRefusedBeforeItIsPublished(t *testing.T) {
|
|
for _, row := range []struct {
|
|
key, want string // want: "seat|<seat>|<verb>|<node>", "mod|<module>|<tool>|<node>", or a refusal's words
|
|
}{
|
|
{"seat:node-service-manager.stop@novox", "seat|node-service-manager|stop|novox"},
|
|
{"seat:operator-channel.tell", "seat|operator-channel|tell|"},
|
|
{"mesh-build-go.fetch@ace", "mod|mesh-build-go|fetch|ace"},
|
|
{"nats.nats_users", "mod|nats|nats_users|"},
|
|
{"seat:node-service-manager.stop@novox@g14", "more than one '@'"},
|
|
{"seat:node-service-manager.stop@", "not a node name"},
|
|
{"seat:node-service-manager.stop@nov.ox", "not a node name"},
|
|
{"seat:node-files.*", "not one subject token"},
|
|
{"mesh-build-go.fe tch", "not one subject token"},
|
|
{"mesh>build.fetch", "not one subject token"},
|
|
{"seat:noverb", "names no seat and verb"},
|
|
{"nodot", "is not <module>.<tool>"},
|
|
{"", "is not <module>.<tool>"},
|
|
} {
|
|
a, err := Parse(row.key)
|
|
got := ""
|
|
switch {
|
|
case err != nil:
|
|
got = err.Error()
|
|
if !strings.Contains(got, row.want) {
|
|
t.Errorf("Parse(%q) refused %q, want %q", row.key, got, row.want)
|
|
}
|
|
continue
|
|
case a.Seat != "":
|
|
got = "seat|" + a.Seat + "|" + a.Verb + "|" + a.Node
|
|
default:
|
|
got = "mod|" + a.Module + "|" + a.Tool + "|" + a.Node
|
|
}
|
|
if got != row.want {
|
|
t.Errorf("Parse(%q) = %s, want %s", row.key, got, row.want)
|
|
}
|
|
}
|
|
if a, err := Parse("seat:node-files.read@g14"); err != nil || a.Key() != "seat:node-files.read" {
|
|
t.Errorf("the key without its machine: %q, %v", a.Key(), err)
|
|
}
|
|
if err := CheckOwn("list@ace"); err != nil {
|
|
t.Errorf("a module's own tool by its bare name was refused: %v", err)
|
|
}
|
|
if err := CheckOwn("li*st"); err == nil {
|
|
t.Error("a bare name that is not one token was accepted")
|
|
}
|
|
}
|