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"
2020-02-22 12:12:14 -05:00
"gotest.tools/v3/assert"
"gotest.tools/v3/assert/cmp"
2018-12-11 09:03:47 -05:00
)
type fakeCandidate struct {
2020-10-02 08:19:34 -04:00
path string
exec bool
meta string
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 ) {
2020-10-02 08:19:34 -04:00
const (
2018-12-11 09:03:47 -05:00
goodPluginName = NamePrefix + "goodplugin"
builtinName = NamePrefix + "builtin"
builtinAlias = NamePrefix + "alias"
2019-05-21 18:24:00 -04:00
badPrefixPath = "/usr/local/libexec/cli-plugins/wobble"
badNamePath = "/usr/local/libexec/cli-plugins/docker-123456"
goodPluginPath = "/usr/local/libexec/cli-plugins/" + goodPluginName
metaExperimental = ` { "SchemaVersion": "0.1.0", "Vendor": "e2e-testing", "Experimental": true} `
2018-12-11 09:03:47 -05:00
)
fakeroot := & cobra . Command { Use : "docker" }
fakeroot . AddCommand ( & cobra . Command {
Use : strings . TrimPrefix ( builtinName , NamePrefix ) ,
Aliases : [ ] string {
strings . TrimPrefix ( builtinAlias , NamePrefix ) ,
} ,
} )
for _ , tc := range [ ] struct {
2019-05-21 18:24:00 -04:00
name string
c * fakeCandidate
2018-12-11 09:03:47 -05:00
// 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 */
2019-05-21 18:24:00 -04:00
{ name : "empty path" , c : & fakeCandidate { path : "" } , err : "plugin candidate path cannot be empty" } ,
{ name : "bad prefix" , c : & fakeCandidate { path : badPrefixPath } , err : fmt . Sprintf ( "does not have %q prefix" , NamePrefix ) } ,
{ name : "bad path" , c : & fakeCandidate { path : badNamePath } , invalid : "did not match" } ,
{ name : "builtin command" , c : & fakeCandidate { path : builtinName } , invalid : ` plugin "builtin" duplicates builtin command ` } ,
{ name : "builtin alias" , c : & fakeCandidate { path : builtinAlias } , invalid : ` plugin "alias" duplicates an alias of builtin command "builtin" ` } ,
{ name : "fetch failure" , c : & fakeCandidate { path : goodPluginPath , exec : false } , invalid : fmt . Sprintf ( "failed to fetch metadata: faked a failure to exec %q" , goodPluginPath ) } ,
{ name : "metadata not json" , c : & fakeCandidate { path : goodPluginPath , exec : true , meta : ` xyzzy ` } , invalid : "invalid character" } ,
{ name : "empty schemaversion" , c : & fakeCandidate { path : goodPluginPath , exec : true , meta : ` { } ` } , invalid : ` plugin SchemaVersion "" is not valid ` } ,
{ name : "invalid schemaversion" , c : & fakeCandidate { path : goodPluginPath , exec : true , meta : ` { "SchemaVersion": "xyzzy"} ` } , invalid : ` plugin SchemaVersion "xyzzy" is not valid ` } ,
{ name : "no vendor" , c : & fakeCandidate { path : goodPluginPath , exec : true , meta : ` { "SchemaVersion": "0.1.0"} ` } , invalid : "plugin metadata does not define a vendor" } ,
{ name : "empty vendor" , c : & fakeCandidate { path : goodPluginPath , exec : true , meta : ` { "SchemaVersion": "0.1.0", "Vendor": ""} ` } , invalid : "plugin metadata does not define a vendor" } ,
2018-12-11 09:03:47 -05:00
// This one should work
2019-05-21 18:24:00 -04:00
{ name : "valid" , c : & fakeCandidate { path : goodPluginPath , exec : true , meta : ` { "SchemaVersion": "0.1.0", "Vendor": "e2e-testing"} ` } } ,
2020-10-02 08:19:34 -04:00
{ name : "experimental + allowing experimental" , c : & fakeCandidate { path : goodPluginPath , exec : true , meta : metaExperimental } } ,
2018-12-11 09:03:47 -05:00
} {
2019-05-21 18:24:00 -04:00
t . Run ( tc . name , func ( t * testing . T ) {
2020-10-02 08:19:34 -04:00
p , err := newPlugin ( tc . c , fakeroot )
2019-05-21 18:24:00 -04:00
if tc . err != "" {
assert . ErrorContains ( t , err , tc . err )
} else if tc . invalid != "" {
assert . NilError ( t , err )
assert . Assert ( t , cmp . ErrorType ( p . Err , reflect . TypeOf ( & pluginError { } ) ) )
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" )
}
} )
2018-12-11 09:03:47 -05:00
}
}
func TestCandidatePath ( t * testing . T ) {
exp := "/some/path"
cand := & candidate { path : exp }
assert . Equal ( t , exp , cand . Path ( ) )
}