summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/spf13/cobra/command_test.go
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2017-11-13 09:09:58 -0800
committerGitHub <noreply@github.com>2017-11-13 09:09:58 -0800
commit1329aa51b605cb54ba9aae3a82a0a87b881fb7b3 (patch)
tree93cbf354ab894a560fc2cef8ef685d681b4ff889 /vendor/github.com/spf13/cobra/command_test.go
parent7304a61ef597970be3031b14e652fb3a4df44304 (diff)
downloadchat-1329aa51b605cb54ba9aae3a82a0a87b881fb7b3.tar.gz
chat-1329aa51b605cb54ba9aae3a82a0a87b881fb7b3.tar.bz2
chat-1329aa51b605cb54ba9aae3a82a0a87b881fb7b3.zip
Updating server dependancies. (#7816)
Diffstat (limited to 'vendor/github.com/spf13/cobra/command_test.go')
-rw-r--r--vendor/github.com/spf13/cobra/command_test.go1473
1 files changed, 1316 insertions, 157 deletions
diff --git a/vendor/github.com/spf13/cobra/command_test.go b/vendor/github.com/spf13/cobra/command_test.go
index aa6658f85..edffc1501 100644
--- a/vendor/github.com/spf13/cobra/command_test.go
+++ b/vendor/github.com/spf13/cobra/command_test.go
@@ -11,27 +11,450 @@ import (
"github.com/spf13/pflag"
)
-// test to ensure hidden commands run as intended
-func TestHiddenCommandExecutes(t *testing.T) {
+func emptyRun(*Command, []string) {}
+
+func executeCommand(root *Command, args ...string) (output string, err error) {
+ _, output, err = executeCommandC(root, args...)
+ return output, err
+}
+
+func executeCommandC(root *Command, args ...string) (c *Command, output string, err error) {
+ buf := new(bytes.Buffer)
+ root.SetOutput(buf)
+ root.SetArgs(args)
+
+ c, err = root.ExecuteC()
+
+ return c, buf.String(), err
+}
+
+func resetCommandLineFlagSet() {
+ pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
+}
+
+func checkStringContains(t *testing.T, got, expected string) {
+ if !strings.Contains(got, expected) {
+ t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expected, got)
+ }
+}
+
+func checkStringOmits(t *testing.T, got, expected string) {
+ if strings.Contains(got, expected) {
+ t.Errorf("Expected to not contain: \n %v\nGot: %v", expected, got)
+ }
+}
- // ensure that outs does not already equal what the command will be setting it
- // to, if it did this test would not actually be testing anything...
- if outs == "hidden" {
- t.Errorf("outs should NOT EQUAL hidden")
+func TestSingleCommand(t *testing.T) {
+ var rootCmdArgs []string
+ rootCmd := &Command{
+ Use: "root",
+ Args: ExactArgs(2),
+ Run: func(_ *Command, args []string) { rootCmdArgs = args },
}
+ aCmd := &Command{Use: "a", Args: NoArgs, Run: emptyRun}
+ bCmd := &Command{Use: "b", Args: NoArgs, Run: emptyRun}
+ rootCmd.AddCommand(aCmd, bCmd)
- cmdHidden.Execute()
+ output, err := executeCommand(rootCmd, "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
- // upon running the command, the value of outs should now be 'hidden'
- if outs != "hidden" {
- t.Errorf("Hidden command failed to run!")
+ got := strings.Join(rootCmdArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("rootCmdArgs expected: %q, got: %q", expected, got)
}
}
-// test to ensure hidden commands do not show up in usage/help text
-func TestHiddenCommandIsHidden(t *testing.T) {
- if cmdHidden.IsAvailableCommand() {
- t.Errorf("Hidden command found!")
+func TestChildCommand(t *testing.T) {
+ var child1CmdArgs []string
+ rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
+ child1Cmd := &Command{
+ Use: "child1",
+ Args: ExactArgs(2),
+ Run: func(_ *Command, args []string) { child1CmdArgs = args },
+ }
+ child2Cmd := &Command{Use: "child2", Args: NoArgs, Run: emptyRun}
+ rootCmd.AddCommand(child1Cmd, child2Cmd)
+
+ output, err := executeCommand(rootCmd, "child1", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ got := strings.Join(child1CmdArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("child1CmdArgs expected: %q, got: %q", expected, got)
+ }
+}
+
+func TestCallCommandWithoutSubcommands(t *testing.T) {
+ rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
+ _, err := executeCommand(rootCmd)
+ if err != nil {
+ t.Errorf("Calling command without subcommands should not have error: %v", err)
+ }
+}
+
+func TestRootExecuteUnknownCommand(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
+
+ output, _ := executeCommand(rootCmd, "unknown")
+
+ expected := "Error: unknown command \"unknown\" for \"root\"\nRun 'root --help' for usage.\n"
+
+ if output != expected {
+ t.Errorf("Expected:\n %q\nGot:\n %q\n", expected, output)
+ }
+}
+
+func TestSubcommandExecuteC(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ childCmd := &Command{Use: "child", Run: emptyRun}
+ rootCmd.AddCommand(childCmd)
+
+ c, output, err := executeCommandC(rootCmd, "child")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if c.Name() != "child" {
+ t.Errorf(`invalid command returned from ExecuteC: expected "child"', got %q`, c.Name())
+ }
+}
+
+func TestRootUnknownCommandSilenced(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ rootCmd.SilenceErrors = true
+ rootCmd.SilenceUsage = true
+ rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
+
+ output, _ := executeCommand(rootCmd, "unknown")
+ if output != "" {
+ t.Errorf("Expected blank output, because of silenced usage.\nGot:\n %q\n", output)
+ }
+}
+
+func TestCommandAlias(t *testing.T) {
+ var timesCmdArgs []string
+ rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
+ echoCmd := &Command{
+ Use: "echo",
+ Aliases: []string{"say", "tell"},
+ Args: NoArgs,
+ Run: emptyRun,
+ }
+ timesCmd := &Command{
+ Use: "times",
+ Args: ExactArgs(2),
+ Run: func(_ *Command, args []string) { timesCmdArgs = args },
+ }
+ echoCmd.AddCommand(timesCmd)
+ rootCmd.AddCommand(echoCmd)
+
+ output, err := executeCommand(rootCmd, "tell", "times", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ got := strings.Join(timesCmdArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got)
+ }
+}
+
+func TestEnablePrefixMatching(t *testing.T) {
+ EnablePrefixMatching = true
+
+ var aCmdArgs []string
+ rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
+ aCmd := &Command{
+ Use: "aCmd",
+ Args: ExactArgs(2),
+ Run: func(_ *Command, args []string) { aCmdArgs = args },
+ }
+ bCmd := &Command{Use: "bCmd", Args: NoArgs, Run: emptyRun}
+ rootCmd.AddCommand(aCmd, bCmd)
+
+ output, err := executeCommand(rootCmd, "a", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ got := strings.Join(aCmdArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("aCmdArgs expected: %q, got: %q", expected, got)
+ }
+
+ EnablePrefixMatching = false
+}
+
+func TestAliasPrefixMatching(t *testing.T) {
+ EnablePrefixMatching = true
+
+ var timesCmdArgs []string
+ rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
+ echoCmd := &Command{
+ Use: "echo",
+ Aliases: []string{"say", "tell"},
+ Args: NoArgs,
+ Run: emptyRun,
+ }
+ timesCmd := &Command{
+ Use: "times",
+ Args: ExactArgs(2),
+ Run: func(_ *Command, args []string) { timesCmdArgs = args },
+ }
+ echoCmd.AddCommand(timesCmd)
+ rootCmd.AddCommand(echoCmd)
+
+ output, err := executeCommand(rootCmd, "sa", "times", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ got := strings.Join(timesCmdArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got)
+ }
+
+ EnablePrefixMatching = false
+}
+
+// TestChildSameName checks the correct behaviour of cobra in cases,
+// when an application with name "foo" and with subcommand "foo"
+// is executed with args "foo foo".
+func TestChildSameName(t *testing.T) {
+ var fooCmdArgs []string
+ rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun}
+ fooCmd := &Command{
+ Use: "foo",
+ Args: ExactArgs(2),
+ Run: func(_ *Command, args []string) { fooCmdArgs = args },
+ }
+ barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun}
+ rootCmd.AddCommand(fooCmd, barCmd)
+
+ output, err := executeCommand(rootCmd, "foo", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ got := strings.Join(fooCmdArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got)
+ }
+}
+
+// TestGrandChildSameName checks the correct behaviour of cobra in cases,
+// when user has a root command and a grand child
+// with the same name.
+func TestGrandChildSameName(t *testing.T) {
+ var fooCmdArgs []string
+ rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun}
+ barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun}
+ fooCmd := &Command{
+ Use: "foo",
+ Args: ExactArgs(2),
+ Run: func(_ *Command, args []string) { fooCmdArgs = args },
+ }
+ barCmd.AddCommand(fooCmd)
+ rootCmd.AddCommand(barCmd)
+
+ output, err := executeCommand(rootCmd, "bar", "foo", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ got := strings.Join(fooCmdArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got)
+ }
+}
+
+func TestFlagLong(t *testing.T) {
+ var cArgs []string
+ c := &Command{
+ Use: "c",
+ Args: ArbitraryArgs,
+ Run: func(_ *Command, args []string) { cArgs = args },
+ }
+
+ var intFlagValue int
+ var stringFlagValue string
+ c.Flags().IntVar(&intFlagValue, "intf", -1, "")
+ c.Flags().StringVar(&stringFlagValue, "sf", "", "")
+
+ output, err := executeCommand(c, "--intf=7", "--sf=abc", "one", "--", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", err)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if c.ArgsLenAtDash() != 1 {
+ t.Errorf("Expected ArgsLenAtDash: %v but got %v", 1, c.ArgsLenAtDash())
+ }
+ if intFlagValue != 7 {
+ t.Errorf("Expected intFlagValue: %v, got %v", 7, intFlagValue)
+ }
+ if stringFlagValue != "abc" {
+ t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue)
+ }
+
+ got := strings.Join(cArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("Expected arguments: %q, got %q", expected, got)
+ }
+}
+
+func TestFlagShort(t *testing.T) {
+ var cArgs []string
+ c := &Command{
+ Use: "c",
+ Args: ArbitraryArgs,
+ Run: func(_ *Command, args []string) { cArgs = args },
+ }
+
+ var intFlagValue int
+ var stringFlagValue string
+ c.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
+ c.Flags().StringVarP(&stringFlagValue, "sf", "s", "", "")
+
+ output, err := executeCommand(c, "-i", "7", "-sabc", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", err)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if intFlagValue != 7 {
+ t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
+ }
+ if stringFlagValue != "abc" {
+ t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue)
+ }
+
+ got := strings.Join(cArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("Expected arguments: %q, got %q", expected, got)
+ }
+}
+
+func TestChildFlag(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ childCmd := &Command{Use: "child", Run: emptyRun}
+ rootCmd.AddCommand(childCmd)
+
+ var intFlagValue int
+ childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
+
+ output, err := executeCommand(rootCmd, "child", "-i7")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", err)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if intFlagValue != 7 {
+ t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
+ }
+}
+
+func TestChildFlagWithParentLocalFlag(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ childCmd := &Command{Use: "child", Run: emptyRun}
+ rootCmd.AddCommand(childCmd)
+
+ var intFlagValue int
+ rootCmd.Flags().StringP("sf", "s", "", "")
+ childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
+
+ _, err := executeCommand(rootCmd, "child", "-i7", "-sabc")
+ if err == nil {
+ t.Errorf("Invalid flag should generate error")
+ }
+
+ checkStringContains(t, err.Error(), "unknown shorthand")
+
+ if intFlagValue != 7 {
+ t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
+ }
+}
+
+func TestFlagInvalidInput(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ rootCmd.Flags().IntP("intf", "i", -1, "")
+
+ _, err := executeCommand(rootCmd, "-iabc")
+ if err == nil {
+ t.Errorf("Invalid flag value should generate error")
+ }
+
+ checkStringContains(t, err.Error(), "invalid syntax")
+}
+
+func TestFlagBeforeCommand(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ childCmd := &Command{Use: "child", Run: emptyRun}
+ rootCmd.AddCommand(childCmd)
+
+ var flagValue int
+ childCmd.Flags().IntVarP(&flagValue, "intf", "i", -1, "")
+
+ // With short flag.
+ _, err := executeCommand(rootCmd, "-i7", "child")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+ if flagValue != 7 {
+ t.Errorf("Expected flag value: %v, got %v", 7, flagValue)
+ }
+
+ // With long flag.
+ _, err = executeCommand(rootCmd, "--intf=8", "child")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+ if flagValue != 8 {
+ t.Errorf("Expected flag value: %v, got %v", 9, flagValue)
}
}
@@ -45,11 +468,11 @@ func TestStripFlags(t *testing.T) {
[]string{"foo", "bar"},
},
{
- []string{"foo", "--bar", "-b"},
+ []string{"foo", "--str", "-s"},
[]string{"foo"},
},
{
- []string{"-b", "foo", "--bar", "bar"},
+ []string{"-s", "foo", "--str", "bar"},
[]string{},
},
{
@@ -65,7 +488,7 @@ func TestStripFlags(t *testing.T) {
[]string{"echo"},
},
{
- []string{"-ib", "echo", "-bfoo", "baz"},
+ []string{"-ib", "echo", "-sfoo", "baz"},
[]string{"echo", "baz"},
},
{
@@ -73,15 +496,15 @@ func TestStripFlags(t *testing.T) {
[]string{"bar", "blah"},
},
{
- []string{"--int=baz", "-bbar", "-i", "foo", "blah"},
+ []string{"--int=baz", "-sbar", "-i", "foo", "blah"},
[]string{"blah"},
},
{
- []string{"--cat", "bar", "-i", "foo", "blah"},
+ []string{"--bool", "bar", "-i", "foo", "blah"},
[]string{"bar", "blah"},
},
{
- []string{"-c", "bar", "-i", "foo", "blah"},
+ []string{"-b", "bar", "-i", "foo", "blah"},
[]string{"bar", "blah"},
},
{
@@ -94,61 +517,757 @@ func TestStripFlags(t *testing.T) {
},
}
- cmdPrint := &Command{
- Use: "print [string to print]",
- Short: "Print anything to the screen",
- Long: `an utterly useless command for testing.`,
- Run: func(cmd *Command, args []string) {
- tp = args
- },
- }
-
- var flagi int
- var flagstr string
- var flagbool bool
- cmdPrint.PersistentFlags().BoolVarP(&flagbool, "persist", "p", false, "help for persistent one")
- cmdPrint.Flags().IntVarP(&flagi, "int", "i", 345, "help message for flag int")
- cmdPrint.Flags().StringVarP(&flagstr, "bar", "b", "bar", "help message for flag string")
- cmdPrint.Flags().BoolVarP(&flagbool, "cat", "c", false, "help message for flag bool")
+ c := &Command{Use: "c", Run: emptyRun}
+ c.PersistentFlags().BoolP("persist", "p", false, "")
+ c.Flags().IntP("int", "i", -1, "")
+ c.Flags().StringP("str", "s", "", "")
+ c.Flags().BoolP("bool", "b", false, "")
- for _, test := range tests {
- output := stripFlags(test.input, cmdPrint)
- if !reflect.DeepEqual(test.output, output) {
- t.Errorf("expected: %v, got: %v", test.output, output)
+ for i, test := range tests {
+ got := stripFlags(test.input, c)
+ if !reflect.DeepEqual(test.output, got) {
+ t.Errorf("(%v) Expected: %v, got: %v", i, test.output, got)
}
}
}
func TestDisableFlagParsing(t *testing.T) {
- targs := []string{}
- cmdPrint := &Command{
+ var cArgs []string
+ c := &Command{
+ Use: "c",
DisableFlagParsing: true,
- Run: func(cmd *Command, args []string) {
- targs = args
+ Run: func(_ *Command, args []string) {
+ cArgs = args
},
}
+
args := []string{"cmd", "-v", "-race", "-file", "foo.go"}
- cmdPrint.SetArgs(args)
- err := cmdPrint.Execute()
+ output, err := executeCommand(c, args...)
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if !reflect.DeepEqual(args, cArgs) {
+ t.Errorf("Expected: %v, got: %v", args, cArgs)
+ }
+}
+
+func TestPersistentFlagsOnSameCommand(t *testing.T) {
+ var rootCmdArgs []string
+ rootCmd := &Command{
+ Use: "root",
+ Args: ArbitraryArgs,
+ Run: func(_ *Command, args []string) { rootCmdArgs = args },
+ }
+
+ var flagValue int
+ rootCmd.PersistentFlags().IntVarP(&flagValue, "intf", "i", -1, "")
+
+ output, err := executeCommand(rootCmd, "-i7", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
if err != nil {
- t.Error(err)
+ t.Errorf("Unexpected error: %v", err)
}
- if !reflect.DeepEqual(args, targs) {
- t.Errorf("expected: %v, got: %v", args, targs)
+
+ got := strings.Join(rootCmdArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("rootCmdArgs expected: %q, got %q", expected, got)
+ }
+ if flagValue != 7 {
+ t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
+ }
+}
+
+// TestEmptyInputs checks,
+// if flags correctly parsed with blank strings in args.
+func TestEmptyInputs(t *testing.T) {
+ c := &Command{Use: "c", Run: emptyRun}
+
+ var flagValue int
+ c.Flags().IntVarP(&flagValue, "intf", "i", -1, "")
+
+ output, err := executeCommand(c, "", "-i7", "")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if flagValue != 7 {
+ t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
+ }
+}
+
+func TestOverwrittenFlag(t *testing.T) {
+ // TODO: This test fails, but should work.
+ t.Skip()
+
+ parent := &Command{Use: "parent", Run: emptyRun}
+ child := &Command{Use: "child", Run: emptyRun}
+
+ parent.PersistentFlags().Bool("boolf", false, "")
+ parent.PersistentFlags().Int("intf", -1, "")
+ child.Flags().String("strf", "", "")
+ child.Flags().Int("intf", -1, "")
+
+ parent.AddCommand(child)
+
+ childInherited := child.InheritedFlags()
+ childLocal := child.LocalFlags()
+
+ if childLocal.Lookup("strf") == nil {
+ t.Error(`LocalFlags expected to contain "strf", got "nil"`)
+ }
+ if childInherited.Lookup("boolf") == nil {
+ t.Error(`InheritedFlags expected to contain "boolf", got "nil"`)
+ }
+
+ if childInherited.Lookup("intf") != nil {
+ t.Errorf(`InheritedFlags should not contain overwritten flag "intf"`)
+ }
+ if childLocal.Lookup("intf") == nil {
+ t.Error(`LocalFlags expected to contain "intf", got "nil"`)
+ }
+}
+
+func TestPersistentFlagsOnChild(t *testing.T) {
+ var childCmdArgs []string
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ childCmd := &Command{
+ Use: "child",
+ Args: ArbitraryArgs,
+ Run: func(_ *Command, args []string) { childCmdArgs = args },
+ }
+ rootCmd.AddCommand(childCmd)
+
+ var parentFlagValue int
+ var childFlagValue int
+ rootCmd.PersistentFlags().IntVarP(&parentFlagValue, "parentf", "p", -1, "")
+ childCmd.Flags().IntVarP(&childFlagValue, "childf", "c", -1, "")
+
+ output, err := executeCommand(rootCmd, "child", "-c7", "-p8", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ got := strings.Join(childCmdArgs, " ")
+ expected := "one two"
+ if got != expected {
+ t.Errorf("childCmdArgs expected: %q, got %q", expected, got)
+ }
+ if parentFlagValue != 8 {
+ t.Errorf("parentFlagValue expected: %v, got %v", 8, parentFlagValue)
+ }
+ if childFlagValue != 7 {
+ t.Errorf("childFlagValue expected: %v, got %v", 7, childFlagValue)
+ }
+}
+
+func TestRequiredFlags(t *testing.T) {
+ c := &Command{Use: "c", Run: emptyRun}
+ c.Flags().String("foo1", "", "")
+ c.MarkFlagRequired("foo1")
+ c.Flags().String("foo2", "", "")
+ c.MarkFlagRequired("foo2")
+ c.Flags().String("bar", "", "")
+
+ expected := fmt.Sprintf("Required flag(s) %q, %q have/has not been set", "foo1", "foo2")
+
+ _, err := executeCommand(c)
+ got := err.Error()
+
+ if got != expected {
+ t.Errorf("Expected error: %q, got: %q", expected, got)
+ }
+}
+
+func TestPersistentRequiredFlags(t *testing.T) {
+ parent := &Command{Use: "parent", Run: emptyRun}
+ parent.PersistentFlags().String("foo1", "", "")
+ parent.MarkPersistentFlagRequired("foo1")
+ parent.PersistentFlags().String("foo2", "", "")
+ parent.MarkPersistentFlagRequired("foo2")
+ parent.Flags().String("foo3", "", "")
+
+ child := &Command{Use: "child", Run: emptyRun}
+ child.Flags().String("bar1", "", "")
+ child.MarkFlagRequired("bar1")
+ child.Flags().String("bar2", "", "")
+ child.MarkFlagRequired("bar2")
+ child.Flags().String("bar3", "", "")
+
+ parent.AddCommand(child)
+
+ expected := fmt.Sprintf("Required flag(s) %q, %q, %q, %q have/has not been set", "bar1", "bar2", "foo1", "foo2")
+
+ _, err := executeCommand(parent, "child")
+ if err.Error() != expected {
+ t.Errorf("Expected %q, got %q", expected, err.Error())
}
}
func TestInitHelpFlagMergesFlags(t *testing.T) {
usage := "custom flag"
- baseCmd := Command{Use: "testcmd"}
- baseCmd.PersistentFlags().Bool("help", false, usage)
- cmd := Command{Use: "do"}
- baseCmd.AddCommand(&cmd)
+ rootCmd := &Command{Use: "root"}
+ rootCmd.PersistentFlags().Bool("help", false, "custom flag")
+ childCmd := &Command{Use: "child"}
+ rootCmd.AddCommand(childCmd)
+
+ childCmd.InitDefaultHelpFlag()
+ got := childCmd.Flags().Lookup("help").Usage
+ if got != usage {
+ t.Errorf("Expected the help flag from the root command with usage: %v\nGot the default with usage: %v", usage, got)
+ }
+}
+
+func TestHelpCommandExecuted(t *testing.T) {
+ rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
+ rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
+
+ output, err := executeCommand(rootCmd, "help")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, rootCmd.Long)
+}
- cmd.InitDefaultHelpFlag()
- actual := cmd.Flags().Lookup("help").Usage
- if actual != usage {
- t.Fatalf("Expected the help flag from the base command with usage '%s', but got the default with usage '%s'", usage, actual)
+func TestHelpCommandExecutedOnChild(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun}
+ rootCmd.AddCommand(childCmd)
+
+ output, err := executeCommand(rootCmd, "help", "child")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, childCmd.Long)
+}
+
+func TestSetHelpCommand(t *testing.T) {
+ c := &Command{Use: "c", Run: emptyRun}
+ c.AddCommand(&Command{Use: "empty", Run: emptyRun})
+
+ expected := "WORKS"
+ c.SetHelpCommand(&Command{
+ Use: "help [command]",
+ Short: "Help about any command",
+ Long: `Help provides help for any command in the application.
+ Simply type ` + c.Name() + ` help [path to command] for full details.`,
+ Run: func(c *Command, _ []string) { c.Print(expected) },
+ })
+
+ got, err := executeCommand(c, "help")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if got != expected {
+ t.Errorf("Expected to contain %q, got %q", expected, got)
+ }
+}
+
+func TestHelpFlagExecuted(t *testing.T) {
+ rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
+
+ output, err := executeCommand(rootCmd, "--help")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, rootCmd.Long)
+}
+
+func TestHelpFlagExecutedOnChild(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun}
+ rootCmd.AddCommand(childCmd)
+
+ output, err := executeCommand(rootCmd, "child", "--help")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, childCmd.Long)
+}
+
+// TestHelpFlagInHelp checks,
+// if '--help' flag is shown in help for child (executing `parent help child`),
+// that has no other flags.
+// Related to https://github.com/spf13/cobra/issues/302.
+func TestHelpFlagInHelp(t *testing.T) {
+ parentCmd := &Command{Use: "parent", Run: func(*Command, []string) {}}
+
+ childCmd := &Command{Use: "child", Run: func(*Command, []string) {}}
+ parentCmd.AddCommand(childCmd)
+
+ output, err := executeCommand(parentCmd, "help", "child")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, "[flags]")
+}
+
+func TestFlagsInUsage(t *testing.T) {
+ rootCmd := &Command{Use: "root", Args: NoArgs, Run: func(*Command, []string) {}}
+ output, err := executeCommand(rootCmd, "--help")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, "[flags]")
+}
+
+func TestHelpExecutedOnNonRunnableChild(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ childCmd := &Command{Use: "child", Long: "Long description"}
+ rootCmd.AddCommand(childCmd)
+
+ output, err := executeCommand(rootCmd, "child")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, childCmd.Long)
+}
+
+func TestUsageIsNotPrintedTwice(t *testing.T) {
+ var cmd = &Command{Use: "root"}
+ var sub = &Command{Use: "sub"}
+ cmd.AddCommand(sub)
+
+ output, _ := executeCommand(cmd, "")
+ if strings.Count(output, "Usage:") != 1 {
+ t.Error("Usage output is not printed exactly once")
+ }
+}
+
+func TestVisitParents(t *testing.T) {
+ c := &Command{Use: "app"}
+ sub := &Command{Use: "sub"}
+ dsub := &Command{Use: "dsub"}
+ sub.AddCommand(dsub)
+ c.AddCommand(sub)
+
+ total := 0
+ add := func(x *Command) {
+ total++
+ }
+ sub.VisitParents(add)
+ if total != 1 {
+ t.Errorf("Should have visited 1 parent but visited %d", total)
+ }
+
+ total = 0
+ dsub.VisitParents(add)
+ if total != 2 {
+ t.Errorf("Should have visited 2 parents but visited %d", total)
+ }
+
+ total = 0
+ c.VisitParents(add)
+ if total != 0 {
+ t.Errorf("Should have visited no parents but visited %d", total)
+ }
+}
+
+func TestSuggestions(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ timesCmd := &Command{
+ Use: "times",
+ SuggestFor: []string{"counts"},
+ Run: emptyRun,
+ }
+ rootCmd.AddCommand(timesCmd)
+
+ templateWithSuggestions := "Error: unknown command \"%s\" for \"root\"\n\nDid you mean this?\n\t%s\n\nRun 'root --help' for usage.\n"
+ templateWithoutSuggestions := "Error: unknown command \"%s\" for \"root\"\nRun 'root --help' for usage.\n"
+
+ tests := map[string]string{
+ "time": "times",
+ "tiems": "times",
+ "tims": "times",
+ "timeS": "times",
+ "rimes": "times",
+ "ti": "times",
+ "t": "times",
+ "timely": "times",
+ "ri": "",
+ "timezone": "",
+ "foo": "",
+ "counts": "times",
+ }
+
+ for typo, suggestion := range tests {
+ for _, suggestionsDisabled := range []bool{true, false} {
+ rootCmd.DisableSuggestions = suggestionsDisabled
+
+ var expected string
+ output, _ := executeCommand(rootCmd, typo)
+
+ if suggestion == "" || suggestionsDisabled {
+ expected = fmt.Sprintf(templateWithoutSuggestions, typo)
+ } else {
+ expected = fmt.Sprintf(templateWithSuggestions, typo, suggestion)
+ }
+
+ if output != expected {
+ t.Errorf("Unexpected response.\nExpected:\n %q\nGot:\n %q\n", expected, output)
+ }
+ }
+ }
+}
+
+func TestRemoveCommand(t *testing.T) {
+ rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
+ childCmd := &Command{Use: "child", Run: emptyRun}
+ rootCmd.AddCommand(childCmd)
+ rootCmd.RemoveCommand(childCmd)
+
+ _, err := executeCommand(rootCmd, "child")
+ if err == nil {
+ t.Error("Expected error on calling removed command. Got nil.")
+ }
+}
+
+func TestReplaceCommandWithRemove(t *testing.T) {
+ childUsed := 0
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ child1Cmd := &Command{
+ Use: "child",
+ Run: func(*Command, []string) { childUsed = 1 },
+ }
+ child2Cmd := &Command{
+ Use: "child",
+ Run: func(*Command, []string) { childUsed = 2 },
+ }
+ rootCmd.AddCommand(child1Cmd)
+ rootCmd.RemoveCommand(child1Cmd)
+ rootCmd.AddCommand(child2Cmd)
+
+ output, err := executeCommand(rootCmd, "child")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if childUsed == 1 {
+ t.Error("Removed command shouldn't be called")
+ }
+ if childUsed != 2 {
+ t.Error("Replacing command should have been called but didn't")
+ }
+}
+
+func TestDeprecatedCommand(t *testing.T) {
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ deprecatedCmd := &Command{
+ Use: "deprecated",
+ Deprecated: "This command is deprecated",
+ Run: emptyRun,
+ }
+ rootCmd.AddCommand(deprecatedCmd)
+
+ output, err := executeCommand(rootCmd, "deprecated")
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ checkStringContains(t, output, deprecatedCmd.Deprecated)
+}
+
+func TestHooks(t *testing.T) {
+ var (
+ persPreArgs string
+ preArgs string
+ runArgs string
+ postArgs string
+ persPostArgs string
+ )
+
+ c := &Command{
+ Use: "c",
+ PersistentPreRun: func(_ *Command, args []string) {
+ persPreArgs = strings.Join(args, " ")
+ },
+ PreRun: func(_ *Command, args []string) {
+ preArgs = strings.Join(args, " ")
+ },
+ Run: func(_ *Command, args []string) {
+ runArgs = strings.Join(args, " ")
+ },
+ PostRun: func(_ *Command, args []string) {
+ postArgs = strings.Join(args, " ")
+ },
+ PersistentPostRun: func(_ *Command, args []string) {
+ persPostArgs = strings.Join(args, " ")
+ },
+ }
+
+ output, err := executeCommand(c, "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if persPreArgs != "one two" {
+ t.Errorf("Expected persPreArgs %q, got %q", "one two", persPreArgs)
+ }
+ if preArgs != "one two" {
+ t.Errorf("Expected preArgs %q, got %q", "one two", preArgs)
+ }
+ if runArgs != "one two" {
+ t.Errorf("Expected runArgs %q, got %q", "one two", runArgs)
+ }
+ if postArgs != "one two" {
+ t.Errorf("Expected postArgs %q, got %q", "one two", postArgs)
+ }
+ if persPostArgs != "one two" {
+ t.Errorf("Expected persPostArgs %q, got %q", "one two", persPostArgs)
+ }
+}
+
+func TestPersistentHooks(t *testing.T) {
+ var (
+ parentPersPreArgs string
+ parentPreArgs string
+ parentRunArgs string
+ parentPostArgs string
+ parentPersPostArgs string
+ )
+
+ var (
+ childPersPreArgs string
+ childPreArgs string
+ childRunArgs string
+ childPostArgs string
+ childPersPostArgs string
+ )
+
+ parentCmd := &Command{
+ Use: "parent",
+ PersistentPreRun: func(_ *Command, args []string) {
+ parentPersPreArgs = strings.Join(args, " ")
+ },
+ PreRun: func(_ *Command, args []string) {
+ parentPreArgs = strings.Join(args, " ")
+ },
+ Run: func(_ *Command, args []string) {
+ parentRunArgs = strings.Join(args, " ")
+ },
+ PostRun: func(_ *Command, args []string) {
+ parentPostArgs = strings.Join(args, " ")
+ },
+ PersistentPostRun: func(_ *Command, args []string) {
+ parentPersPostArgs = strings.Join(args, " ")
+ },
+ }
+
+ childCmd := &Command{
+ Use: "child",
+ PersistentPreRun: func(_ *Command, args []string) {
+ childPersPreArgs = strings.Join(args, " ")
+ },
+ PreRun: func(_ *Command, args []string) {
+ childPreArgs = strings.Join(args, " ")
+ },
+ Run: func(_ *Command, args []string) {
+ childRunArgs = strings.Join(args, " ")
+ },
+ PostRun: func(_ *Command, args []string) {
+ childPostArgs = strings.Join(args, " ")
+ },
+ PersistentPostRun: func(_ *Command, args []string) {
+ childPersPostArgs = strings.Join(args, " ")
+ },
+ }
+ parentCmd.AddCommand(childCmd)
+
+ output, err := executeCommand(parentCmd, "child", "one", "two")
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ // TODO: This test fails, but should not.
+ // Related to https://github.com/spf13/cobra/issues/252.
+ //
+ // if parentPersPreArgs != "one two" {
+ // t.Errorf("Expected parentPersPreArgs %q, got %q", "one two", parentPersPreArgs)
+ // }
+ if parentPreArgs != "" {
+ t.Errorf("Expected blank parentPreArgs, got %q", parentPreArgs)
+ }
+ if parentRunArgs != "" {
+ t.Errorf("Expected blank parentRunArgs, got %q", parentRunArgs)
+ }
+ if parentPostArgs != "" {
+ t.Errorf("Expected blank parentPostArgs, got %q", parentPostArgs)
+ }
+ // TODO: This test fails, but should not.
+ // Related to https://github.com/spf13/cobra/issues/252.
+ //
+ // if parentPersPostArgs != "one two" {
+ // t.Errorf("Expected parentPersPostArgs %q, got %q", "one two", parentPersPostArgs)
+ // }
+
+ if childPersPreArgs != "one two" {
+ t.Errorf("Expected childPersPreArgs %q, got %q", "one two", childPersPreArgs)
+ }
+ if childPreArgs != "one two" {
+ t.Errorf("Expected childPreArgs %q, got %q", "one two", childPreArgs)
+ }
+ if childRunArgs != "one two" {
+ t.Errorf("Expected childRunArgs %q, got %q", "one two", childRunArgs)
+ }
+ if childPostArgs != "one two" {
+ t.Errorf("Expected childPostArgs %q, got %q", "one two", childPostArgs)
+ }
+ if childPersPostArgs != "one two" {
+ t.Errorf("Expected childPersPostArgs %q, got %q", "one two", childPersPostArgs)
+ }
+}
+
+// Related to https://github.com/spf13/cobra/issues/521.
+func TestGlobalNormFuncPropagation(t *testing.T) {
+ normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
+ return pflag.NormalizedName(name)
+ }
+
+ rootCmd := &Command{Use: "root", Run: emptyRun}
+ childCmd := &Command{Use: "child", Run: emptyRun}
+ rootCmd.AddCommand(childCmd)
+
+ rootCmd.SetGlobalNormalizationFunc(normFunc)
+ if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() {
+ t.Error("rootCmd seems to have a wrong normalization function")
+ }
+
+ if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(childCmd.GlobalNormalizationFunc()).Pointer() {
+ t.Error("childCmd should have had the normalization function of rootCmd")
+ }
+}
+
+// Related to https://github.com/spf13/cobra/issues/521.
+func TestNormPassedOnLocal(t *testing.T) {
+ toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
+ return pflag.NormalizedName(strings.ToUpper(name))
+ }
+
+ c := &Command{}
+ c.Flags().Bool("flagname", true, "this is a dummy flag")
+ c.SetGlobalNormalizationFunc(toUpper)
+ if c.LocalFlags().Lookup("flagname") != c.LocalFlags().Lookup("FLAGNAME") {
+ t.Error("Normalization function should be passed on to Local flag set")
+ }
+}
+
+// Related to https://github.com/spf13/cobra/issues/521.
+func TestNormPassedOnInherited(t *testing.T) {
+ toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
+ return pflag.NormalizedName(strings.ToUpper(name))
+ }
+
+ c := &Command{}
+ c.SetGlobalNormalizationFunc(toUpper)
+
+ child1 := &Command{}
+ c.AddCommand(child1)
+
+ c.PersistentFlags().Bool("flagname", true, "")
+
+ child2 := &Command{}
+ c.AddCommand(child2)
+
+ inherited := child1.InheritedFlags()
+ if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") {
+ t.Error("Normalization function should be passed on to inherited flag set in command added before flag")
+ }
+
+ inherited = child2.InheritedFlags()
+ if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") {
+ t.Error("Normalization function should be passed on to inherited flag set in command added after flag")
+ }
+}
+
+// Related to https://github.com/spf13/cobra/issues/521.
+func TestConsistentNormalizedName(t *testing.T) {
+ toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
+ return pflag.NormalizedName(strings.ToUpper(name))
+ }
+ n := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
+ return pflag.NormalizedName(name)
+ }
+
+ c := &Command{}
+ c.Flags().Bool("flagname", true, "")
+ c.SetGlobalNormalizationFunc(toUpper)
+ c.SetGlobalNormalizationFunc(n)
+
+ if c.LocalFlags().Lookup("flagname") == c.LocalFlags().Lookup("FLAGNAME") {
+ t.Error("Normalizing flag names should not result in duplicate flags")
+ }
+}
+
+func TestFlagOnPflagCommandLine(t *testing.T) {
+ flagName := "flagOnCommandLine"
+ pflag.String(flagName, "", "about my flag")
+
+ c := &Command{Use: "c", Run: emptyRun}
+ c.AddCommand(&Command{Use: "child", Run: emptyRun})
+
+ output, _ := executeCommand(c, "--help")
+ checkStringContains(t, output, flagName)
+
+ resetCommandLineFlagSet()
+}
+
+// TestHiddenCommandExecutes checks,
+// if hidden commands run as intended.
+func TestHiddenCommandExecutes(t *testing.T) {
+ executed := false
+ c := &Command{
+ Use: "c",
+ Hidden: true,
+ Run: func(*Command, []string) { executed = true },
+ }
+
+ output, err := executeCommand(c)
+ if output != "" {
+ t.Errorf("Unexpected output: %v", output)
+ }
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+
+ if !executed {
+ t.Error("Hidden command should have been executed")
+ }
+}
+
+// test to ensure hidden commands do not show up in usage/help text
+func TestHiddenCommandIsHidden(t *testing.T) {
+ c := &Command{Use: "c", Hidden: true, Run: emptyRun}
+ if c.IsAvailableCommand() {
+ t.Errorf("Hidden command should be unavailable")
}
}
@@ -158,15 +1277,16 @@ func TestCommandsAreSorted(t *testing.T) {
originalNames := []string{"middle", "zlast", "afirst"}
expectedNames := []string{"afirst", "middle", "zlast"}
- var tmpCommand = &Command{Use: "tmp"}
+ var rootCmd = &Command{Use: "root"}
for _, name := range originalNames {
- tmpCommand.AddCommand(&Command{Use: name})
+ rootCmd.AddCommand(&Command{Use: name})
}
- for i, c := range tmpCommand.Commands() {
- if expectedNames[i] != c.Name() {
- t.Errorf("expected: %s, got: %s", expectedNames[i], c.Name())
+ for i, c := range rootCmd.Commands() {
+ got := c.Name()
+ if expectedNames[i] != got {
+ t.Errorf("Expected: %s, got: %s", expectedNames[i], got)
}
}
@@ -178,15 +1298,16 @@ func TestEnableCommandSortingIsDisabled(t *testing.T) {
originalNames := []string{"middle", "zlast", "afirst"}
- var tmpCommand = &Command{Use: "tmp"}
+ var rootCmd = &Command{Use: "root"}
for _, name := range originalNames {
- tmpCommand.AddCommand(&Command{Use: name})
+ rootCmd.AddCommand(&Command{Use: name})
}
- for i, c := range tmpCommand.Commands() {
- if originalNames[i] != c.Name() {
- t.Errorf("expected: %s, got: %s", originalNames[i], c.Name())
+ for i, c := range rootCmd.Commands() {
+ got := c.Name()
+ if originalNames[i] != got {
+ t.Errorf("expected: %s, got: %s", originalNames[i], got)
}
}
@@ -194,33 +1315,27 @@ func TestEnableCommandSortingIsDisabled(t *testing.T) {
}
func TestSetOutput(t *testing.T) {
- cmd := &Command{}
- cmd.SetOutput(nil)
- if out := cmd.OutOrStdout(); out != os.Stdout {
- t.Fatalf("expected setting output to nil to revert back to stdout, got %v", out)
+ c := &Command{}
+ c.SetOutput(nil)
+ if out := c.OutOrStdout(); out != os.Stdout {
+ t.Errorf("Expected setting output to nil to revert back to stdout")
}
}
func TestFlagErrorFunc(t *testing.T) {
- cmd := &Command{
- Use: "print",
- RunE: func(cmd *Command, args []string) error {
- return nil
- },
- }
- expectedFmt := "This is expected: %s"
+ c := &Command{Use: "c", Run: emptyRun}
- cmd.SetFlagErrorFunc(func(c *Command, err error) error {
+ expectedFmt := "This is expected: %v"
+ c.SetFlagErrorFunc(func(_ *Command, err error) error {
return fmt.Errorf(expectedFmt, err)
})
- cmd.SetArgs([]string{"--bogus-flag"})
- cmd.SetOutput(new(bytes.Buffer))
- err := cmd.Execute()
+ _, err := executeCommand(c, "--unknown-flag")
- expected := fmt.Sprintf(expectedFmt, "unknown flag: --bogus-flag")
- if err.Error() != expected {
- t.Errorf("expected %v, got %v", expected, err.Error())
+ got := err.Error()
+ expected := fmt.Sprintf(expectedFmt, "unknown flag: --unknown-flag")
+ if got != expected {
+ t.Errorf("Expected %v, got %v", expected, got)
}
}
@@ -228,19 +1343,19 @@ func TestFlagErrorFunc(t *testing.T) {
// if cmd.LocalFlags() is unsorted when cmd.Flags().SortFlags set to false.
// Related to https://github.com/spf13/cobra/issues/404.
func TestSortedFlags(t *testing.T) {
- cmd := &Command{}
- cmd.Flags().SortFlags = false
+ c := &Command{}
+ c.Flags().SortFlags = false
names := []string{"C", "B", "A", "D"}
for _, name := range names {
- cmd.Flags().Bool(name, false, "")
+ c.Flags().Bool(name, false, "")
}
i := 0
- cmd.LocalFlags().VisitAll(func(f *pflag.Flag) {
+ c.LocalFlags().VisitAll(func(f *pflag.Flag) {
if i == len(names) {
return
}
- if isStringInStringSlice(f.Name, names) {
+ if stringInSlice(f.Name, names) {
if names[i] != f.Name {
t.Errorf("Incorrect order. Expected %v, got %v", names[i], f.Name)
}
@@ -249,101 +1364,145 @@ func TestSortedFlags(t *testing.T) {
})
}
-// contains checks, if s is in ss.
-func isStringInStringSlice(s string, ss []string) bool {
- for _, v := range ss {
- if v == s {
- return true
- }
- }
- return false
-}
-
-// TestHelpFlagInHelp checks,
-// if '--help' flag is shown in help for child (executing `parent help child`),
-// that has no other flags.
-// Related to https://github.com/spf13/cobra/issues/302.
-func TestHelpFlagInHelp(t *testing.T) {
- output := new(bytes.Buffer)
- parent := &Command{Use: "parent", Run: func(*Command, []string) {}}
- parent.SetOutput(output)
-
- child := &Command{Use: "child", Run: func(*Command, []string) {}}
- parent.AddCommand(child)
-
- parent.SetArgs([]string{"help", "child"})
- err := parent.Execute()
- if err != nil {
- t.Fatal(err)
- }
-
- if !strings.Contains(output.String(), "[flags]") {
- t.Errorf("\nExpecting to contain: %v\nGot: %v", "[flags]", output.String())
- }
-}
-
// TestMergeCommandLineToFlags checks,
// if pflag.CommandLine is correctly merged to c.Flags() after first call
// of c.mergePersistentFlags.
// Related to https://github.com/spf13/cobra/issues/443.
func TestMergeCommandLineToFlags(t *testing.T) {
pflag.Bool("boolflag", false, "")
- c := &Command{Use: "c", Run: func(*Command, []string) {}}
+ c := &Command{Use: "c", Run: emptyRun}
c.mergePersistentFlags()
if c.Flags().Lookup("boolflag") == nil {
t.Fatal("Expecting to have flag from CommandLine in c.Flags()")
}
- // Reset pflag.CommandLine flagset.
- pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
+ resetCommandLineFlagSet()
}
// TestUseDeprecatedFlags checks,
// if cobra.Execute() prints a message, if a deprecated flag is used.
// Related to https://github.com/spf13/cobra/issues/463.
func TestUseDeprecatedFlags(t *testing.T) {
- c := &Command{Use: "c", Run: func(*Command, []string) {}}
- output := new(bytes.Buffer)
- c.SetOutput(output)
+ c := &Command{Use: "c", Run: emptyRun}
c.Flags().BoolP("deprecated", "d", false, "deprecated flag")
c.Flags().MarkDeprecated("deprecated", "This flag is deprecated")
- c.SetArgs([]string{"c", "-d"})
- if err := c.Execute(); err != nil {
+ output, err := executeCommand(c, "c", "-d")
+ if err != nil {
t.Error("Unexpected error:", err)
}
- if !strings.Contains(output.String(), "This flag is deprecated") {
- t.Errorf("Expected to contain deprecated message, but got %q", output.String())
+ checkStringContains(t, output, "This flag is deprecated")
+}
+
+func TestTraverseWithParentFlags(t *testing.T) {
+ rootCmd := &Command{Use: "root", TraverseChildren: true}
+ rootCmd.Flags().String("str", "", "")
+ rootCmd.Flags().BoolP("bool", "b", false, "")
+
+ childCmd := &Command{Use: "child"}
+ childCmd.Flags().Int("int", -1, "")
+
+ rootCmd.AddCommand(childCmd)
+
+ c, args, err := rootCmd.Traverse([]string{"-b", "--str", "ok", "child", "--int"})
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+ if len(args) != 1 && args[0] != "--add" {
+ t.Errorf("Wrong args: %v", args)
+ }
+ if c.Name() != childCmd.Name() {
+ t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name())
}
}
-// TestSetHelpCommand checks, if SetHelpCommand works correctly.
-func TestSetHelpCommand(t *testing.T) {
- c := &Command{Use: "c", Run: func(*Command, []string) {}}
- output := new(bytes.Buffer)
- c.SetOutput(output)
- c.SetArgs([]string{"help"})
-
- // Help will not be shown, if c has no subcommands.
- c.AddCommand(&Command{
- Use: "empty",
- Run: func(cmd *Command, args []string) {},
- })
+func TestTraverseNoParentFlags(t *testing.T) {
+ rootCmd := &Command{Use: "root", TraverseChildren: true}
+ rootCmd.Flags().String("foo", "", "foo things")
- correctMessage := "WORKS"
- c.SetHelpCommand(&Command{
- Use: "help [command]",
- Short: "Help about any command",
- Long: `Help provides help for any command in the application.
- Simply type ` + c.Name() + ` help [path to command] for full details.`,
- Run: func(c *Command, args []string) { c.Print(correctMessage) },
- })
+ childCmd := &Command{Use: "child"}
+ childCmd.Flags().String("str", "", "")
+ rootCmd.AddCommand(childCmd)
- if err := c.Execute(); err != nil {
- t.Error("Unexpected error:", err)
+ c, args, err := rootCmd.Traverse([]string{"child"})
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+ if len(args) != 0 {
+ t.Errorf("Wrong args %v", args)
+ }
+ if c.Name() != childCmd.Name() {
+ t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name())
+ }
+}
+
+func TestTraverseWithBadParentFlags(t *testing.T) {
+ rootCmd := &Command{Use: "root", TraverseChildren: true}
+
+ childCmd := &Command{Use: "child"}
+ childCmd.Flags().String("str", "", "")
+ rootCmd.AddCommand(childCmd)
+
+ expected := "unknown flag: --str"
+
+ c, _, err := rootCmd.Traverse([]string{"--str", "ok", "child"})
+ if err == nil || !strings.Contains(err.Error(), expected) {
+ t.Errorf("Expected error, %q, got %q", expected, err)
+ }
+ if c != nil {
+ t.Errorf("Expected nil command")
}
+}
+
+func TestTraverseWithBadChildFlag(t *testing.T) {
+ rootCmd := &Command{Use: "root", TraverseChildren: true}
+ rootCmd.Flags().String("str", "", "")
+
+ childCmd := &Command{Use: "child"}
+ rootCmd.AddCommand(childCmd)
+
+ // Expect no error because the last commands args shouldn't be parsed in
+ // Traverse.
+ c, args, err := rootCmd.Traverse([]string{"child", "--str"})
+ if err != nil {
+ t.Errorf("Unexpected error: %v", err)
+ }
+ if len(args) != 1 && args[0] != "--str" {
+ t.Errorf("Wrong args: %v", args)
+ }
+ if c.Name() != childCmd.Name() {
+ t.Errorf("Expected command %q, got: %q", childCmd.Name(), c.Name())
+ }
+}
+
+func TestTraverseWithTwoSubcommands(t *testing.T) {
+ rootCmd := &Command{Use: "root", TraverseChildren: true}
+
+ subCmd := &Command{Use: "sub", TraverseChildren: true}
+ rootCmd.AddCommand(subCmd)
+
+ subsubCmd := &Command{
+ Use: "subsub",
+ }
+ subCmd.AddCommand(subsubCmd)
+
+ c, _, err := rootCmd.Traverse([]string{"sub", "subsub"})
+ if err != nil {
+ t.Fatalf("Unexpected error: %v", err)
+ }
+ if c.Name() != subsubCmd.Name() {
+ t.Fatalf("Expected command: %q, got %q", subsubCmd.Name(), c.Name())
+ }
+}
+
+// TestUpdateName checks if c.Name() updates on changed c.Use.
+// Related to https://github.com/spf13/cobra/pull/422#discussion_r143918343.
+func TestUpdateName(t *testing.T) {
+ c := &Command{Use: "name xyz"}
+ originalName := c.Name()
- if output.String() != correctMessage {
- t.Errorf("Expected to contain %q message, but got %q", correctMessage, output.String())
+ c.Use = "changedName abc"
+ if originalName == c.Name() || c.Name() != "changedName" {
+ t.Error("c.Name() should be updated on changed c.Use")
}
}