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"]) } // ADR 0565 §2 (issue 1953 D1): a merged message carries the predefined list exact, or says the merge holds none; a // pull message carries neither. f.Predefined = []byte(`{"domain":{"type":"string"}}`) if data, err := EncodeForge(f); err != nil { t.Fatal(err) } else if got, err := DecodeForge(data); err != nil || string(got.Predefined) != `{"domain":{"type":"string"}}` { t.Errorf("the predefined list read back as %s, %v", got.Predefined, err) } f.Predefined, f.PredefinedRead = nil, true if _, err := EncodeForge(f); err != nil { t.Errorf("a merge holding no predefined list: %v", err) } pull := Forge{Kind: ForgePull, Repository: "novox/mesh-sdk", Number: 1, Head: "h", Action: PullOpened, PredefinedRead: true} if _, err := EncodeForge(pull); err == nil || !strings.Contains(err.Error(), "only a merged message") { t.Errorf("a pull message carrying the predefined list: %v", err) } } 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"`}, // No repository holds placement (ADR 0567 §11): a message carrying placement files is refused, on a merge or a pull. "placement files": {func(f *Forge) { f.RetiredPlacements = []byte(`{"anchor":"{}"}`) }, "mesh-placement"}, "placements read": {func(f *Forge) { f.RetiredRead = true }, "mesh-placement"}, // ADR 0565 §2 (issue 1953 D1): the predefined list is one JSON object, said present or absent, never both. "predefined not an object": {func(f *Forge) { f.Predefined = []byte(`["domain"]`) }, "one JSON object"}, "predefined both": {func(f *Forge) { f.Predefined = []byte(`{}`); f.PredefinedRead = true }, "says the merge holds none"}, } { 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) } }