13 "github.com/spf13/pflag"
16 var tp, te, tt, tr []string
17 var rootPersPre, echoPre, echoPersPre, timesPersPre []string
18 var flagb1, flagb2, flagb3, flagbr, flagbp bool
19 var flags1, flags2a, flags2b, flags3, outs string
20 var flagi1, flagi2, flagi3, flagi4, flagir int
24 const strtwoParentHelp = "help message for parent flag strtwo"
25 const strtwoChildHelp = "help message for child flag strtwo"
27 var cmdHidden = &Command{
28 Use: "hide [secret string to print]",
29 Short: "Print anything to screen (if command is known)",
30 Long: `an absolutely utterly useless command for testing.`,
31 Run: func(cmd *Command, args []string) {
37 var cmdPrint = &Command{
38 Use: "print [string to print]",
39 Args: MinimumNArgs(1),
40 Short: "Print anything to the screen",
41 Long: `an absolutely utterly useless command for testing.`,
42 Run: func(cmd *Command, args []string) {
47 var cmdEcho = &Command{
48 Use: "echo [string to echo]",
49 Aliases: []string{"say"},
50 Short: "Echo anything to the screen",
51 Long: `an utterly useless command for testing.`,
52 Example: "Just run cobra-test echo",
53 PersistentPreRun: func(cmd *Command, args []string) {
56 PreRun: func(cmd *Command, args []string) {
59 Run: func(cmd *Command, args []string) {
64 var cmdEchoSub = &Command{
65 Use: "echosub [string to print]",
66 Short: "second sub command for echo",
67 Long: `an absolutely utterly useless command for testing gendocs!.`,
68 Run: func(cmd *Command, args []string) {
72 var cmdDeprecated = &Command{
73 Use: "deprecated [can't do anything here]",
74 Short: "A command which is deprecated",
75 Long: `an absolutely utterly useless command for testing deprecation!.`,
76 Deprecated: "Please use echo instead",
77 Run: func(cmd *Command, args []string) {
82 var cmdTimes = &Command{
83 Use: "times [# times] [string to echo]",
84 SuggestFor: []string{"counts"},
85 Short: "Echo anything to the screen more times",
86 Long: `a slightly useless command for testing.`,
87 PersistentPreRun: func(cmd *Command, args []string) {
90 Run: func(cmd *Command, args []string) {
94 ValidArgs: []string{"one", "two", "three", "four"},
97 var cmdRootNoRun = &Command{
99 Short: "The root can run its own function",
100 Long: "The root description for help",
101 PersistentPreRun: func(cmd *Command, args []string) {
106 var cmdRootSameName = &Command{
108 Short: "Root with the same name as a subcommand",
109 Long: "The root description for help",
112 var cmdRootTakesArgs = &Command{
113 Use: "root-with-args [random args]",
114 Short: "The root can run it's own function and takes args!",
115 Long: "The root description for help, and some args",
116 Run: func(cmd *Command, args []string) {
122 var cmdRootWithRun = &Command{
124 Short: "The root can run its own function",
125 Long: "The root description for help",
126 Run: func(cmd *Command, args []string) {
132 var cmdSubNoRun = &Command{
134 Short: "A subcommand without a Run function",
135 Long: "A long output about a subcommand without a Run function",
138 var cmdCustomFlags = &Command{
139 Use: "customflags [flags] -- REMOTE_COMMAND",
140 Short: "A command that expects flags in a custom location",
141 Long: "A long output about a command that expects flags in a custom location",
142 Run: func(cmd *Command, args []string) {
146 var cmdVersion1 = &Command{
148 Short: "Print the version number",
149 Long: `First version of the version command`,
150 Run: func(cmd *Command, args []string) {
155 var cmdVersion2 = &Command{
157 Short: "Print the version number",
158 Long: `Second version of the version command`,
159 Run: func(cmd *Command, args []string) {
164 var cmdColon = &Command{
166 Run: func(cmd *Command, args []string) {
172 cmdPrint.ResetFlags()
173 cmdTimes.ResetFlags()
174 cmdRootNoRun.ResetFlags()
175 cmdRootSameName.ResetFlags()
176 cmdRootWithRun.ResetFlags()
177 cmdSubNoRun.ResetFlags()
178 cmdCustomFlags.ResetFlags()
179 cmdVersion1.ResetFlags()
180 cmdVersion2.ResetFlags()
182 cmdRootNoRun.PersistentFlags().StringVarP(&flags2a, "strtwo", "t", "two", strtwoParentHelp)
183 cmdCustomFlags.Flags().IntVar(&flagi4, "intfour", 456, "help message for flag intfour")
184 cmdEcho.Flags().BoolVarP(&flagb1, "boolone", "b", true, "help message for flag boolone")
185 cmdEcho.Flags().IntVarP(&flagi1, "intone", "i", 123, "help message for flag intone")
186 cmdEcho.PersistentFlags().BoolVarP(&flagbp, "persistentbool", "p", false, "help message for flag persistentbool")
187 cmdEcho.PersistentFlags().StringVarP(&flags1, "strone", "s", "one", "help message for flag strone")
188 cmdPrint.Flags().IntVarP(&flagi3, "intthree", "i", 345, "help message for flag intthree")
189 cmdTimes.Flags().BoolVarP(&flagb2, "booltwo", "c", false, "help message for flag booltwo")
190 cmdTimes.Flags().IntVarP(&flagi2, "inttwo", "j", 234, "help message for flag inttwo")
191 cmdTimes.Flags().StringVarP(&flags2b, "strtwo", "t", "2", strtwoChildHelp)
192 cmdTimes.PersistentFlags().StringVarP(&flags2b, "strtwo", "t", "2", strtwoChildHelp)
193 cmdTimes.LocalFlags() // populate lflags before parent is set
194 cmdPrint.Flags().BoolVarP(&flagb3, "boolthree", "b", true, "help message for flag boolthree")
195 cmdPrint.PersistentFlags().StringVarP(&flags3, "strthree", "s", "three", "help message for flag strthree")
199 cmdEcho.ResetCommands()
200 cmdPrint.ResetCommands()
201 cmdTimes.ResetCommands()
202 cmdRootNoRun.ResetCommands()
203 cmdRootSameName.ResetCommands()
204 cmdRootWithRun.ResetCommands()
205 cmdSubNoRun.ResetCommands()
206 cmdCustomFlags.ResetCommands()
209 func initialize() *Command {
210 tt, tp, te = nil, nil, nil
211 rootPersPre, echoPre, echoPersPre, timesPersPre = nil, nil, nil, nil
219 func initializeWithSameName() *Command {
220 tt, tp, te = nil, nil, nil
221 rootPersPre, echoPre, echoPersPre, timesPersPre = nil, nil, nil, nil
222 var c = cmdRootSameName
228 func initializeWithRootCmd() *Command {
229 cmdRootWithRun.ResetCommands()
230 tt, tp, te, tr, rootcalled = nil, nil, nil, nil, false
232 cmdRootWithRun.Flags().BoolVarP(&flagbr, "boolroot", "b", false, "help message for flag boolroot")
233 cmdRootWithRun.Flags().IntVarP(&flagir, "introot", "i", 321, "help message for flag introot")
235 return cmdRootWithRun
238 type resulter struct {
244 func fullSetupTest(args ...string) resulter {
245 c := initializeWithRootCmd()
247 return fullTester(c, args...)
250 func noRRSetupTestSilenced(args ...string) resulter {
252 c.SilenceErrors = true
253 c.SilenceUsage = true
254 return fullTester(c, args...)
257 func noRRSetupTest(args ...string) resulter {
260 return fullTester(c, args...)
263 func rootOnlySetupTest(args ...string) resulter {
264 c := initializeWithRootCmd()
266 return simpleTester(c, args...)
269 func simpleTester(c *Command, args ...string) resulter {
270 buf := new(bytes.Buffer)
271 // Testing flag with invalid input
276 output := buf.String()
278 return resulter{err, output, c}
281 func simpleTesterC(c *Command, args ...string) resulter {
282 buf := new(bytes.Buffer)
283 // Testing flag with invalid input
287 cmd, err := c.ExecuteC()
288 output := buf.String()
290 return resulter{err, output, cmd}
293 func fullTester(c *Command, args ...string) resulter {
294 buf := new(bytes.Buffer)
295 // Testing flag with invalid input
297 cmdEcho.AddCommand(cmdTimes)
298 c.AddCommand(cmdPrint, cmdEcho, cmdSubNoRun, cmdCustomFlags, cmdDeprecated)
302 output := buf.String()
304 return resulter{err, output, c}
307 func logErr(t *testing.T, found, expected string) {
308 out := new(bytes.Buffer)
310 _, _, line, ok := runtime.Caller(2)
312 fmt.Fprintf(out, "Line: %d ", line)
314 fmt.Fprintf(out, "Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found)
315 t.Errorf(out.String())
318 func checkStringContains(t *testing.T, found, expected string) {
319 if !strings.Contains(found, expected) {
320 logErr(t, found, expected)
324 func checkResultContains(t *testing.T, x resulter, check string) {
325 checkStringContains(t, x.Output, check)
328 func checkStringOmits(t *testing.T, found, expected string) {
329 if strings.Contains(found, expected) {
330 logErr(t, found, expected)
334 func checkResultOmits(t *testing.T, x resulter, check string) {
335 checkStringOmits(t, x.Output, check)
338 func checkOutputContains(t *testing.T, c *Command, check string) {
339 buf := new(bytes.Buffer)
343 if !strings.Contains(buf.String(), check) {
344 logErr(t, buf.String(), check)
348 func TestSingleCommand(t *testing.T) {
349 noRRSetupTest("print", "one", "two")
351 if te != nil || tt != nil {
352 t.Error("Wrong command called")
355 t.Error("Wrong command called")
357 if strings.Join(tp, " ") != "one two" {
358 t.Error("Command didn't parse correctly")
362 func TestChildCommand(t *testing.T) {
363 noRRSetupTest("echo", "times", "one", "two")
365 if te != nil || tp != nil {
366 t.Error("Wrong command called")
369 t.Error("Wrong command called")
371 if strings.Join(tt, " ") != "one two" {
372 t.Error("Command didn't parse correctly")
376 func TestCommandAlias(t *testing.T) {
377 noRRSetupTest("say", "times", "one", "two")
379 if te != nil || tp != nil {
380 t.Error("Wrong command called")
383 t.Error("Wrong command called")
385 if strings.Join(tt, " ") != "one two" {
386 t.Error("Command didn't parse correctly")
390 func TestPrefixMatching(t *testing.T) {
391 EnablePrefixMatching = true
392 noRRSetupTest("ech", "times", "one", "two")
394 if te != nil || tp != nil {
395 t.Error("Wrong command called")
398 t.Error("Wrong command called")
400 if strings.Join(tt, " ") != "one two" {
401 t.Error("Command didn't parse correctly")
404 EnablePrefixMatching = false
407 func TestNoPrefixMatching(t *testing.T) {
408 EnablePrefixMatching = false
410 noRRSetupTest("ech", "times", "one", "two")
412 if !(tt == nil && te == nil && tp == nil) {
413 t.Error("Wrong command called")
417 func TestAliasPrefixMatching(t *testing.T) {
418 EnablePrefixMatching = true
419 noRRSetupTest("sa", "times", "one", "two")
421 if te != nil || tp != nil {
422 t.Error("Wrong command called")
425 t.Error("Wrong command called")
427 if strings.Join(tt, " ") != "one two" {
428 t.Error("Command didn't parse correctly")
430 EnablePrefixMatching = false
433 func TestChildSameName(t *testing.T) {
434 c := initializeWithSameName()
435 c.AddCommand(cmdPrint, cmdEcho)
436 c.SetArgs([]string{"print", "one", "two"})
439 if te != nil || tt != nil {
440 t.Error("Wrong command called")
443 t.Error("Wrong command called")
445 if strings.Join(tp, " ") != "one two" {
446 t.Error("Command didn't parse correctly")
450 func TestGrandChildSameName(t *testing.T) {
451 c := initializeWithSameName()
452 cmdTimes.AddCommand(cmdPrint)
453 c.AddCommand(cmdTimes)
454 c.SetArgs([]string{"times", "print", "one", "two"})
457 if te != nil || tt != nil {
458 t.Error("Wrong command called")
461 t.Error("Wrong command called")
463 if strings.Join(tp, " ") != "one two" {
464 t.Error("Command didn't parse correctly")
468 func TestUsage(t *testing.T) {
469 x := fullSetupTest("help")
470 checkResultContains(t, x, cmdRootWithRun.Use+" [flags]")
471 x = fullSetupTest("help", "customflags")
472 checkResultContains(t, x, cmdCustomFlags.Use)
473 checkResultOmits(t, x, cmdCustomFlags.Use+" [flags]")
476 func TestRootTakesNoArgs(t *testing.T) {
477 c := initializeWithSameName()
478 c.AddCommand(cmdPrint, cmdEcho)
479 result := simpleTester(c, "illegal")
481 if result.Error == nil {
482 t.Fatal("Expected an error")
485 expectedError := `unknown command "illegal" for "print"`
486 if !strings.Contains(result.Error.Error(), expectedError) {
487 t.Errorf("exptected %v, got %v", expectedError, result.Error.Error())
491 func TestRootTakesArgs(t *testing.T) {
492 c := cmdRootTakesArgs
493 result := simpleTester(c, "legal")
495 if result.Error != nil {
496 t.Errorf("expected no error, but got %v", result.Error)
500 func TestSubCmdTakesNoArgs(t *testing.T) {
501 result := fullSetupTest("deprecated", "illegal")
503 if result.Error == nil {
504 t.Fatal("Expected an error")
507 expectedError := `unknown command "illegal" for "cobra-test deprecated"`
508 if !strings.Contains(result.Error.Error(), expectedError) {
509 t.Errorf("expected %v, got %v", expectedError, result.Error.Error())
513 func TestSubCmdTakesArgs(t *testing.T) {
514 noRRSetupTest("echo", "times", "one", "two")
515 if strings.Join(tt, " ") != "one two" {
516 t.Error("Command didn't parse correctly")
520 func TestCmdOnlyValidArgs(t *testing.T) {
521 result := noRRSetupTest("echo", "times", "one", "two", "five")
523 if result.Error == nil {
524 t.Fatal("Expected an error")
527 expectedError := `invalid argument "five"`
528 if !strings.Contains(result.Error.Error(), expectedError) {
529 t.Errorf("expected %v, got %v", expectedError, result.Error.Error())
533 func TestFlagLong(t *testing.T) {
534 noRRSetupTest("echo", "--intone=13", "something", "--", "here")
536 if cmdEcho.ArgsLenAtDash() != 1 {
537 t.Errorf("expected argsLenAtDash: %d but got %d", 1, cmdRootNoRun.ArgsLenAtDash())
539 if strings.Join(te, " ") != "something here" {
540 t.Errorf("flags didn't leave proper args remaining..%s given", te)
543 t.Errorf("int flag didn't get correct value, had %d", flagi1)
546 t.Errorf("default flag value changed, 234 expected, %d given", flagi2)
550 func TestFlagShort(t *testing.T) {
551 noRRSetupTest("echo", "-i13", "--", "something", "here")
553 if cmdEcho.ArgsLenAtDash() != 0 {
554 t.Errorf("expected argsLenAtDash: %d but got %d", 0, cmdRootNoRun.ArgsLenAtDash())
556 if strings.Join(te, " ") != "something here" {
557 t.Errorf("flags didn't leave proper args remaining..%s given", te)
560 t.Errorf("int flag didn't get correct value, had %d", flagi1)
563 t.Errorf("default flag value changed, 234 expected, %d given", flagi2)
566 noRRSetupTest("echo", "-i", "13", "something", "here")
568 if strings.Join(te, " ") != "something here" {
569 t.Errorf("flags didn't leave proper args remaining..%s given", te)
572 t.Errorf("int flag didn't get correct value, had %d", flagi1)
575 t.Errorf("default flag value changed, 234 expected, %d given", flagi2)
578 noRRSetupTest("print", "-i99", "one", "two")
580 if strings.Join(tp, " ") != "one two" {
581 t.Errorf("flags didn't leave proper args remaining..%s given", tp)
584 t.Errorf("int flag didn't get correct value, had %d", flagi3)
587 t.Errorf("default flag value changed on different command with same shortname, 234 expected, %d given", flagi2)
591 func TestChildCommandFlags(t *testing.T) {
592 noRRSetupTest("echo", "times", "-j", "99", "one", "two")
594 if strings.Join(tt, " ") != "one two" {
595 t.Errorf("flags didn't leave proper args remaining..%s given", tt)
598 // Testing with flag that shouldn't be persistent
599 r := noRRSetupTest("echo", "times", "-j", "99", "-i77", "one", "two")
602 t.Errorf("invalid flag should generate error")
605 if !strings.Contains(r.Error.Error(), "unknown shorthand") {
606 t.Errorf("Wrong error message displayed, \n %s", r.Error)
610 t.Errorf("flag value should be 99, %d given", flagi2)
614 t.Errorf("unset flag should have default value, expecting 123, given %d", flagi1)
617 // Testing with flag only existing on child
618 r = noRRSetupTest("echo", "-j", "99", "-i77", "one", "two")
621 t.Errorf("invalid flag should generate error")
623 if !strings.Contains(r.Error.Error(), "unknown shorthand flag") {
624 t.Errorf("Wrong error message displayed, \n %s", r.Error)
627 // Testing with persistent flag overwritten by child
628 noRRSetupTest("echo", "times", "--strtwo=child", "one", "two")
630 if flags2b != "child" {
631 t.Errorf("flag value should be child, %s given", flags2b)
634 if flags2a != "two" {
635 t.Errorf("unset flag should have default value, expecting two, given %s", flags2a)
638 // Testing flag with invalid input
639 r = noRRSetupTest("echo", "-i10E")
642 t.Errorf("invalid input should generate error")
644 if !strings.Contains(r.Error.Error(), "invalid syntax") {
645 t.Errorf("Wrong error message displayed, \n %s", r.Error)
649 func TestTrailingCommandFlags(t *testing.T) {
650 x := fullSetupTest("echo", "two", "-x")
653 t.Errorf("invalid flag should generate error")
657 func TestInvalidSubcommandFlags(t *testing.T) {
658 cmd := initializeWithRootCmd()
659 cmd.AddCommand(cmdTimes)
661 result := simpleTester(cmd, "times", "--inttwo=2", "--badflag=bar")
662 // given that we are not checking here result.Error we check for
663 // stock usage message
664 checkResultContains(t, result, "cobra-test times [# times]")
665 if strings.Contains(result.Error.Error(), "unknown flag: --inttwo") {
666 t.Errorf("invalid --badflag flag shouldn't fail on 'unknown' --inttwo flag")
671 func TestSubcommandExecuteC(t *testing.T) {
672 cmd := initializeWithRootCmd()
674 Use: "double message",
675 Run: func(c *Command, args []string) {
676 msg := strings.Join(args, " ")
683 Run: func(c *Command, args []string) {
684 msg := strings.Join(args, " ")
689 cmd.AddCommand(double, echo)
691 result := simpleTesterC(cmd, "double", "hello", "world")
692 checkResultContains(t, result, "hello world hello world")
694 if result.Command.Name() != "double" {
695 t.Errorf("invalid cmd returned from ExecuteC: should be 'double' but got %s", result.Command.Name())
698 result = simpleTesterC(cmd, "echo", "msg", "to", "be", "echoed")
699 checkResultContains(t, result, "msg to be echoed")
701 if result.Command.Name() != "echo" {
702 t.Errorf("invalid cmd returned from ExecuteC: should be 'echo' but got %s", result.Command.Name())
706 func TestSubcommandArgEvaluation(t *testing.T) {
707 cmd := initializeWithRootCmd()
711 Run: func(cmd *Command, args []string) {
714 cmd.AddCommand(first)
718 Run: func(cmd *Command, args []string) {
719 fmt.Fprintf(cmd.OutOrStdout(), "%v", args)
722 first.AddCommand(second)
724 result := simpleTester(cmd, "first", "second", "first", "third")
726 expectedOutput := fmt.Sprint([]string{"first third"})
727 if result.Output != expectedOutput {
728 t.Errorf("exptected %v, got %v", expectedOutput, result.Output)
732 func TestPersistentFlags(t *testing.T) {
733 fullSetupTest("echo", "-s", "something", "-p", "more", "here")
735 // persistentFlag should act like normal flag on its own command
736 if strings.Join(te, " ") != "more here" {
737 t.Errorf("flags didn't leave proper args remaining..%s given", te)
739 if flags1 != "something" {
740 t.Errorf("string flag didn't get correct value, had %v", flags1)
743 t.Errorf("persistent bool flag not parsed correctly. Expected true, had %v", flagbp)
746 // persistentFlag should act like normal flag on its own command
747 fullSetupTest("echo", "times", "-s", "again", "-c", "-p", "one", "two")
749 if strings.Join(tt, " ") != "one two" {
750 t.Errorf("flags didn't leave proper args remaining. %s given", tt)
753 if flags1 != "again" {
754 t.Errorf("string flag didn't get correct value, had %v", flags1)
758 t.Errorf("local flag not parsed correctly. Expected true, had %v", flagb2)
761 t.Errorf("persistent bool flag not parsed correctly. Expected true, had %v", flagbp)
765 func TestHelpCommand(t *testing.T) {
766 x := fullSetupTest("help")
767 checkResultContains(t, x, cmdRootWithRun.Long)
769 x = fullSetupTest("help", "echo")
770 checkResultContains(t, x, cmdEcho.Long)
772 x = fullSetupTest("help", "echo", "times")
773 checkResultContains(t, x, cmdTimes.Long)
776 func TestChildCommandHelp(t *testing.T) {
777 c := noRRSetupTest("print", "--help")
778 checkResultContains(t, c, strtwoParentHelp)
779 r := noRRSetupTest("echo", "times", "--help")
780 checkResultContains(t, r, strtwoChildHelp)
783 func TestNonRunChildHelp(t *testing.T) {
784 x := noRRSetupTest("subnorun")
785 checkResultContains(t, x, cmdSubNoRun.Long)
788 func TestRunnableRootCommand(t *testing.T) {
789 x := fullSetupTest("")
792 t.Errorf("Root Function was not called\n out:%v", x.Error)
796 func TestVisitParents(t *testing.T) {
797 c := &Command{Use: "app"}
798 sub := &Command{Use: "sub"}
799 dsub := &Command{Use: "dsub"}
803 add := func(x *Command) {
806 sub.VisitParents(add)
808 t.Errorf("Should have visited 1 parent but visited %d", total)
812 dsub.VisitParents(add)
814 t.Errorf("Should have visited 2 parent but visited %d", total)
820 t.Errorf("Should have not visited any parent but visited %d", total)
824 func TestRunnableRootCommandNilInput(t *testing.T) {
825 c := initializeWithRootCmd()
827 buf := new(bytes.Buffer)
828 // Testing flag with invalid input
830 cmdEcho.AddCommand(cmdTimes)
831 c.AddCommand(cmdPrint, cmdEcho)
832 c.SetArgs([]string{})
836 t.Errorf("Execute() failed with %v", err)
840 t.Errorf("Root Function was not called")
844 func TestRunnableRootCommandEmptyInput(t *testing.T) {
845 args := []string{"", "--introot=12", ""}
846 c := initializeWithRootCmd()
848 buf := new(bytes.Buffer)
849 // Testing flag with invalid input
851 cmdEcho.AddCommand(cmdTimes)
852 c.AddCommand(cmdPrint, cmdEcho)
858 t.Errorf("Root Function was not called.\nOutput was:\n%s\n", buf)
862 func TestInvalidSubcommandWhenArgsAllowed(t *testing.T) {
863 fullSetupTest("echo", "invalid-sub")
865 if te[0] != "invalid-sub" {
866 t.Errorf("Subcommand didn't work...")
870 func TestRootFlags(t *testing.T) {
871 fullSetupTest("-i", "17", "-b")
874 t.Errorf("flag value should be true, %v given", flagbr)
878 t.Errorf("flag value should be 17, %d given", flagir)
882 func TestRootHelp(t *testing.T) {
883 x := fullSetupTest("--help")
885 checkResultContains(t, x, "Available Commands:")
886 checkResultContains(t, x, "for more information about a command")
888 if strings.Contains(x.Output, "unknown flag: --help") {
889 t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
892 if strings.Contains(x.Output, cmdEcho.Use) {
893 t.Errorf("--help shouldn't display subcommand's usage, Got: \n %s", x.Output)
896 x = fullSetupTest("echo", "--help")
898 if strings.Contains(x.Output, cmdTimes.Use) {
899 t.Errorf("--help shouldn't display subsubcommand's usage, Got: \n %s", x.Output)
902 checkResultContains(t, x, "Available Commands:")
903 checkResultContains(t, x, "for more information about a command")
905 if strings.Contains(x.Output, "unknown flag: --help") {
906 t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
911 func TestFlagAccess(t *testing.T) {
914 cmdEcho.AddCommand(cmdTimes)
915 local := cmdTimes.LocalFlags()
916 inherited := cmdTimes.InheritedFlags()
918 for _, f := range []string{"inttwo", "strtwo", "booltwo"} {
919 if local.Lookup(f) == nil {
920 t.Errorf("LocalFlags expected to contain %s, Got: nil", f)
923 if inherited.Lookup("strone") == nil {
924 t.Errorf("InheritedFlags expected to contain strone, Got: nil")
926 if inherited.Lookup("strtwo") != nil {
927 t.Errorf("InheritedFlags shouldn not contain overwritten flag strtwo")
931 func TestNoNRunnableRootCommandNilInput(t *testing.T) {
934 buf := new(bytes.Buffer)
935 // Testing flag with invalid input
937 cmdEcho.AddCommand(cmdTimes)
938 c.AddCommand(cmdPrint, cmdEcho)
939 c.SetArgs([]string{})
943 if !strings.Contains(buf.String(), cmdRootNoRun.Long) {
944 t.Errorf("Expected to get help output, Got: \n %s", buf)
948 func TestRootNoCommandHelp(t *testing.T) {
949 x := rootOnlySetupTest("--help")
951 checkResultOmits(t, x, "Available Commands:")
952 checkResultOmits(t, x, "for more information about a command")
954 if strings.Contains(x.Output, "unknown flag: --help") {
955 t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
958 x = rootOnlySetupTest("echo", "--help")
960 checkResultOmits(t, x, "Available Commands:")
961 checkResultOmits(t, x, "for more information about a command")
963 if strings.Contains(x.Output, "unknown flag: --help") {
964 t.Errorf("--help shouldn't trigger an error, Got: \n %s", x.Output)
968 func TestRootUnknownCommand(t *testing.T) {
969 r := noRRSetupTest("bogus")
970 s := "Error: unknown command \"bogus\" for \"cobra-test\"\nRun 'cobra-test --help' for usage.\n"
973 t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output)
976 r = noRRSetupTest("--strtwo=a", "bogus")
978 t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", s, r.Output)
982 func TestRootUnknownCommandSilenced(t *testing.T) {
983 r := noRRSetupTestSilenced("bogus")
986 t.Errorf("Unexpected response.\nExpecting to be: \n\"\"\n Got:\n %q\n", r.Output)
989 r = noRRSetupTestSilenced("--strtwo=a", "bogus")
991 t.Errorf("Unexpected response.\nExpecting to be:\n\"\"\nGot:\n %q\n", r.Output)
995 func TestRootSuggestions(t *testing.T) {
996 outputWithSuggestions := "Error: unknown command \"%s\" for \"cobra-test\"\n\nDid you mean this?\n\t%s\n\nRun 'cobra-test --help' for usage.\n"
997 outputWithoutSuggestions := "Error: unknown command \"%s\" for \"cobra-test\"\nRun 'cobra-test --help' for usage.\n"
999 cmd := initializeWithRootCmd()
1000 cmd.AddCommand(cmdTimes)
1002 tests := map[string]string{
1017 for typo, suggestion := range tests {
1018 for _, suggestionsDisabled := range []bool{false, true} {
1019 cmd.DisableSuggestions = suggestionsDisabled
1020 result := simpleTester(cmd, typo)
1022 if len(suggestion) == 0 || suggestionsDisabled {
1023 expected = fmt.Sprintf(outputWithoutSuggestions, typo)
1025 expected = fmt.Sprintf(outputWithSuggestions, typo, suggestion)
1027 if result.Output != expected {
1028 t.Errorf("Unexpected response.\nExpecting to be:\n %q\nGot:\n %q\n", expected, result.Output)
1034 func TestFlagsBeforeCommand(t *testing.T) {
1035 // short without space
1036 x := fullSetupTest("-i10", "echo")
1038 t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
1041 x = noRRSetupTest("echo", "-i=10")
1043 t.Errorf("Valid Input shouldn't have errors, got:\n %s", x.Error)
1047 x = noRRSetupTest("--intone=123", "echo", "one", "two")
1049 t.Errorf("Valid Input shouldn't have errors, got:\n %s", x.Error)
1052 // With parsing error properly reported
1053 x = fullSetupTest("-i10E", "echo")
1054 if !strings.Contains(x.Error.Error(), "invalid syntax") {
1055 t.Errorf("Wrong error message displayed, \n %s", x.Error)
1059 func TestRemoveCommand(t *testing.T) {
1061 c := initializeWithRootCmd()
1062 c.AddCommand(cmdVersion1)
1063 c.RemoveCommand(cmdVersion1)
1064 x := fullTester(c, "version")
1066 t.Errorf("Removed command should not have been called\n")
1071 func TestCommandWithoutSubcommands(t *testing.T) {
1072 c := initializeWithRootCmd()
1074 x := simpleTester(c, "")
1076 t.Errorf("Calling command without subcommands should not have error: %v", x.Error)
1081 func TestCommandWithoutSubcommandsWithArg(t *testing.T) {
1082 c := initializeWithRootCmd()
1083 expectedArgs := []string{"arg"}
1085 x := simpleTester(c, "arg")
1087 t.Errorf("Calling command without subcommands but with arg should not have error: %v", x.Error)
1090 if !reflect.DeepEqual(expectedArgs, tr) {
1091 t.Errorf("Calling command without subcommands but with arg has wrong args: expected: %v, actual: %v", expectedArgs, tr)
1096 func TestReplaceCommandWithRemove(t *testing.T) {
1098 c := initializeWithRootCmd()
1099 c.AddCommand(cmdVersion1)
1100 c.RemoveCommand(cmdVersion1)
1101 c.AddCommand(cmdVersion2)
1102 x := fullTester(c, "version")
1104 t.Errorf("Valid Input shouldn't have errors, got:\n %q", x.Error)
1107 if versionUsed == 1 {
1108 t.Errorf("Removed command shouldn't be called\n")
1110 if versionUsed != 2 {
1111 t.Errorf("Replacing command should have been called but didn't\n")
1115 func TestDeprecatedSub(t *testing.T) {
1116 c := fullSetupTest("deprecated")
1118 checkResultContains(t, c, cmdDeprecated.Deprecated)
1121 func TestPreRun(t *testing.T) {
1122 noRRSetupTest("echo", "one", "two")
1123 if echoPre == nil || echoPersPre == nil {
1124 t.Error("PreRun or PersistentPreRun not called")
1126 if rootPersPre != nil || timesPersPre != nil {
1127 t.Error("Wrong *Pre functions called!")
1130 noRRSetupTest("echo", "times", "one", "two")
1131 if timesPersPre == nil {
1132 t.Error("PreRun or PersistentPreRun not called")
1134 if echoPre != nil || echoPersPre != nil || rootPersPre != nil {
1135 t.Error("Wrong *Pre functions called!")
1138 noRRSetupTest("print", "one", "two")
1139 if rootPersPre == nil {
1140 t.Error("Parent PersistentPreRun not called but should not have been")
1142 if echoPre != nil || echoPersPre != nil || timesPersPre != nil {
1143 t.Error("Wrong *Pre functions called!")
1147 // Check if cmdEchoSub gets PersistentPreRun from rootCmd even if is added last
1148 func TestPeristentPreRunPropagation(t *testing.T) {
1149 rootCmd := initialize()
1151 // First add the cmdEchoSub to cmdPrint
1152 cmdPrint.AddCommand(cmdEchoSub)
1153 // Now add cmdPrint to rootCmd
1154 rootCmd.AddCommand(cmdPrint)
1156 rootCmd.SetArgs([]string{"print", "echosub", "lala"})
1159 if len(rootPersPre) == 0 || rootPersPre[0] != "lala" {
1160 t.Error("RootCmd PersistentPreRun not called but should have been")
1164 func TestGlobalNormFuncPropagation(t *testing.T) {
1165 normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
1166 return pflag.NormalizedName(name)
1169 rootCmd := initialize()
1170 rootCmd.AddCommand(cmdEcho)
1172 rootCmd.SetGlobalNormalizationFunc(normFunc)
1173 if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() {
1174 t.Error("rootCmd seems to have a wrong normalization function")
1177 // Also check it propagates retroactively
1178 if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(cmdEcho.GlobalNormalizationFunc()).Pointer() {
1179 t.Error("cmdEcho should have had the normalization function of rootCmd")
1182 // First add the cmdEchoSub to cmdPrint
1183 cmdPrint.AddCommand(cmdEchoSub)
1184 if cmdPrint.GlobalNormalizationFunc() != nil && cmdEchoSub.GlobalNormalizationFunc() != nil {
1185 t.Error("cmdPrint and cmdEchoSub should had no normalization functions")
1188 // Now add cmdPrint to rootCmd
1189 rootCmd.AddCommand(cmdPrint)
1190 if reflect.ValueOf(cmdPrint.GlobalNormalizationFunc()).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() ||
1191 reflect.ValueOf(cmdEchoSub.GlobalNormalizationFunc()).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() {
1192 t.Error("cmdPrint and cmdEchoSub should had the normalization function of rootCmd")
1196 func TestNormPassedOnLocal(t *testing.T) {
1197 n := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
1198 return pflag.NormalizedName(strings.ToUpper(name))
1204 cmd.Flags().BoolVar(&flagVal, "flagname", true, "this is a dummy flag")
1205 cmd.SetGlobalNormalizationFunc(n)
1206 if cmd.LocalFlags().Lookup("flagname") != cmd.LocalFlags().Lookup("FLAGNAME") {
1207 t.Error("Normalization function should be passed on to Local flag set")
1211 func TestNormPassedOnInherited(t *testing.T) {
1212 n := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
1213 return pflag.NormalizedName(strings.ToUpper(name))
1216 cmd, childBefore, childAfter := &Command{}, &Command{}, &Command{}
1218 cmd.AddCommand(childBefore)
1220 cmd.PersistentFlags().BoolVar(&flagVal, "flagname", true, "this is a dummy flag")
1221 cmd.SetGlobalNormalizationFunc(n)
1223 cmd.AddCommand(childAfter)
1225 if f := childBefore.InheritedFlags(); f.Lookup("flagname") == nil || f.Lookup("flagname") != f.Lookup("FLAGNAME") {
1226 t.Error("Normalization function should be passed on to inherited flag set in command added before flag")
1228 if f := childAfter.InheritedFlags(); f.Lookup("flagname") == nil || f.Lookup("flagname") != f.Lookup("FLAGNAME") {
1229 t.Error("Normalization function should be passed on to inherited flag set in command added after flag")
1233 // Related to https://github.com/spf13/cobra/issues/521.
1234 func TestNormConsistent(t *testing.T) {
1235 n := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
1236 return pflag.NormalizedName(strings.ToUpper(name))
1238 id := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
1239 return pflag.NormalizedName(name)
1245 cmd.Flags().BoolVar(&flagVal, "flagname", true, "this is a dummy flag")
1246 // Build local flag set
1249 cmd.SetGlobalNormalizationFunc(n)
1250 cmd.SetGlobalNormalizationFunc(id)
1252 if cmd.LocalFlags().Lookup("flagname") == cmd.LocalFlags().Lookup("FLAGNAME") {
1253 t.Error("Normalizing flag names should not result in duplicate flags")
1257 func TestFlagOnPflagCommandLine(t *testing.T) {
1258 flagName := "flagOnCommandLine"
1259 pflag.String(flagName, "", "about my flag")
1260 r := fullSetupTest("--help")
1262 checkResultContains(t, r, flagName)
1264 // Reset pflag.CommandLine flagset.
1265 pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
1268 func TestAddTemplateFunctions(t *testing.T) {
1269 AddTemplateFunc("t", func() bool { return true })
1270 AddTemplateFuncs(template.FuncMap{
1271 "f": func() bool { return false },
1272 "h": func() string { return "Hello," },
1273 "w": func() string { return "world." }})
1275 const usage = "Hello, world."
1278 c.SetUsageTemplate(`{{if t}}{{h}}{{end}}{{if f}}{{h}}{{end}} {{w}}`)
1280 if us := c.UsageString(); us != usage {
1281 t.Errorf("c.UsageString() != \"%s\", is \"%s\"", usage, us)
1285 func TestUsageIsNotPrintedTwice(t *testing.T) {
1286 var cmd = &Command{Use: "root"}
1287 var sub = &Command{Use: "sub"}
1290 r := simpleTester(cmd, "")
1291 if strings.Count(r.Output, "Usage:") != 1 {
1292 t.Error("Usage output is not printed exactly once")
1296 func BenchmarkInheritedFlags(b *testing.B) {
1298 cmdEcho.AddCommand(cmdTimes)
1301 for i := 0; i < b.N; i++ {
1302 cmdTimes.InheritedFlags()
1306 func BenchmarkLocalFlags(b *testing.B) {
1308 cmdEcho.AddCommand(cmdTimes)
1311 for i := 0; i < b.N; i++ {
1312 cmdTimes.LocalFlags()