ADR 0593 §7: the composer with its refusals leaves mesh-sdk, so mesh-sdk carries no composition rule. The catalogue functions only the node-engine's composition reaches (Resolve, Resolution's Compose, Declaration, DataItems, LeftOut, Rules and the rest, the settings, placeholder and template refusals, the rendering helpers) are copied with their tests into internal/compose/resolution; a method of a mesh-sdk shape becomes a function taking it first. The composition calls its own copies, and the captured catalogue its tests read lives here now, shared by mesh-compose's tests. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
118 lines
4.6 KiB
Go
118 lines
4.6 KiB
Go
package resolution
|
|
|
|
import (
|
|
"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)
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
}
|