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