Files
mesh-sdk/go/delivery/forge_inputs_test.go
T
mesh-tools 31c3b6cedc Carry manifests and lock hashes in the forge messages, keep a module's new-form inputs, and lay out the build modules' toolchain keys (design 47 R4c-1, issues 1442, 1443)
The indexer needs a module's manifest, lock hashes and toolchain to compute its new-form fingerprint, and has none of them (ADR 0465 clauses 1, 2, 5): the forge messages now carry the first two, a module keeps its inputs so it can be computed again when a toolchain is reported, and the build modules' toolchain keys have a layout and an agreement rule.
2026-10-20 18:20:15 +00:00

136 lines
5.0 KiB
Go

package delivery
import (
"strings"
"testing"
)
const oddManifest = "{\n\t\"module\": \"a\",\n \"z\": 1, \"a\": [ \"x\",\"y\" ],\n \"why\": \"é — <b> & \\n\"\n}\n\n"
func mergedWithInputs() Forge {
return Forge{Kind: ForgeMerged, Repository: "novox/mesh-sdk", Number: 36, Head: "aaaa", Merge: "cccc", Root: "t0",
Trees: map[string]string{"a": "t1", "b": "t2"},
Manifests: map[string]string{"a": oddManifest},
Locks: map[string]map[string]string{"a": {"go.sum": strings.Repeat("ab", 32)}}}
}
// 1442/AC1
func TestForgeMergedCarriesManifestsAndLocks(t *testing.T) {
f := mergedWithInputs()
data, err := EncodeForge(f)
if err != nil {
t.Fatal(err)
}
got, err := DecodeForge(data)
if err != nil {
t.Fatal(err)
}
if got.Manifests["a"] != oddManifest || !SameForge(got, withV(f)) {
t.Errorf("the message changed on the way: %q", got.Manifests["a"])
}
}
func withV(f Forge) Forge { f.V = Version; return f }
// 1442/AC2
func TestForgeMergedRefusesBadInputs(t *testing.T) {
for name, tc := range map[string]struct {
mut func(*Forge)
want string
}{
"manifest outside trees": {func(f *Forge) { f.Manifests["zz"] = "{}" }, `"zz"`},
"locks outside trees": {func(f *Forge) { f.Locks["yy"] = map[string]string{"go.sum": "h"} }, `"yy"`},
"empty manifest": {func(f *Forge) { f.Manifests["b"] = "" }, `"b"`},
"empty lock hash": {func(f *Forge) { f.Locks["a"]["go.sum"] = "" }, `"a"`},
} {
f := mergedWithInputs()
tc.mut(&f)
if _, err := EncodeForge(f); err == nil || !strings.Contains(err.Error(), tc.want) {
t.Errorf("%s: %v, want a refusal naming %s", name, err, tc.want)
}
}
}
// 1442/AC3
func TestForgePullCarriesManifestsAndLocks(t *testing.T) {
pull := func(action string) Forge {
return Forge{Kind: ForgePull, Repository: "novox/mesh-sdk", Number: 1, Head: "h", Action: action,
Dirs: []string{"a"}, DirsKnown: true, Manifests: map[string]string{"a": oddManifest},
Locks: map[string]map[string]string{"a": {"go.sum": strings.Repeat("0", 64)}}}
}
for _, action := range []string{PullOpened, PullUpdated} {
data, err := EncodeForge(pull(action))
if err != nil {
t.Fatalf("%s: %v", action, err)
}
if got, err := DecodeForge(data); err != nil || got.Manifests["a"] != oddManifest {
t.Errorf("%s: %v", action, err)
}
}
f := pull(PullOpened)
f.Manifests["b"] = "{}"
if _, err := EncodeForge(f); err == nil || !strings.Contains(err.Error(), `"b"`) {
t.Errorf("a manifest outside Dirs: %v", err)
}
f = pull(PullOpened)
f.Locks["c"] = map[string]string{"go.sum": "h"}
if _, err := EncodeForge(f); err == nil || !strings.Contains(err.Error(), `"c"`) {
t.Errorf("locks outside Dirs: %v", err)
}
for name, f := range map[string]Forge{
"refused manifests": {Kind: ForgeRefused, Repository: "a/b", Act: "x", Words: "no", Manifests: map[string]string{"a": "{}"}},
"refused locks": {Kind: ForgeRefused, Repository: "a/b", Act: "x", Words: "no", Locks: map[string]map[string]string{"a": {"go.sum": "h"}}},
"open manifests": {Kind: ForgeOpen, Manifests: map[string]string{"a": "{}"}},
"open locks": {Kind: ForgeOpen, Locks: map[string]map[string]string{"a": {"go.sum": "h"}}},
} {
if _, err := EncodeForge(f); err == nil {
t.Errorf("%s was encoded", name)
}
}
}
// 1442/AC4
func TestForgeFromAnOlderBridge(t *testing.T) {
old := `{"v":1,"kind":"merged","repository":"novox/mesh-sdk","number":36,"head":"aaaa","merge":"cccc","trees":{"a":"t1"},"root":"t0"}`
f, err := DecodeForge([]byte(old))
if err != nil || f.Manifests != nil || f.Locks != nil {
t.Fatalf("%+v, %v", f, err)
}
data, err := EncodeForge(f)
if err != nil || strings.Contains(string(data), "manifests") || strings.Contains(string(data), "locks") {
t.Errorf("%s, %v", data, err)
}
}
// 1442/AC5
func TestModuleKeepsInputs2(t *testing.T) {
kept := KeptInputs2{Tree: "t1", Bases: []string{"src2:" + strings.Repeat("1", 64), "src2:" + strings.Repeat("2", 64)},
Builder: "src2:" + strings.Repeat("3", 64), Contexts: map[string]string{"web": "t9"},
Locks: map[string]string{"web": strings.Repeat("cd", 32)}}
m := Module{FP: "src1:x", Manifest: strings.Repeat("ef", 32), Inputs2: &kept, Repository: "novox/m", Commit: "c"}
m.FP = SourcePrefix + "x"
data, err := EncodeModule(m)
if err != nil {
t.Fatal(err)
}
got, err := DecodeModule(data)
if err != nil {
t.Fatal(err)
}
m.V = Version
if !SameModule(got, m) {
t.Errorf("Inputs2 did not come back equal: %+v", got.Inputs2)
}
tc := map[string]Toolchain2{"web": {Language: "typescript", Version: "5.9", Recipe: "2"}}
want, none := SourceFingerprint2(SourceInputs2{Module: "m", Tree: kept.Tree, Bases: kept.Bases, Builder: kept.Builder,
Contexts: kept.Contexts, Locks: kept.Locks, Toolchains: tc})
have, none2 := SourceFingerprint2(got.Inputs2.With("m", tc))
if want == "" || none != "" || none2 != "" || have != want {
t.Errorf("fingerprints differ: %q %q (%q %q)", have, want, none, none2)
}
m.Manifest = ""
if _, err := EncodeModule(m); err == nil {
t.Error("Inputs2 without a manifest digest was encoded")
}
}