Files
mesh-sdk/go/delivery/forge_inputs_test.go
T
mesh-tools 6f9a83646a
mesh/merge-gate head 6f9a83646ab7 merged into trunk ab0c16ddad26 — pass, with a note: builds mesh-sdk (+41 dependent(s)) → ace, g14, novox, shanks; no bus …
mesh/repo-check head 6f9a83646ab7 merged into trunk ab0c16ddad26 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (typescript)…
mesh/delivery delivered
Pin the json names of manifests, locks and inputs2 by the encoded bytes (issue 1442, review round 1)
Go decodes keys case-insensitively, so a round trip could not see a dropped tag; the encoded bytes now name each field and an older message re-encodes to its own bytes.
2026-10-20 18:22:58 +00:00

145 lines
5.3 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)
}
for _, frag := range []string{`"manifests":{"a":`, `"locks":{"a":{"go.sum":`} {
if !strings.Contains(string(data), frag) {
t.Errorf("the encoding lacks %s: %s", frag, data)
}
}
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)
// the older message is written with the struct's key order, so the bytes compare as they are
if err != nil || string(data) != old {
t.Errorf("%s, %v, want exactly %s", data, err, old)
}
}
// 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)
}
if !strings.Contains(string(data), `"inputs2":{"tree":"t1"`) {
t.Errorf("the encoding lacks inputs2: %s", data)
}
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")
}
}