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
69 lines
2.4 KiB
Go
69 lines
2.4 KiB
Go
package resolution
|
|
|
|
import (
|
|
"encoding/json"
|
|
"reflect"
|
|
"testing"
|
|
|
|
mcat "git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// What a provider receives is composed once, and issued twice: as its received file, and in its
|
|
// membership on the bus (novox/hq ADR 0167). The two are the same list, so a proxy reading the bus
|
|
// and one reading the file serve the same routes — including the port the machine published, which
|
|
// is the same-node fix the file already carries.
|
|
func TestWhatAProviderReceivesIsTheSameOnTheBusAsInItsFile(t *testing.T) {
|
|
gitea := mcat.Manifest{
|
|
Module: "gitea", Version: "1",
|
|
Listens: []mcat.Listening{{Port: 3000, Protocol: "tcp", From: mcat.FromMesh}},
|
|
Contributes: map[string]map[string]any{"route": {"label": "git", "port": 3000}},
|
|
Resources: []map[string]any{{
|
|
"id": "server", "type": "container", "name": "gitea", "ports": []any{"3000"},
|
|
}},
|
|
}
|
|
r, err := Resolve(shelf(gitea, routeProxy(), stepCA()),
|
|
[]string{"gitea", "route-proxy", "step-ca"}, reachable(), mcat.World{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
composed, err := Compose(r, mcat.Rendering{Ports: map[string]map[int]int{"gitea": {3000: 20000}}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
file := fileNamed(composed.Resources, "route-proxy.received-route")
|
|
if file == nil {
|
|
t.Fatal("the proxy was given no routes file")
|
|
}
|
|
var written struct {
|
|
Given []mcat.Contribution `json:"given"`
|
|
}
|
|
if err := json.Unmarshal([]byte(file["content"].(string)), &written); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
issued, said := composed.Received["route-proxy"]["route"]
|
|
if !said {
|
|
t.Fatalf("nothing is issued for the proxy to receive on the bus: %v", composed.Received)
|
|
}
|
|
// Compared as JSON, which is what both are once they leave the controller.
|
|
a, _ := json.Marshal(written.Given)
|
|
b, _ := json.Marshal(issued)
|
|
var fromFile, fromBus any
|
|
_ = json.Unmarshal(a, &fromFile)
|
|
_ = json.Unmarshal(b, &fromBus)
|
|
if !reflect.DeepEqual(fromFile, fromBus) {
|
|
t.Errorf("the bus and the file disagree about the routes:\nfile %s\nbus %s", a, b)
|
|
}
|
|
if len(issued) != 1 {
|
|
t.Fatalf("expected one route on the bus, got %v", issued)
|
|
}
|
|
if port, ok := asPort(issued[0].Values["port"]); !ok || port != 20000 {
|
|
t.Errorf("the bus carries a port nothing listens on: %v", issued[0].Values["port"])
|
|
}
|
|
|
|
// A module that receives nothing is issued nothing to receive.
|
|
if _, any := composed.Received["gitea"]; any {
|
|
t.Errorf("a module that receives nothing was issued something: %v", composed.Received["gitea"])
|
|
}
|
|
}
|