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  }