github.com/itscaro/cli@v0.0.0-20190705081621-c9db0fe93829/cli-plugins/manager/candidate_test.go (about) 1 package manager 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 "testing" 8 9 "github.com/spf13/cobra" 10 "gotest.tools/assert" 11 "gotest.tools/assert/cmp" 12 ) 13 14 type fakeCandidate struct { 15 path string 16 exec bool 17 meta string 18 allowExperimental bool 19 } 20 21 func (c *fakeCandidate) Path() string { 22 return c.path 23 } 24 25 func (c *fakeCandidate) Metadata() ([]byte, error) { 26 if !c.exec { 27 return nil, fmt.Errorf("faked a failure to exec %q", c.path) 28 } 29 return []byte(c.meta), nil 30 } 31 32 func TestValidateCandidate(t *testing.T) { 33 var ( 34 goodPluginName = NamePrefix + "goodplugin" 35 36 builtinName = NamePrefix + "builtin" 37 builtinAlias = NamePrefix + "alias" 38 39 badPrefixPath = "/usr/local/libexec/cli-plugins/wobble" 40 badNamePath = "/usr/local/libexec/cli-plugins/docker-123456" 41 goodPluginPath = "/usr/local/libexec/cli-plugins/" + goodPluginName 42 metaExperimental = `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing", "Experimental": true}` 43 ) 44 45 fakeroot := &cobra.Command{Use: "docker"} 46 fakeroot.AddCommand(&cobra.Command{ 47 Use: strings.TrimPrefix(builtinName, NamePrefix), 48 Aliases: []string{ 49 strings.TrimPrefix(builtinAlias, NamePrefix), 50 }, 51 }) 52 53 for _, tc := range []struct { 54 name string 55 c *fakeCandidate 56 57 // Either err or invalid may be non-empty, but not both (both can be empty for a good plugin). 58 err string 59 invalid string 60 }{ 61 /* Each failing one of the tests */ 62 {name: "empty path", c: &fakeCandidate{path: ""}, err: "plugin candidate path cannot be empty"}, 63 {name: "bad prefix", c: &fakeCandidate{path: badPrefixPath}, err: fmt.Sprintf("does not have %q prefix", NamePrefix)}, 64 {name: "bad path", c: &fakeCandidate{path: badNamePath}, invalid: "did not match"}, 65 {name: "builtin command", c: &fakeCandidate{path: builtinName}, invalid: `plugin "builtin" duplicates builtin command`}, 66 {name: "builtin alias", c: &fakeCandidate{path: builtinAlias}, invalid: `plugin "alias" duplicates an alias of builtin command "builtin"`}, 67 {name: "fetch failure", c: &fakeCandidate{path: goodPluginPath, exec: false}, invalid: fmt.Sprintf("failed to fetch metadata: faked a failure to exec %q", goodPluginPath)}, 68 {name: "metadata not json", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `xyzzy`}, invalid: "invalid character"}, 69 {name: "empty schemaversion", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{}`}, invalid: `plugin SchemaVersion "" is not valid`}, 70 {name: "invalid schemaversion", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "xyzzy"}`}, invalid: `plugin SchemaVersion "xyzzy" is not valid`}, 71 {name: "no vendor", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0"}`}, invalid: "plugin metadata does not define a vendor"}, 72 {name: "empty vendor", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": ""}`}, invalid: "plugin metadata does not define a vendor"}, 73 {name: "experimental required", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: metaExperimental}, invalid: "requires experimental CLI"}, 74 // This one should work 75 {name: "valid", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing"}`}}, 76 {name: "valid + allowing experimental", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing"}`, allowExperimental: true}}, 77 {name: "experimental + allowing experimental", c: &fakeCandidate{path: goodPluginPath, exec: true, meta: metaExperimental, allowExperimental: true}}, 78 } { 79 t.Run(tc.name, func(t *testing.T) { 80 p, err := newPlugin(tc.c, fakeroot, tc.c.allowExperimental) 81 if tc.err != "" { 82 assert.ErrorContains(t, err, tc.err) 83 } else if tc.invalid != "" { 84 assert.NilError(t, err) 85 assert.Assert(t, cmp.ErrorType(p.Err, reflect.TypeOf(&pluginError{}))) 86 assert.ErrorContains(t, p.Err, tc.invalid) 87 } else { 88 assert.NilError(t, err) 89 assert.Equal(t, NamePrefix+p.Name, goodPluginName) 90 assert.Equal(t, p.SchemaVersion, "0.1.0") 91 assert.Equal(t, p.Vendor, "e2e-testing") 92 } 93 }) 94 } 95 } 96 97 func TestCandidatePath(t *testing.T) { 98 exp := "/some/path" 99 cand := &candidate{path: exp} 100 assert.Equal(t, exp, cand.Path()) 101 }