forked from mirror/cobra
Improve tests
This commit is contained in:
parent
099c5aef9e
commit
65c8acb228
|
@ -10,13 +10,13 @@ import (
|
||||||
|
|
||||||
func checkOmit(t *testing.T, found, unexpected string) {
|
func checkOmit(t *testing.T, found, unexpected string) {
|
||||||
if strings.Contains(found, unexpected) {
|
if strings.Contains(found, unexpected) {
|
||||||
t.Errorf("Unexpected response.\nGot: %q\nBut should not have!\n", unexpected)
|
t.Errorf("Got: %q\nBut should not have!\n", unexpected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func check(t *testing.T, found, expected string) {
|
func check(t *testing.T, found, expected string) {
|
||||||
if !strings.Contains(found, expected) {
|
if !strings.Contains(found, expected) {
|
||||||
t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found)
|
t.Errorf("Expecting to contain: \n %q\nGot:\n %q\n", expected, found)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,162 +33,164 @@ func runShellCheck(s string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer stdin.Close()
|
|
||||||
stdin.Write([]byte(s))
|
stdin.Write([]byte(s))
|
||||||
|
stdin.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// World worst custom function, just keep telling you to enter hello!
|
// World worst custom function, just keep telling you to enter hello!
|
||||||
const (
|
const bashCompletionFunc = `__custom_func() {
|
||||||
bashCompletionFunc = `__custom_func() {
|
COMPREPLY=( "hello" )
|
||||||
COMPREPLY=( "hello" )
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
)
|
|
||||||
|
|
||||||
func TestBashCompletions(t *testing.T) {
|
func TestBashCompletions(t *testing.T) {
|
||||||
c := initializeWithRootCmd()
|
rootCmd := &Command{
|
||||||
cmdEcho.AddCommand(cmdTimes)
|
Use: "root",
|
||||||
c.AddCommand(cmdEcho, cmdPrint, cmdDeprecated, cmdColon)
|
ArgAliases: []string{"pods", "nodes", "services", "replicationcontrollers", "po", "no", "svc", "rc"},
|
||||||
|
ValidArgs: []string{"pod", "node", "service", "replicationcontroller"},
|
||||||
|
BashCompletionFunction: bashCompletionFunc,
|
||||||
|
Run: emptyRun,
|
||||||
|
}
|
||||||
|
rootCmd.Flags().IntP("introot", "i", -1, "help message for flag introot")
|
||||||
|
rootCmd.MarkFlagRequired("introot")
|
||||||
|
|
||||||
// custom completion function
|
// Filename.
|
||||||
c.BashCompletionFunction = bashCompletionFunc
|
rootCmd.Flags().String("filename", "", "Enter a filename")
|
||||||
|
rootCmd.MarkFlagFilename("filename", "json", "yaml", "yml")
|
||||||
|
|
||||||
// required flag
|
// Persistent filename.
|
||||||
c.MarkFlagRequired("introot")
|
rootCmd.PersistentFlags().String("persistent-filename", "", "Enter a filename")
|
||||||
|
rootCmd.MarkPersistentFlagFilename("persistent-filename")
|
||||||
|
rootCmd.MarkPersistentFlagRequired("persistent-filename")
|
||||||
|
|
||||||
// valid nouns
|
// Filename extensions.
|
||||||
validArgs := []string{"pod", "node", "service", "replicationcontroller"}
|
rootCmd.Flags().String("filename-ext", "", "Enter a filename (extension limited)")
|
||||||
c.ValidArgs = validArgs
|
rootCmd.MarkFlagFilename("filename-ext")
|
||||||
|
rootCmd.Flags().String("custom", "", "Enter a filename (extension limited)")
|
||||||
|
rootCmd.MarkFlagCustom("custom", "__complete_custom")
|
||||||
|
|
||||||
// noun aliases
|
// Subdirectories in a given directory.
|
||||||
argAliases := []string{"pods", "nodes", "services", "replicationcontrollers", "po", "no", "svc", "rc"}
|
rootCmd.Flags().String("theme", "", "theme to use (located in /themes/THEMENAME/)")
|
||||||
c.ArgAliases = argAliases
|
rootCmd.Flags().SetAnnotation("theme", BashCompSubdirsInDir, []string{"themes"})
|
||||||
|
|
||||||
// filename
|
echoCmd := &Command{
|
||||||
var flagval string
|
Use: "echo [string to echo]",
|
||||||
c.Flags().StringVar(&flagval, "filename", "", "Enter a filename")
|
Aliases: []string{"say"},
|
||||||
c.MarkFlagFilename("filename", "json", "yaml", "yml")
|
Short: "Echo anything to the screen",
|
||||||
|
Long: "an utterly useless command for testing.",
|
||||||
|
Example: "Just run cobra-test echo",
|
||||||
|
Run: emptyRun,
|
||||||
|
}
|
||||||
|
|
||||||
// persistent filename
|
printCmd := &Command{
|
||||||
var flagvalPersistent string
|
Use: "print [string to print]",
|
||||||
c.PersistentFlags().StringVar(&flagvalPersistent, "persistent-filename", "", "Enter a filename")
|
Args: MinimumNArgs(1),
|
||||||
c.MarkPersistentFlagFilename("persistent-filename")
|
Short: "Print anything to the screen",
|
||||||
c.MarkPersistentFlagRequired("persistent-filename")
|
Long: "an absolutely utterly useless command for testing.",
|
||||||
|
Run: emptyRun,
|
||||||
|
}
|
||||||
|
|
||||||
// filename extensions
|
deprecatedCmd := &Command{
|
||||||
var flagvalExt string
|
Use: "deprecated [can't do anything here]",
|
||||||
c.Flags().StringVar(&flagvalExt, "filename-ext", "", "Enter a filename (extension limited)")
|
Args: NoArgs,
|
||||||
c.MarkFlagFilename("filename-ext")
|
Short: "A command which is deprecated",
|
||||||
|
Long: "an absolutely utterly useless command for testing deprecation!.",
|
||||||
|
Deprecated: "Please use echo instead",
|
||||||
|
Run: emptyRun,
|
||||||
|
}
|
||||||
|
|
||||||
// filename extensions
|
colonCmd := &Command{
|
||||||
var flagvalCustom string
|
Use: "cmd:colon",
|
||||||
c.Flags().StringVar(&flagvalCustom, "custom", "", "Enter a filename (extension limited)")
|
Run: emptyRun,
|
||||||
c.MarkFlagCustom("custom", "__complete_custom")
|
}
|
||||||
|
|
||||||
// subdirectories in a given directory
|
timesCmd := &Command{
|
||||||
var flagvalTheme string
|
Use: "times [# times] [string to echo]",
|
||||||
c.Flags().StringVar(&flagvalTheme, "theme", "", "theme to use (located in /themes/THEMENAME/)")
|
SuggestFor: []string{"counts"},
|
||||||
c.Flags().SetAnnotation("theme", BashCompSubdirsInDir, []string{"themes"})
|
Args: OnlyValidArgs,
|
||||||
|
ValidArgs: []string{"one", "two", "three", "four"},
|
||||||
|
Short: "Echo anything to the screen more times",
|
||||||
|
Long: "a slightly useless command for testing.",
|
||||||
|
Run: emptyRun,
|
||||||
|
}
|
||||||
|
|
||||||
out := new(bytes.Buffer)
|
echoCmd.AddCommand(timesCmd)
|
||||||
c.GenBashCompletion(out)
|
rootCmd.AddCommand(echoCmd, printCmd, deprecatedCmd, colonCmd)
|
||||||
str := out.String()
|
|
||||||
|
|
||||||
check(t, str, "_cobra-test")
|
buf := new(bytes.Buffer)
|
||||||
check(t, str, "_cobra-test_echo")
|
rootCmd.GenBashCompletion(buf)
|
||||||
check(t, str, "_cobra-test_echo_times")
|
output := buf.String()
|
||||||
check(t, str, "_cobra-test_print")
|
|
||||||
check(t, str, "_cobra-test_cmd__colon")
|
check(t, output, "_root")
|
||||||
|
check(t, output, "_root_echo")
|
||||||
|
check(t, output, "_root_echo_times")
|
||||||
|
check(t, output, "_root_print")
|
||||||
|
check(t, output, "_root_cmd__colon")
|
||||||
|
|
||||||
// check for required flags
|
// check for required flags
|
||||||
check(t, str, `must_have_one_flag+=("--introot=")`)
|
check(t, output, `must_have_one_flag+=("--introot=")`)
|
||||||
check(t, str, `must_have_one_flag+=("--persistent-filename=")`)
|
check(t, output, `must_have_one_flag+=("--persistent-filename=")`)
|
||||||
// check for custom completion function
|
// check for custom completion function
|
||||||
check(t, str, `COMPREPLY=( "hello" )`)
|
check(t, output, `COMPREPLY=( "hello" )`)
|
||||||
// check for required nouns
|
// check for required nouns
|
||||||
check(t, str, `must_have_one_noun+=("pod")`)
|
check(t, output, `must_have_one_noun+=("pod")`)
|
||||||
// check for noun aliases
|
// check for noun aliases
|
||||||
check(t, str, `noun_aliases+=("pods")`)
|
check(t, output, `noun_aliases+=("pods")`)
|
||||||
check(t, str, `noun_aliases+=("rc")`)
|
check(t, output, `noun_aliases+=("rc")`)
|
||||||
checkOmit(t, str, `must_have_one_noun+=("pods")`)
|
checkOmit(t, output, `must_have_one_noun+=("pods")`)
|
||||||
// check for filename extension flags
|
// check for filename extension flags
|
||||||
check(t, str, `flags_completion+=("_filedir")`)
|
check(t, output, `flags_completion+=("_filedir")`)
|
||||||
// check for filename extension flags
|
// check for filename extension flags
|
||||||
check(t, str, `must_have_one_noun+=("three")`)
|
check(t, output, `must_have_one_noun+=("three")`)
|
||||||
// check for filename extension flags
|
// check for filename extension flags
|
||||||
check(t, str, `flags_completion+=("__handle_filename_extension_flag json|yaml|yml")`)
|
check(t, output, `flags_completion+=("__handle_filename_extension_flag json|yaml|yml")`)
|
||||||
// check for custom flags
|
// check for custom flags
|
||||||
check(t, str, `flags_completion+=("__complete_custom")`)
|
check(t, output, `flags_completion+=("__complete_custom")`)
|
||||||
// check for subdirs_in_dir flags
|
// check for subdirs_in_dir flags
|
||||||
check(t, str, `flags_completion+=("__handle_subdirs_in_dir_flag themes")`)
|
check(t, output, `flags_completion+=("__handle_subdirs_in_dir_flag themes")`)
|
||||||
|
|
||||||
checkOmit(t, str, cmdDeprecated.Name())
|
checkOmit(t, output, deprecatedCmd.Name())
|
||||||
|
|
||||||
// if available, run shellcheck against the script
|
// If available, run shellcheck against the script.
|
||||||
if err := exec.Command("which", "shellcheck").Run(); err != nil {
|
if err := exec.Command("which", "shellcheck").Run(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := runShellCheck(str)
|
if err := runShellCheck(output); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("shellcheck failed: %v", err)
|
t.Fatalf("shellcheck failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBashCompletionHiddenFlag(t *testing.T) {
|
func TestBashCompletionHiddenFlag(t *testing.T) {
|
||||||
var cmdTrue = &Command{
|
c := &Command{Use: "c", Run: emptyRun}
|
||||||
Use: "does nothing",
|
|
||||||
Run: func(cmd *Command, args []string) {},
|
|
||||||
}
|
|
||||||
|
|
||||||
const flagName = "hidden-foo-bar-baz"
|
const flagName = "hiddenFlag"
|
||||||
|
c.Flags().Bool(flagName, false, "")
|
||||||
|
c.Flags().MarkHidden(flagName)
|
||||||
|
|
||||||
var flagValue bool
|
buf := new(bytes.Buffer)
|
||||||
cmdTrue.Flags().BoolVar(&flagValue, flagName, false, "hidden flag")
|
c.GenBashCompletion(buf)
|
||||||
cmdTrue.Flags().MarkHidden(flagName)
|
output := buf.String()
|
||||||
|
|
||||||
out := new(bytes.Buffer)
|
if strings.Contains(output, flagName) {
|
||||||
cmdTrue.GenBashCompletion(out)
|
t.Errorf("Expected completion to not include %q flag: Got %v", flagName, output)
|
||||||
bashCompletion := out.String()
|
|
||||||
if strings.Contains(bashCompletion, flagName) {
|
|
||||||
t.Errorf("expected completion to not include %q flag: Got %v", flagName, bashCompletion)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBashCompletionDeprecatedFlag(t *testing.T) {
|
func TestBashCompletionDeprecatedFlag(t *testing.T) {
|
||||||
var cmdTrue = &Command{
|
c := &Command{Use: "c", Run: emptyRun}
|
||||||
Use: "does nothing",
|
|
||||||
Run: func(cmd *Command, args []string) {},
|
|
||||||
}
|
|
||||||
|
|
||||||
const flagName = "deprecated-foo-bar-baz"
|
const flagName = "deprecated-flag"
|
||||||
|
c.Flags().Bool(flagName, false, "")
|
||||||
var flagValue bool
|
c.Flags().MarkDeprecated(flagName, "use --not-deprecated instead")
|
||||||
cmdTrue.Flags().BoolVar(&flagValue, flagName, false, "hidden flag")
|
|
||||||
cmdTrue.Flags().MarkDeprecated(flagName, "use --does-not-exist instead")
|
|
||||||
|
|
||||||
out := new(bytes.Buffer)
|
|
||||||
cmdTrue.GenBashCompletion(out)
|
|
||||||
bashCompletion := out.String()
|
|
||||||
if strings.Contains(bashCompletion, flagName) {
|
|
||||||
t.Errorf("expected completion to not include %q flag: Got %v", flagName, bashCompletion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkBashCompletion(b *testing.B) {
|
|
||||||
c := initializeWithRootCmd()
|
|
||||||
cmdEcho.AddCommand(cmdTimes)
|
|
||||||
c.AddCommand(cmdEcho, cmdPrint, cmdDeprecated, cmdColon)
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
c.GenBashCompletion(buf)
|
||||||
|
output := buf.String()
|
||||||
|
|
||||||
b.ResetTimer()
|
if strings.Contains(output, flagName) {
|
||||||
for i := 0; i < b.N; i++ {
|
t.Errorf("expected completion to not include %q flag: Got %v", flagName, output)
|
||||||
buf.Reset()
|
|
||||||
if err := c.GenBashCompletion(buf); err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
9
cobra.go
9
cobra.go
|
@ -188,3 +188,12 @@ func ld(s, t string, ignoreCase bool) int {
|
||||||
}
|
}
|
||||||
return d[len(s)][len(t)]
|
return d[len(s)][len(t)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stringInSlice(a string, list []string) bool {
|
||||||
|
for _, b := range list {
|
||||||
|
if b == a {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
1298
cobra_test.go
1298
cobra_test.go
File diff suppressed because it is too large
Load Diff
|
@ -621,10 +621,8 @@ func (c *Command) Root() *Command {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArgsLenAtDash will return the length of f.Args at the moment when a -- was
|
// ArgsLenAtDash will return the length of c.Flags().Args at the moment
|
||||||
// found during arg parsing. This allows your program to know which args were
|
// when a -- was found during args parsing.
|
||||||
// before the -- and which came after. (Description from
|
|
||||||
// https://godoc.org/github.com/spf13/pflag#FlagSet.ArgsLenAtDash).
|
|
||||||
func (c *Command) ArgsLenAtDash() int {
|
func (c *Command) ArgsLenAtDash() int {
|
||||||
return c.Flags().ArgsLenAtDash()
|
return c.Flags().ArgsLenAtDash()
|
||||||
}
|
}
|
||||||
|
|
1605
command_test.go
1605
command_test.go
File diff suppressed because it is too large
Load Diff
|
@ -77,10 +77,11 @@ func TestZshCompletion(t *testing.T) {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
tc.root.GenZshCompletion(buf)
|
tc.root.GenZshCompletion(buf)
|
||||||
completion := buf.String()
|
output := buf.String()
|
||||||
|
|
||||||
for _, expectedExpression := range tc.expectedExpressions {
|
for _, expectedExpression := range tc.expectedExpressions {
|
||||||
if !strings.Contains(completion, expectedExpression) {
|
if !strings.Contains(output, expectedExpression) {
|
||||||
t.Errorf("expected completion to contain '%v' somewhere; got '%v'", expectedExpression, completion)
|
t.Errorf("Expected completion to contain %q somewhere; got %q", expectedExpression, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue