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.
136 lines
5.0 KiB
Go
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")
|
|
}
|
|
}
|