mesh-wireguard (built by nobody) and every module a node runs inside its own composition (Node.InOwn, from frombus.InOwn of what it runs) were cut out as skipped: every node's shadow answered differs to the placement seed, and a node composing itself after it would drop their resources. compositions now folds them in place, module taken off, filled paths with them, as mesh-controller's compositionsOf does; a want naming a new-form build still moves one out.
115 lines
4.5 KiB
Go
115 lines
4.5 KiB
Go
package compose
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
func fpFor(c byte) string { return delivery.SourcePrefix2 + strings.Repeat(string(c), 64) }
|
|
|
|
// 1943/AC5: a node's compositions are its declaration as Compose gives it, split by the module each resource belongs
|
|
// to: every resource once, each in its module's composition at the fingerprint given, the module's ownership said on
|
|
// it; a module given no fingerprint is named as skipped and composed nowhere.
|
|
func TestCompositionsAreTheDeclarationSplitByModule(t *testing.T) {
|
|
in := aSmallMesh(t)
|
|
d, _, err := Compose(in, "laptop")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var want []string
|
|
for _, r := range d.Resources {
|
|
want = append(want, r["type"].(string)+":"+r["id"].(string))
|
|
}
|
|
sort.Strings(want)
|
|
|
|
fps := map[string]string{"mesh-wireguard": fpFor('a'), "files": fpFor('b')}
|
|
out, skipped, err := Compositions(in, "laptop", fps, Foreseeing)
|
|
if err != nil || len(skipped) != 0 {
|
|
t.Fatalf("Compositions = %v, skipped %v", err, skipped)
|
|
}
|
|
var got []string
|
|
for key, c := range out {
|
|
node, module, fp, isNode, err := delivery.ParseComposedKey(key)
|
|
if err != nil || node != "laptop" || module != c.Module || fp != c.FP || (isNode != (module == "")) {
|
|
t.Errorf("key %s holds %s at %s (%v)", key, c.Module, c.FP, err)
|
|
}
|
|
if !isNode && fp != fps[module] {
|
|
t.Errorf("%s is composed at %s, given %s", module, fp, fps[module])
|
|
}
|
|
if _, err := delivery.EncodeComposed(c); err != nil {
|
|
t.Errorf("%s: %v", key, err)
|
|
}
|
|
for _, raw := range c.Resources {
|
|
var r struct{ ID, Type, Module string }
|
|
_ = json.Unmarshal(raw, &r)
|
|
if r.Module != module {
|
|
t.Errorf("%s holds %s of %q", key, r.ID, r.Module)
|
|
}
|
|
got = append(got, r.Type+":"+r.ID)
|
|
}
|
|
}
|
|
sort.Strings(got)
|
|
if strings.Join(got, " ") != strings.Join(want, " ") {
|
|
t.Errorf("the compositions hold %v, the declaration %v", got, want)
|
|
}
|
|
|
|
one, skipped, err := Compositions(in, "laptop", map[string]string{"mesh-wireguard": fpFor('a')}, Foreseeing)
|
|
if err != nil || strings.Join(skipped, ",") != "files" {
|
|
t.Fatalf("one module: %v, skipped %v", err, skipped)
|
|
}
|
|
for _, c := range one {
|
|
if c.Module == "files" {
|
|
t.Errorf("a module given no fingerprint was composed")
|
|
}
|
|
}
|
|
|
|
// Issue 1126: a module the node runs inside its own composition (Node.InOwn), and the private network's always,
|
|
// given no fingerprint of the new form, is folded into the node's own as the controller's composed writer folds it:
|
|
// every resource in its place, its module taken off, its id still naming it, nothing skipped.
|
|
folding := in
|
|
folding.Nodes = append([]Node(nil), in.Nodes...)
|
|
for i := range folding.Nodes {
|
|
if folding.Nodes[i].Name == "laptop" {
|
|
folding.Nodes[i].InOwn = map[string]bool{"files": true}
|
|
}
|
|
}
|
|
all, skipped, err := Compositions(folding, "laptop", nil, Foreseeing)
|
|
nodeKey, _ := delivery.ComposedNodeKey("laptop")
|
|
if err != nil || len(skipped) != 0 || len(all) != 1 || len(all[nodeKey].Resources) != len(want) {
|
|
t.Fatalf("folded: %v, skipped %v, %d compositions, %d of %d resources in the node's own", err, skipped, len(all), len(all[nodeKey].Resources), len(want))
|
|
}
|
|
for i, raw := range all[nodeKey].Resources {
|
|
var r map[string]any
|
|
_ = json.Unmarshal(raw, &r)
|
|
if _, says := r["module"]; says || r["id"] != d.Resources[i]["id"] {
|
|
t.Errorf("folded resource %d is %v, the declaration's %v", i, r["id"], d.Resources[i]["id"])
|
|
}
|
|
}
|
|
if _, err := delivery.EncodeComposed(all[nodeKey]); err != nil {
|
|
t.Errorf("the node's own with the folded modules: %v", err)
|
|
}
|
|
if _, _, err := Compositions(in, "nowhere", fps, Foreseeing); err == nil {
|
|
t.Errorf("a node the mesh does not have was composed")
|
|
}
|
|
}
|
|
|
|
// 1943/AC1: the upgrade policies and sources a composition's value may name are the catalogue's own words.
|
|
func TestTheComposedPoliciesAreTheCatalogues(t *testing.T) {
|
|
for _, p := range []string{catalogue.PolicyRoll, catalogue.PolicyTogether, catalogue.PolicyRecord} {
|
|
for _, from := range []string{catalogue.FromPerson, catalogue.FromModule, catalogue.FromBus, catalogue.FromData, catalogue.FromDefault} {
|
|
v := delivery.ComposedDigest{Digest: "sha256:" + strings.Repeat("a", 64), Judgement: delivery.JudgedNeither, Policy: p, PolicyFrom: from}
|
|
if _, err := delivery.EncodeComposedDigest(v); err != nil {
|
|
t.Errorf("%s from %s: %v", p, from, err)
|
|
}
|
|
}
|
|
}
|
|
if delivery.PolicyRecord != catalogue.PolicyRecord {
|
|
t.Errorf("delivery.PolicyRecord = %q, the catalogue's %q", delivery.PolicyRecord, catalogue.PolicyRecord)
|
|
}
|
|
}
|