Files
mesh-host/internal/compose/resolution/served_own_names_test.go
T
jschoubben b6c174a324 A consumer beside a held provider is told what it serves without the names it does not compose, never their placeholders (issue 1921, milestone 47/G)
The provider held on its machine is composed apart, so no module of the composed set serves the provision; its
manifest's served values reached the consumer's binding raw and the binding refused the consumer for a
${bound:route:name-web} it does not require (the group check of 8a80e8e86858 on novox, mesh-build-node beside a held
gitea). Each such key is now left out and said on the need, as a provider elsewhere leaves it out (ADR 0346).

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-07 07:19:58 +01:00

142 lines
5.9 KiB
Go

package resolution
import (
"slices"
"strings"
"testing"
mcat "git.novox.be/novox/mesh-sdk/go/catalogue"
)
const aRegistryForge = `{"module":"forge","version":"1","requires":["route"],
"provides":[{"name":"npm-package-registry","scope":"mesh"}],
"contributes":{"route":{"web":{"label":"git","port":3000}}},
"serves":{"npm-package-registry":{"scheme":"http","port":3000,"npm-path":"/api/packages/novox/npm/",
"public-root":"https://${bound:route:name-web}/api/packages/novox/npm/"}}}`
func aForgeManifest(t *testing.T) mcat.Manifest {
t.Helper()
m, err := decodeForTest([]byte(aRegistryForge))
if err != nil {
t.Fatal(err)
}
return m
}
func TestAProviderServesItsOwnComposedName(t *testing.T) {
m := aForgeManifest(t)
r := mcat.Resolution{Node: "home", PublicDomain: "example.org"}
got, said, err := ServedOwnNames(r, m, "npm-package-registry", m.Serves["npm-package-registry"], nil)
if err != nil {
t.Fatal(err)
}
if got["public-root"] != "https://git.example.org/api/packages/novox/npm/" || len(said) != 0 {
t.Fatalf("the public root is the route's composed name: %v, said %v", got, said)
}
if got["npm-path"] != "/api/packages/novox/npm/" || got["port"] != float64(3000) {
t.Fatalf("the rest is served as it was: %v", got)
}
if m.Serves["npm-package-registry"]["public-root"] != "https://${bound:route:name-web}/api/packages/novox/npm/" {
t.Fatal("the manifest's own map was rewritten")
}
}
// On the provider's own machine the consumer is served the same name (ADR 0346 §2).
func TestAConsumerBesideTheProviderIsServedItsName(t *testing.T) {
m := aForgeManifest(t)
consumer := mcat.Manifest{Module: "lab", Version: "1", Requires: []string{"npm-package-registry"},
Binds: map[string]string{"npm-package-registry": "/var/lib/lab/package-registry.json"}}
node := workstation()
node.PublicDomain = "example.org"
got, err := Resolve(shelf(minimalRouteProxy(), m, consumer), []string{"route-proxy", "forge", "lab"}, node, mcat.World{})
if err != nil {
t.Fatal(err)
}
served, answered, err := resolutionServedOnThisMachine(got, "npm-package-registry", mcat.Rendering{})
if err != nil || !answered {
t.Fatalf("answered %v: %v", answered, err)
}
if served["public-root"] != "https://git.example.org/api/packages/novox/npm/" {
t.Fatalf("served beside the provider: %v", served)
}
out, err := Declaration(got, mcat.Rendering{})
if err != nil {
t.Fatal(err)
}
var binding string
for _, r := range out {
if r["path"] == "/var/lib/lab/package-registry.json" {
binding, _ = r["content"].(string)
}
}
if !strings.Contains(binding, `"public-root": "https://git.example.org/api/packages/novox/npm/"`) &&
!strings.Contains(binding, `"public-root":"https://git.example.org/api/packages/novox/npm/"`) {
t.Fatalf("the consumer's binding carries the name:\n%s", binding)
}
if strings.Contains(binding, "${bound:") {
t.Fatalf("a placeholder reached the consumer:\n%s", binding)
}
// Issue 1921 (the group check of 8a80e8e86858, novox): the provider held on this machine (composed apart, as what runs
// of it) is not in the composed set, so none of its own names is composed here. The consumer beside it is told
// what it serves without the keys that name them, each said on the need, never the placeholder: its binding refused
// the consumer with "has a file that says ${bound:route:name-web}, and lab does not require route".
held, err := Resolve(shelf(minimalRouteProxy(), m, consumer), []string{"route-proxy", "forge", "lab"}, node, mcat.World{})
if err != nil {
t.Fatal(err)
}
held.Modules = slices.DeleteFunc(slices.Clone(held.Modules), func(m mcat.Manifest) bool { return m.Module == "forge" })
out, err = Declaration(held, mcat.Rendering{})
if err != nil {
t.Fatalf("a consumer beside a held provider: %v", err)
}
for _, r := range out {
if c, _ := r["content"].(string); r["path"] == "/var/lib/lab/package-registry.json" && (strings.Contains(c, "${bound:") || !strings.Contains(c, "npm-path")) {
t.Fatalf("the binding beside a held provider:\n%s", c)
}
}
for _, n := range held.Needs {
if n.Name == "npm-package-registry" && (len(n.LeftOut) != 1 || !strings.Contains(n.LeftOut[0], `"public-root"`)) {
t.Fatalf("the need beside a held provider says not what was left out: %+v", n)
}
}
}
// From another machine, the provider's served values carry what that machine composed, and a key it
// left out is said on the consumer's need (ADR 0346 §2, §3).
func TestAConsumerElsewhereIsToldWhatTheProviderLeftOut(t *testing.T) {
consumer := mcat.Manifest{Module: "lab", Version: "1", Requires: []string{"npm-package-registry"},
Binds: map[string]string{"npm-package-registry": "/var/lib/lab/package-registry.json"}}
node := workstation()
node.At = "workstation.internal"
world := mcat.World{Offered: map[string][]mcat.Provider{"npm-package-registry": {{Node: "home", At: "home.internal",
Module: "forge", Serves: map[string]any{"port": 3000},
LeftOut: []string{`forge serves npm-package-registry without "public-root"`}}}}}
got, err := Resolve(shelf(aForgeManifest(t), consumer), []string{"lab"}, node, world)
if err != nil {
t.Fatal(err)
}
for _, n := range got.Needs {
if n.Name == "npm-package-registry" {
if len(n.LeftOut) != 1 {
t.Fatalf("the need carries what was left out: %+v", n)
}
return
}
}
t.Fatalf("no need: %+v", got.Needs)
}
// The provider's contributions file carries no own name on a consumer's entry (ADR 0346 §4): only what
// is derived for that consumer is there (ADR 0202 §5), and the provider reads its own names in its files.
func TestAProvidersOwnNameIsNotOnItsConsumersEntry(t *testing.T) {
m := aForgeManifest(t)
r := mcat.Resolution{Node: "home", PublicDomain: "example.org", Modules: []mcat.Manifest{m}}
derived, err := resolutionDerivedFor(r, "npm-package-registry", "lab_home", "lab", "", nil)
if err != nil {
t.Fatal(err)
}
if derived != nil {
t.Fatalf("a consumer's entry carries only what was derived for it: %v", derived)
}
}