Reach a seat and a module of one name each: list the seat's verbs, and route a machine's address to the module
mesh/merge-gate pass: builds mesh-tools, node-tools → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (0 of …
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

mesh-delivery is the delivery's seat and the module holding it, which answers the seat's verbs with
tools of the same names. Discovery keyed the seat's verbs and the module's tools in one namespace, so
the module's tool took the key and the seat was listed with no verb; and every address with the name
resolved to the seat, so neither the seat's verbs nor the module's tools could be called. The keys are
apart, and `<node>/<module>.<tool>` reaches the module when the module serves it (novox/hq issue 284).
This commit is contained in:
jochen
2026-10-07 01:37:46 +02:00
parent 01c98db0a4
commit dac4d423a8
3 changed files with 181 additions and 91 deletions
@@ -0,0 +1,57 @@
package console
import (
"strings"
"testing"
"github.com/novox/mesh-tools/node-tools/internal/announce"
)
// **Issue 284**: mesh-delivery is the delivery's seat, held once for the mesh, and the module holding it,
// which answers the seat's verbs with tools of the same names and has tools of its own. Discovery put the
// module's tool and the seat's verb under one key, so the seat was listed with no verb; and every address
// with the name resolved to the seat — `mesh-delivery.deliveries` and `novox/mesh-delivery.delivery_status`
// alike were refused, the seat's verbs and the module's tools both out of reach.
func TestASeatAndAModuleOfOneNameAreEachReached(t *testing.T) {
var endpoints []announce.Endpoint
for _, tool := range []string{"deliveries", "delivery_status"} {
endpoints = append(endpoints, announce.Endpoint{Kind: announce.KindTool, Module: "mesh-delivery", Tool: tool,
Node: "anchor", Subject: "mesh.mod.mesh-delivery.tool." + tool + ".anchor"})
}
for _, verb := range []string{"deliveries", "stalled"} {
endpoints = append(endpoints, announce.Endpoint{Kind: announce.KindSeat, Module: "mesh-delivery", Seat: "mesh-delivery",
Tool: verb, Scope: "mesh", Subject: "mesh.seat.mesh-delivery.tool." + verb})
}
x, _, _ := indexOfEndpoints(endpoints)
s := x.seat("mesh-delivery")
if s == nil || len(s.Verbs) != 2 {
t.Fatalf("the seat is listed with verbs %v, not its two", s)
}
if m := x.Modules["mesh-delivery"]; m == nil || len(m.Tools) != 2 {
t.Fatalf("the module is listed with tools %v, not its two", m)
}
for address, want := range map[string]struct {
seat bool
key string
}{
"mesh-delivery.deliveries": {true, "seat:mesh-delivery.deliveries"},
"mesh-delivery.stalled": {true, "seat:mesh-delivery.stalled"},
"anchor/mesh-delivery.delivery_status": {false, "mesh-delivery.delivery_status@anchor"},
"anchor/mesh-delivery.deliveries": {false, "mesh-delivery.deliveries@anchor"},
} {
got, err := resolve(x, address)
if err != nil {
t.Errorf("%s: %v", address, err)
continue
}
if got.Seat != want.seat || got.Key != want.key {
t.Errorf("%s resolves to %+v, not the %s", address, got, want.key)
}
}
// A module tool of the name without a machine: the module keeps state on its machine, so it says so.
if _, err := resolve(x, "mesh-delivery.delivery_status"); err == nil || !strings.Contains(err.Error(), "<node>/") {
t.Errorf("the module's tool without a machine: %v", err)
}
}