package delivery import ( "strings" "testing" ) const oddManifest = "{\n\t\"module\": \"a\",\n \"z\": 1, \"a\": [ \"x\",\"y\" ],\n \"why\": \"é — & \\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") } }