2018-12-11 09:03:47 -05:00
|
|
|
package manager
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2018-12-19 09:49:20 -05:00
|
|
|
"reflect"
|
2018-12-11 09:03:47 -05:00
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"gotest.tools/assert"
|
2018-12-19 09:49:20 -05:00
|
|
|
"gotest.tools/assert/cmp"
|
2018-12-11 09:03:47 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
type fakeCandidate struct {
|
2019-05-21 12:50:12 -04:00
|
|
|
path string
|
|
|
|
exec bool
|
|
|
|
meta string
|
|
|
|
allowExperimental bool
|
2018-12-11 09:03:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *fakeCandidate) Path() string {
|
|
|
|
return c.path
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *fakeCandidate) Metadata() ([]byte, error) {
|
|
|
|
if !c.exec {
|
|
|
|
return nil, fmt.Errorf("faked a failure to exec %q", c.path)
|
|
|
|
}
|
|
|
|
return []byte(c.meta), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestValidateCandidate(t *testing.T) {
|
|
|
|
var (
|
|
|
|
goodPluginName = NamePrefix + "goodplugin"
|
|
|
|
|
|
|
|
builtinName = NamePrefix + "builtin"
|
|
|
|
builtinAlias = NamePrefix + "alias"
|
|
|
|
|
|
|
|
badPrefixPath = "/usr/local/libexec/cli-plugins/wobble"
|
|
|
|
badNamePath = "/usr/local/libexec/cli-plugins/docker-123456"
|
|
|
|
goodPluginPath = "/usr/local/libexec/cli-plugins/" + goodPluginName
|
|
|
|
)
|
|
|
|
|
|
|
|
fakeroot := &cobra.Command{Use: "docker"}
|
|
|
|
fakeroot.AddCommand(&cobra.Command{
|
|
|
|
Use: strings.TrimPrefix(builtinName, NamePrefix),
|
|
|
|
Aliases: []string{
|
|
|
|
strings.TrimPrefix(builtinAlias, NamePrefix),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
for _, tc := range []struct {
|
|
|
|
c *fakeCandidate
|
|
|
|
|
|
|
|
// Either err or invalid may be non-empty, but not both (both can be empty for a good plugin).
|
|
|
|
err string
|
|
|
|
invalid string
|
|
|
|
}{
|
|
|
|
/* Each failing one of the tests */
|
|
|
|
{c: &fakeCandidate{path: ""}, err: "plugin candidate path cannot be empty"},
|
|
|
|
{c: &fakeCandidate{path: badPrefixPath}, err: fmt.Sprintf("does not have %q prefix", NamePrefix)},
|
|
|
|
{c: &fakeCandidate{path: badNamePath}, invalid: "did not match"},
|
|
|
|
{c: &fakeCandidate{path: builtinName}, invalid: `plugin "builtin" duplicates builtin command`},
|
|
|
|
{c: &fakeCandidate{path: builtinAlias}, invalid: `plugin "alias" duplicates an alias of builtin command "builtin"`},
|
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: false}, invalid: fmt.Sprintf("failed to fetch metadata: faked a failure to exec %q", goodPluginPath)},
|
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `xyzzy`}, invalid: "invalid character"},
|
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{}`}, invalid: `plugin SchemaVersion "" is not valid`},
|
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "xyzzy"}`}, invalid: `plugin SchemaVersion "xyzzy" is not valid`},
|
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0"}`}, invalid: "plugin metadata does not define a vendor"},
|
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": ""}`}, invalid: "plugin metadata does not define a vendor"},
|
2019-05-21 12:50:12 -04:00
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing", "Experimental": true}`}, invalid: "requires experimental CLI"},
|
2018-12-11 09:03:47 -05:00
|
|
|
// This one should work
|
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing"}`}},
|
2019-05-21 12:50:12 -04:00
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing"}`, allowExperimental: true}},
|
|
|
|
{c: &fakeCandidate{path: goodPluginPath, exec: true, meta: `{"SchemaVersion": "0.1.0", "Vendor": "e2e-testing", "Experimental": true}`, allowExperimental: true}},
|
2018-12-11 09:03:47 -05:00
|
|
|
} {
|
2019-05-21 12:50:12 -04:00
|
|
|
p, err := newPlugin(tc.c, fakeroot, tc.c.allowExperimental)
|
2018-12-11 09:03:47 -05:00
|
|
|
if tc.err != "" {
|
|
|
|
assert.ErrorContains(t, err, tc.err)
|
|
|
|
} else if tc.invalid != "" {
|
|
|
|
assert.NilError(t, err)
|
2018-12-19 09:49:20 -05:00
|
|
|
assert.Assert(t, cmp.ErrorType(p.Err, reflect.TypeOf(&pluginError{})))
|
2018-12-11 09:03:47 -05:00
|
|
|
assert.ErrorContains(t, p.Err, tc.invalid)
|
|
|
|
} else {
|
|
|
|
assert.NilError(t, err)
|
|
|
|
assert.Equal(t, NamePrefix+p.Name, goodPluginName)
|
|
|
|
assert.Equal(t, p.SchemaVersion, "0.1.0")
|
|
|
|
assert.Equal(t, p.Vendor, "e2e-testing")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCandidatePath(t *testing.T) {
|
|
|
|
exp := "/some/path"
|
|
|
|
cand := &candidate{path: exp}
|
|
|
|
assert.Equal(t, exp, cand.Path())
|
|
|
|
}
|