git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/cobra/command_test.go (about)

     1  // Copyright 2013-2022 The Cobra Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package cobra
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"fmt"
    21  	"io/ioutil"
    22  	"os"
    23  	"reflect"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/spf13/pflag"
    28  )
    29  
    30  func emptyRun(*Command, []string) {}
    31  
    32  func executeCommand(root *Command, args ...string) (output string, err error) {
    33  	_, output, err = executeCommandC(root, args...)
    34  	return output, err
    35  }
    36  
    37  func executeCommandWithContext(ctx context.Context, root *Command, args ...string) (output string, err error) {
    38  	buf := new(bytes.Buffer)
    39  	root.SetOut(buf)
    40  	root.SetErr(buf)
    41  	root.SetArgs(args)
    42  
    43  	err = root.ExecuteContext(ctx)
    44  
    45  	return buf.String(), err
    46  }
    47  
    48  func executeCommandC(root *Command, args ...string) (c *Command, output string, err error) {
    49  	buf := new(bytes.Buffer)
    50  	root.SetOut(buf)
    51  	root.SetErr(buf)
    52  	root.SetArgs(args)
    53  
    54  	c, err = root.ExecuteC()
    55  
    56  	return c, buf.String(), err
    57  }
    58  
    59  func executeCommandWithContextC(ctx context.Context, root *Command, args ...string) (c *Command, output string, err error) {
    60  	buf := new(bytes.Buffer)
    61  	root.SetOut(buf)
    62  	root.SetErr(buf)
    63  	root.SetArgs(args)
    64  
    65  	c, err = root.ExecuteContextC(ctx)
    66  
    67  	return c, buf.String(), err
    68  }
    69  
    70  func resetCommandLineFlagSet() {
    71  	pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
    72  }
    73  
    74  func checkStringContains(t *testing.T, got, expected string) {
    75  	if !strings.Contains(got, expected) {
    76  		t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expected, got)
    77  	}
    78  }
    79  
    80  func checkStringOmits(t *testing.T, got, expected string) {
    81  	if strings.Contains(got, expected) {
    82  		t.Errorf("Expected to not contain: \n %v\nGot: %v", expected, got)
    83  	}
    84  }
    85  
    86  const onetwo = "one two"
    87  
    88  func TestSingleCommand(t *testing.T) {
    89  	var rootCmdArgs []string
    90  	rootCmd := &Command{
    91  		Use:  "root",
    92  		Args: ExactArgs(2),
    93  		Run:  func(_ *Command, args []string) { rootCmdArgs = args },
    94  	}
    95  	aCmd := &Command{Use: "a", Args: NoArgs, Run: emptyRun}
    96  	bCmd := &Command{Use: "b", Args: NoArgs, Run: emptyRun}
    97  	rootCmd.AddCommand(aCmd, bCmd)
    98  
    99  	output, err := executeCommand(rootCmd, "one", "two")
   100  	if output != "" {
   101  		t.Errorf("Unexpected output: %v", output)
   102  	}
   103  	if err != nil {
   104  		t.Errorf("Unexpected error: %v", err)
   105  	}
   106  
   107  	got := strings.Join(rootCmdArgs, " ")
   108  	if got != onetwo {
   109  		t.Errorf("rootCmdArgs expected: %q, got: %q", onetwo, got)
   110  	}
   111  }
   112  
   113  func TestChildCommand(t *testing.T) {
   114  	var child1CmdArgs []string
   115  	rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
   116  	child1Cmd := &Command{
   117  		Use:  "child1",
   118  		Args: ExactArgs(2),
   119  		Run:  func(_ *Command, args []string) { child1CmdArgs = args },
   120  	}
   121  	child2Cmd := &Command{Use: "child2", Args: NoArgs, Run: emptyRun}
   122  	rootCmd.AddCommand(child1Cmd, child2Cmd)
   123  
   124  	output, err := executeCommand(rootCmd, "child1", "one", "two")
   125  	if output != "" {
   126  		t.Errorf("Unexpected output: %v", output)
   127  	}
   128  	if err != nil {
   129  		t.Errorf("Unexpected error: %v", err)
   130  	}
   131  
   132  	got := strings.Join(child1CmdArgs, " ")
   133  	if got != onetwo {
   134  		t.Errorf("child1CmdArgs expected: %q, got: %q", onetwo, got)
   135  	}
   136  }
   137  
   138  func TestCallCommandWithoutSubcommands(t *testing.T) {
   139  	rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
   140  	_, err := executeCommand(rootCmd)
   141  	if err != nil {
   142  		t.Errorf("Calling command without subcommands should not have error: %v", err)
   143  	}
   144  }
   145  
   146  func TestRootExecuteUnknownCommand(t *testing.T) {
   147  	rootCmd := &Command{Use: "root", Run: emptyRun}
   148  	rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
   149  
   150  	output, _ := executeCommand(rootCmd, "unknown")
   151  
   152  	expected := "Error: unknown command \"unknown\" for \"root\"\nRun 'root --help' for usage.\n"
   153  
   154  	if output != expected {
   155  		t.Errorf("Expected:\n %q\nGot:\n %q\n", expected, output)
   156  	}
   157  }
   158  
   159  func TestSubcommandExecuteC(t *testing.T) {
   160  	rootCmd := &Command{Use: "root", Run: emptyRun}
   161  	childCmd := &Command{Use: "child", Run: emptyRun}
   162  	rootCmd.AddCommand(childCmd)
   163  
   164  	c, output, err := executeCommandC(rootCmd, "child")
   165  	if output != "" {
   166  		t.Errorf("Unexpected output: %v", output)
   167  	}
   168  	if err != nil {
   169  		t.Errorf("Unexpected error: %v", err)
   170  	}
   171  
   172  	if c.Name() != "child" {
   173  		t.Errorf(`invalid command returned from ExecuteC: expected "child"', got: %q`, c.Name())
   174  	}
   175  }
   176  
   177  func TestExecuteContext(t *testing.T) {
   178  	ctx := context.TODO()
   179  
   180  	ctxRun := func(cmd *Command, args []string) {
   181  		if cmd.Context() != ctx {
   182  			t.Errorf("Command %q must have context when called with ExecuteContext", cmd.Use)
   183  		}
   184  	}
   185  
   186  	rootCmd := &Command{Use: "root", Run: ctxRun, PreRun: ctxRun}
   187  	childCmd := &Command{Use: "child", Run: ctxRun, PreRun: ctxRun}
   188  	granchildCmd := &Command{Use: "grandchild", Run: ctxRun, PreRun: ctxRun}
   189  
   190  	childCmd.AddCommand(granchildCmd)
   191  	rootCmd.AddCommand(childCmd)
   192  
   193  	if _, err := executeCommandWithContext(ctx, rootCmd, ""); err != nil {
   194  		t.Errorf("Root command must not fail: %+v", err)
   195  	}
   196  
   197  	if _, err := executeCommandWithContext(ctx, rootCmd, "child"); err != nil {
   198  		t.Errorf("Subcommand must not fail: %+v", err)
   199  	}
   200  
   201  	if _, err := executeCommandWithContext(ctx, rootCmd, "child", "grandchild"); err != nil {
   202  		t.Errorf("Command child must not fail: %+v", err)
   203  	}
   204  }
   205  
   206  func TestExecuteContextC(t *testing.T) {
   207  	ctx := context.TODO()
   208  
   209  	ctxRun := func(cmd *Command, args []string) {
   210  		if cmd.Context() != ctx {
   211  			t.Errorf("Command %q must have context when called with ExecuteContext", cmd.Use)
   212  		}
   213  	}
   214  
   215  	rootCmd := &Command{Use: "root", Run: ctxRun, PreRun: ctxRun}
   216  	childCmd := &Command{Use: "child", Run: ctxRun, PreRun: ctxRun}
   217  	granchildCmd := &Command{Use: "grandchild", Run: ctxRun, PreRun: ctxRun}
   218  
   219  	childCmd.AddCommand(granchildCmd)
   220  	rootCmd.AddCommand(childCmd)
   221  
   222  	if _, _, err := executeCommandWithContextC(ctx, rootCmd, ""); err != nil {
   223  		t.Errorf("Root command must not fail: %+v", err)
   224  	}
   225  
   226  	if _, _, err := executeCommandWithContextC(ctx, rootCmd, "child"); err != nil {
   227  		t.Errorf("Subcommand must not fail: %+v", err)
   228  	}
   229  
   230  	if _, _, err := executeCommandWithContextC(ctx, rootCmd, "child", "grandchild"); err != nil {
   231  		t.Errorf("Command child must not fail: %+v", err)
   232  	}
   233  }
   234  
   235  func TestExecute_NoContext(t *testing.T) {
   236  	run := func(cmd *Command, args []string) {
   237  		if cmd.Context() != context.Background() {
   238  			t.Errorf("Command %s must have background context", cmd.Use)
   239  		}
   240  	}
   241  
   242  	rootCmd := &Command{Use: "root", Run: run, PreRun: run}
   243  	childCmd := &Command{Use: "child", Run: run, PreRun: run}
   244  	granchildCmd := &Command{Use: "grandchild", Run: run, PreRun: run}
   245  
   246  	childCmd.AddCommand(granchildCmd)
   247  	rootCmd.AddCommand(childCmd)
   248  
   249  	if _, err := executeCommand(rootCmd, ""); err != nil {
   250  		t.Errorf("Root command must not fail: %+v", err)
   251  	}
   252  
   253  	if _, err := executeCommand(rootCmd, "child"); err != nil {
   254  		t.Errorf("Subcommand must not fail: %+v", err)
   255  	}
   256  
   257  	if _, err := executeCommand(rootCmd, "child", "grandchild"); err != nil {
   258  		t.Errorf("Command child must not fail: %+v", err)
   259  	}
   260  }
   261  
   262  func TestRootUnknownCommandSilenced(t *testing.T) {
   263  	rootCmd := &Command{Use: "root", Run: emptyRun}
   264  	rootCmd.SilenceErrors = true
   265  	rootCmd.SilenceUsage = true
   266  	rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
   267  
   268  	output, _ := executeCommand(rootCmd, "unknown")
   269  	if output != "" {
   270  		t.Errorf("Expected blank output, because of silenced usage.\nGot:\n %q\n", output)
   271  	}
   272  }
   273  
   274  func TestCommandAlias(t *testing.T) {
   275  	var timesCmdArgs []string
   276  	rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
   277  	echoCmd := &Command{
   278  		Use:     "echo",
   279  		Aliases: []string{"say", "tell"},
   280  		Args:    NoArgs,
   281  		Run:     emptyRun,
   282  	}
   283  	timesCmd := &Command{
   284  		Use:  "times",
   285  		Args: ExactArgs(2),
   286  		Run:  func(_ *Command, args []string) { timesCmdArgs = args },
   287  	}
   288  	echoCmd.AddCommand(timesCmd)
   289  	rootCmd.AddCommand(echoCmd)
   290  
   291  	output, err := executeCommand(rootCmd, "tell", "times", "one", "two")
   292  	if output != "" {
   293  		t.Errorf("Unexpected output: %v", output)
   294  	}
   295  	if err != nil {
   296  		t.Errorf("Unexpected error: %v", err)
   297  	}
   298  
   299  	got := strings.Join(timesCmdArgs, " ")
   300  	if got != onetwo {
   301  		t.Errorf("timesCmdArgs expected: %v, got: %v", onetwo, got)
   302  	}
   303  }
   304  
   305  func TestEnablePrefixMatching(t *testing.T) {
   306  	EnablePrefixMatching = true
   307  
   308  	var aCmdArgs []string
   309  	rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
   310  	aCmd := &Command{
   311  		Use:  "aCmd",
   312  		Args: ExactArgs(2),
   313  		Run:  func(_ *Command, args []string) { aCmdArgs = args },
   314  	}
   315  	bCmd := &Command{Use: "bCmd", Args: NoArgs, Run: emptyRun}
   316  	rootCmd.AddCommand(aCmd, bCmd)
   317  
   318  	output, err := executeCommand(rootCmd, "a", "one", "two")
   319  	if output != "" {
   320  		t.Errorf("Unexpected output: %v", output)
   321  	}
   322  	if err != nil {
   323  		t.Errorf("Unexpected error: %v", err)
   324  	}
   325  
   326  	got := strings.Join(aCmdArgs, " ")
   327  	if got != onetwo {
   328  		t.Errorf("aCmdArgs expected: %q, got: %q", onetwo, got)
   329  	}
   330  
   331  	EnablePrefixMatching = defaultPrefixMatching
   332  }
   333  
   334  func TestAliasPrefixMatching(t *testing.T) {
   335  	EnablePrefixMatching = true
   336  
   337  	var timesCmdArgs []string
   338  	rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
   339  	echoCmd := &Command{
   340  		Use:     "echo",
   341  		Aliases: []string{"say", "tell"},
   342  		Args:    NoArgs,
   343  		Run:     emptyRun,
   344  	}
   345  	timesCmd := &Command{
   346  		Use:  "times",
   347  		Args: ExactArgs(2),
   348  		Run:  func(_ *Command, args []string) { timesCmdArgs = args },
   349  	}
   350  	echoCmd.AddCommand(timesCmd)
   351  	rootCmd.AddCommand(echoCmd)
   352  
   353  	output, err := executeCommand(rootCmd, "sa", "times", "one", "two")
   354  	if output != "" {
   355  		t.Errorf("Unexpected output: %v", output)
   356  	}
   357  	if err != nil {
   358  		t.Errorf("Unexpected error: %v", err)
   359  	}
   360  
   361  	got := strings.Join(timesCmdArgs, " ")
   362  	if got != onetwo {
   363  		t.Errorf("timesCmdArgs expected: %v, got: %v", onetwo, got)
   364  	}
   365  
   366  	EnablePrefixMatching = defaultPrefixMatching
   367  }
   368  
   369  // TestChildSameName checks the correct behaviour of cobra in cases,
   370  // when an application with name "foo" and with subcommand "foo"
   371  // is executed with args "foo foo".
   372  func TestChildSameName(t *testing.T) {
   373  	var fooCmdArgs []string
   374  	rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun}
   375  	fooCmd := &Command{
   376  		Use:  "foo",
   377  		Args: ExactArgs(2),
   378  		Run:  func(_ *Command, args []string) { fooCmdArgs = args },
   379  	}
   380  	barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun}
   381  	rootCmd.AddCommand(fooCmd, barCmd)
   382  
   383  	output, err := executeCommand(rootCmd, "foo", "one", "two")
   384  	if output != "" {
   385  		t.Errorf("Unexpected output: %v", output)
   386  	}
   387  	if err != nil {
   388  		t.Errorf("Unexpected error: %v", err)
   389  	}
   390  
   391  	got := strings.Join(fooCmdArgs, " ")
   392  	if got != onetwo {
   393  		t.Errorf("fooCmdArgs expected: %v, got: %v", onetwo, got)
   394  	}
   395  }
   396  
   397  // TestGrandChildSameName checks the correct behaviour of cobra in cases,
   398  // when user has a root command and a grand child
   399  // with the same name.
   400  func TestGrandChildSameName(t *testing.T) {
   401  	var fooCmdArgs []string
   402  	rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun}
   403  	barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun}
   404  	fooCmd := &Command{
   405  		Use:  "foo",
   406  		Args: ExactArgs(2),
   407  		Run:  func(_ *Command, args []string) { fooCmdArgs = args },
   408  	}
   409  	barCmd.AddCommand(fooCmd)
   410  	rootCmd.AddCommand(barCmd)
   411  
   412  	output, err := executeCommand(rootCmd, "bar", "foo", "one", "two")
   413  	if output != "" {
   414  		t.Errorf("Unexpected output: %v", output)
   415  	}
   416  	if err != nil {
   417  		t.Errorf("Unexpected error: %v", err)
   418  	}
   419  
   420  	got := strings.Join(fooCmdArgs, " ")
   421  	if got != onetwo {
   422  		t.Errorf("fooCmdArgs expected: %v, got: %v", onetwo, got)
   423  	}
   424  }
   425  
   426  func TestFlagLong(t *testing.T) {
   427  	var cArgs []string
   428  	c := &Command{
   429  		Use:  "c",
   430  		Args: ArbitraryArgs,
   431  		Run:  func(_ *Command, args []string) { cArgs = args },
   432  	}
   433  
   434  	var intFlagValue int
   435  	var stringFlagValue string
   436  	c.Flags().IntVar(&intFlagValue, "intf", -1, "")
   437  	c.Flags().StringVar(&stringFlagValue, "sf", "", "")
   438  
   439  	output, err := executeCommand(c, "--intf=7", "--sf=abc", "one", "--", "two")
   440  	if output != "" {
   441  		t.Errorf("Unexpected output: %v", err)
   442  	}
   443  	if err != nil {
   444  		t.Errorf("Unexpected error: %v", err)
   445  	}
   446  
   447  	if c.ArgsLenAtDash() != 1 {
   448  		t.Errorf("Expected ArgsLenAtDash: %v but got %v", 1, c.ArgsLenAtDash())
   449  	}
   450  	if intFlagValue != 7 {
   451  		t.Errorf("Expected intFlagValue: %v, got %v", 7, intFlagValue)
   452  	}
   453  	if stringFlagValue != "abc" {
   454  		t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue)
   455  	}
   456  
   457  	got := strings.Join(cArgs, " ")
   458  	if got != onetwo {
   459  		t.Errorf("rootCmdArgs expected: %q, got: %q", onetwo, got)
   460  	}
   461  }
   462  
   463  func TestFlagShort(t *testing.T) {
   464  	var cArgs []string
   465  	c := &Command{
   466  		Use:  "c",
   467  		Args: ArbitraryArgs,
   468  		Run:  func(_ *Command, args []string) { cArgs = args },
   469  	}
   470  
   471  	var intFlagValue int
   472  	var stringFlagValue string
   473  	c.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
   474  	c.Flags().StringVarP(&stringFlagValue, "sf", "s", "", "")
   475  
   476  	output, err := executeCommand(c, "-i", "7", "-sabc", "one", "two")
   477  	if output != "" {
   478  		t.Errorf("Unexpected output: %v", err)
   479  	}
   480  	if err != nil {
   481  		t.Errorf("Unexpected error: %v", err)
   482  	}
   483  
   484  	if intFlagValue != 7 {
   485  		t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
   486  	}
   487  	if stringFlagValue != "abc" {
   488  		t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue)
   489  	}
   490  
   491  	got := strings.Join(cArgs, " ")
   492  	if got != onetwo {
   493  		t.Errorf("rootCmdArgs expected: %q, got: %q", onetwo, got)
   494  	}
   495  }
   496  
   497  func TestChildFlag(t *testing.T) {
   498  	rootCmd := &Command{Use: "root", Run: emptyRun}
   499  	childCmd := &Command{Use: "child", Run: emptyRun}
   500  	rootCmd.AddCommand(childCmd)
   501  
   502  	var intFlagValue int
   503  	childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
   504  
   505  	output, err := executeCommand(rootCmd, "child", "-i7")
   506  	if output != "" {
   507  		t.Errorf("Unexpected output: %v", err)
   508  	}
   509  	if err != nil {
   510  		t.Errorf("Unexpected error: %v", err)
   511  	}
   512  
   513  	if intFlagValue != 7 {
   514  		t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
   515  	}
   516  }
   517  
   518  func TestChildFlagWithParentLocalFlag(t *testing.T) {
   519  	rootCmd := &Command{Use: "root", Run: emptyRun}
   520  	childCmd := &Command{Use: "child", Run: emptyRun}
   521  	rootCmd.AddCommand(childCmd)
   522  
   523  	var intFlagValue int
   524  	rootCmd.Flags().StringP("sf", "s", "", "")
   525  	childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
   526  
   527  	_, err := executeCommand(rootCmd, "child", "-i7", "-sabc")
   528  	if err == nil {
   529  		t.Errorf("Invalid flag should generate error")
   530  	}
   531  
   532  	checkStringContains(t, err.Error(), "unknown shorthand")
   533  
   534  	if intFlagValue != 7 {
   535  		t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
   536  	}
   537  }
   538  
   539  func TestFlagInvalidInput(t *testing.T) {
   540  	rootCmd := &Command{Use: "root", Run: emptyRun}
   541  	rootCmd.Flags().IntP("intf", "i", -1, "")
   542  
   543  	_, err := executeCommand(rootCmd, "-iabc")
   544  	if err == nil {
   545  		t.Errorf("Invalid flag value should generate error")
   546  	}
   547  
   548  	checkStringContains(t, err.Error(), "invalid syntax")
   549  }
   550  
   551  func TestFlagBeforeCommand(t *testing.T) {
   552  	rootCmd := &Command{Use: "root", Run: emptyRun}
   553  	childCmd := &Command{Use: "child", Run: emptyRun}
   554  	rootCmd.AddCommand(childCmd)
   555  
   556  	var flagValue int
   557  	childCmd.Flags().IntVarP(&flagValue, "intf", "i", -1, "")
   558  
   559  	// With short flag.
   560  	_, err := executeCommand(rootCmd, "-i7", "child")
   561  	if err != nil {
   562  		t.Errorf("Unexpected error: %v", err)
   563  	}
   564  	if flagValue != 7 {
   565  		t.Errorf("Expected flag value: %v, got %v", 7, flagValue)
   566  	}
   567  
   568  	// With long flag.
   569  	_, err = executeCommand(rootCmd, "--intf=8", "child")
   570  	if err != nil {
   571  		t.Errorf("Unexpected error: %v", err)
   572  	}
   573  	if flagValue != 8 {
   574  		t.Errorf("Expected flag value: %v, got %v", 9, flagValue)
   575  	}
   576  }
   577  
   578  func TestStripFlags(t *testing.T) {
   579  	tests := []struct {
   580  		input  []string
   581  		output []string
   582  	}{
   583  		{
   584  			[]string{"foo", "bar"},
   585  			[]string{"foo", "bar"},
   586  		},
   587  		{
   588  			[]string{"foo", "--str", "-s"},
   589  			[]string{"foo"},
   590  		},
   591  		{
   592  			[]string{"-s", "foo", "--str", "bar"},
   593  			[]string{},
   594  		},
   595  		{
   596  			[]string{"-i10", "echo"},
   597  			[]string{"echo"},
   598  		},
   599  		{
   600  			[]string{"-i=10", "echo"},
   601  			[]string{"echo"},
   602  		},
   603  		{
   604  			[]string{"--int=100", "echo"},
   605  			[]string{"echo"},
   606  		},
   607  		{
   608  			[]string{"-ib", "echo", "-sfoo", "baz"},
   609  			[]string{"echo", "baz"},
   610  		},
   611  		{
   612  			[]string{"-i=baz", "bar", "-i", "foo", "blah"},
   613  			[]string{"bar", "blah"},
   614  		},
   615  		{
   616  			[]string{"--int=baz", "-sbar", "-i", "foo", "blah"},
   617  			[]string{"blah"},
   618  		},
   619  		{
   620  			[]string{"--bool", "bar", "-i", "foo", "blah"},
   621  			[]string{"bar", "blah"},
   622  		},
   623  		{
   624  			[]string{"-b", "bar", "-i", "foo", "blah"},
   625  			[]string{"bar", "blah"},
   626  		},
   627  		{
   628  			[]string{"--persist", "bar"},
   629  			[]string{"bar"},
   630  		},
   631  		{
   632  			[]string{"-p", "bar"},
   633  			[]string{"bar"},
   634  		},
   635  	}
   636  
   637  	c := &Command{Use: "c", Run: emptyRun}
   638  	c.PersistentFlags().BoolP("persist", "p", false, "")
   639  	c.Flags().IntP("int", "i", -1, "")
   640  	c.Flags().StringP("str", "s", "", "")
   641  	c.Flags().BoolP("bool", "b", false, "")
   642  
   643  	for i, test := range tests {
   644  		got := stripFlags(test.input, c)
   645  		if !reflect.DeepEqual(test.output, got) {
   646  			t.Errorf("(%v) Expected: %v, got: %v", i, test.output, got)
   647  		}
   648  	}
   649  }
   650  
   651  func TestDisableFlagParsing(t *testing.T) {
   652  	var cArgs []string
   653  	c := &Command{
   654  		Use:                "c",
   655  		DisableFlagParsing: true,
   656  		Run: func(_ *Command, args []string) {
   657  			cArgs = args
   658  		},
   659  	}
   660  
   661  	args := []string{"cmd", "-v", "-race", "-file", "foo.go"}
   662  	output, err := executeCommand(c, args...)
   663  	if output != "" {
   664  		t.Errorf("Unexpected output: %v", output)
   665  	}
   666  	if err != nil {
   667  		t.Errorf("Unexpected error: %v", err)
   668  	}
   669  
   670  	if !reflect.DeepEqual(args, cArgs) {
   671  		t.Errorf("Expected: %v, got: %v", args, cArgs)
   672  	}
   673  }
   674  
   675  func TestPersistentFlagsOnSameCommand(t *testing.T) {
   676  	var rootCmdArgs []string
   677  	rootCmd := &Command{
   678  		Use:  "root",
   679  		Args: ArbitraryArgs,
   680  		Run:  func(_ *Command, args []string) { rootCmdArgs = args },
   681  	}
   682  
   683  	var flagValue int
   684  	rootCmd.PersistentFlags().IntVarP(&flagValue, "intf", "i", -1, "")
   685  
   686  	output, err := executeCommand(rootCmd, "-i7", "one", "two")
   687  	if output != "" {
   688  		t.Errorf("Unexpected output: %v", output)
   689  	}
   690  	if err != nil {
   691  		t.Errorf("Unexpected error: %v", err)
   692  	}
   693  
   694  	got := strings.Join(rootCmdArgs, " ")
   695  	if got != onetwo {
   696  		t.Errorf("rootCmdArgs expected: %q, got %q", onetwo, got)
   697  	}
   698  	if flagValue != 7 {
   699  		t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
   700  	}
   701  }
   702  
   703  // TestEmptyInputs checks,
   704  // if flags correctly parsed with blank strings in args.
   705  func TestEmptyInputs(t *testing.T) {
   706  	c := &Command{Use: "c", Run: emptyRun}
   707  
   708  	var flagValue int
   709  	c.Flags().IntVarP(&flagValue, "intf", "i", -1, "")
   710  
   711  	output, err := executeCommand(c, "", "-i7", "")
   712  	if output != "" {
   713  		t.Errorf("Unexpected output: %v", output)
   714  	}
   715  	if err != nil {
   716  		t.Errorf("Unexpected error: %v", err)
   717  	}
   718  
   719  	if flagValue != 7 {
   720  		t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
   721  	}
   722  }
   723  
   724  func TestChildFlagShadowsParentPersistentFlag(t *testing.T) {
   725  	parent := &Command{Use: "parent", Run: emptyRun}
   726  	child := &Command{Use: "child", Run: emptyRun}
   727  
   728  	parent.PersistentFlags().Bool("boolf", false, "")
   729  	parent.PersistentFlags().Int("intf", -1, "")
   730  	child.Flags().String("strf", "", "")
   731  	child.Flags().Int("intf", -1, "")
   732  
   733  	parent.AddCommand(child)
   734  
   735  	childInherited := child.InheritedFlags()
   736  	childLocal := child.LocalFlags()
   737  
   738  	if childLocal.Lookup("strf") == nil {
   739  		t.Error(`LocalFlags expected to contain "strf", got "nil"`)
   740  	}
   741  	if childInherited.Lookup("boolf") == nil {
   742  		t.Error(`InheritedFlags expected to contain "boolf", got "nil"`)
   743  	}
   744  
   745  	if childInherited.Lookup("intf") != nil {
   746  		t.Errorf(`InheritedFlags should not contain shadowed flag "intf"`)
   747  	}
   748  	if childLocal.Lookup("intf") == nil {
   749  		t.Error(`LocalFlags expected to contain "intf", got "nil"`)
   750  	}
   751  }
   752  
   753  func TestPersistentFlagsOnChild(t *testing.T) {
   754  	var childCmdArgs []string
   755  	rootCmd := &Command{Use: "root", Run: emptyRun}
   756  	childCmd := &Command{
   757  		Use:  "child",
   758  		Args: ArbitraryArgs,
   759  		Run:  func(_ *Command, args []string) { childCmdArgs = args },
   760  	}
   761  	rootCmd.AddCommand(childCmd)
   762  
   763  	var parentFlagValue int
   764  	var childFlagValue int
   765  	rootCmd.PersistentFlags().IntVarP(&parentFlagValue, "parentf", "p", -1, "")
   766  	childCmd.Flags().IntVarP(&childFlagValue, "childf", "c", -1, "")
   767  
   768  	output, err := executeCommand(rootCmd, "child", "-c7", "-p8", "one", "two")
   769  	if output != "" {
   770  		t.Errorf("Unexpected output: %v", output)
   771  	}
   772  	if err != nil {
   773  		t.Errorf("Unexpected error: %v", err)
   774  	}
   775  
   776  	got := strings.Join(childCmdArgs, " ")
   777  	if got != onetwo {
   778  		t.Errorf("rootCmdArgs expected: %q, got: %q", onetwo, got)
   779  	}
   780  	if parentFlagValue != 8 {
   781  		t.Errorf("parentFlagValue expected: %v, got %v", 8, parentFlagValue)
   782  	}
   783  	if childFlagValue != 7 {
   784  		t.Errorf("childFlagValue expected: %v, got %v", 7, childFlagValue)
   785  	}
   786  }
   787  
   788  func TestRequiredFlags(t *testing.T) {
   789  	c := &Command{Use: "c", Run: emptyRun}
   790  	c.Flags().String("foo1", "", "")
   791  	assertNoErr(t, c.MarkFlagRequired("foo1"))
   792  	c.Flags().String("foo2", "", "")
   793  	assertNoErr(t, c.MarkFlagRequired("foo2"))
   794  	c.Flags().String("bar", "", "")
   795  
   796  	expected := fmt.Sprintf("required flag(s) %q, %q not set", "foo1", "foo2")
   797  
   798  	_, err := executeCommand(c)
   799  	got := err.Error()
   800  
   801  	if got != expected {
   802  		t.Errorf("Expected error: %q, got: %q", expected, got)
   803  	}
   804  }
   805  
   806  func TestPersistentRequiredFlags(t *testing.T) {
   807  	parent := &Command{Use: "parent", Run: emptyRun}
   808  	parent.PersistentFlags().String("foo1", "", "")
   809  	assertNoErr(t, parent.MarkPersistentFlagRequired("foo1"))
   810  	parent.PersistentFlags().String("foo2", "", "")
   811  	assertNoErr(t, parent.MarkPersistentFlagRequired("foo2"))
   812  	parent.Flags().String("foo3", "", "")
   813  
   814  	child := &Command{Use: "child", Run: emptyRun}
   815  	child.Flags().String("bar1", "", "")
   816  	assertNoErr(t, child.MarkFlagRequired("bar1"))
   817  	child.Flags().String("bar2", "", "")
   818  	assertNoErr(t, child.MarkFlagRequired("bar2"))
   819  	child.Flags().String("bar3", "", "")
   820  
   821  	parent.AddCommand(child)
   822  
   823  	expected := fmt.Sprintf("required flag(s) %q, %q, %q, %q not set", "bar1", "bar2", "foo1", "foo2")
   824  
   825  	_, err := executeCommand(parent, "child")
   826  	if err.Error() != expected {
   827  		t.Errorf("Expected %q, got %q", expected, err.Error())
   828  	}
   829  }
   830  
   831  func TestPersistentRequiredFlagsWithDisableFlagParsing(t *testing.T) {
   832  	// Make sure a required persistent flag does not break
   833  	// commands that disable flag parsing
   834  
   835  	parent := &Command{Use: "parent", Run: emptyRun}
   836  	parent.PersistentFlags().Bool("foo", false, "")
   837  	flag := parent.PersistentFlags().Lookup("foo")
   838  	assertNoErr(t, parent.MarkPersistentFlagRequired("foo"))
   839  
   840  	child := &Command{Use: "child", Run: emptyRun}
   841  	child.DisableFlagParsing = true
   842  
   843  	parent.AddCommand(child)
   844  
   845  	if _, err := executeCommand(parent, "--foo", "child"); err != nil {
   846  		t.Errorf("Unexpected error: %v", err)
   847  	}
   848  
   849  	// Reset the flag or else it will remember the state from the previous command
   850  	flag.Changed = false
   851  	if _, err := executeCommand(parent, "child", "--foo"); err != nil {
   852  		t.Errorf("Unexpected error: %v", err)
   853  	}
   854  
   855  	// Reset the flag or else it will remember the state from the previous command
   856  	flag.Changed = false
   857  	if _, err := executeCommand(parent, "child"); err != nil {
   858  		t.Errorf("Unexpected error: %v", err)
   859  	}
   860  }
   861  
   862  func TestInitHelpFlagMergesFlags(t *testing.T) {
   863  	usage := "custom flag"
   864  	rootCmd := &Command{Use: "root"}
   865  	rootCmd.PersistentFlags().Bool("help", false, "custom flag")
   866  	childCmd := &Command{Use: "child"}
   867  	rootCmd.AddCommand(childCmd)
   868  
   869  	childCmd.InitDefaultHelpFlag()
   870  	got := childCmd.Flags().Lookup("help").Usage
   871  	if got != usage {
   872  		t.Errorf("Expected the help flag from the root command with usage: %v\nGot the default with usage: %v", usage, got)
   873  	}
   874  }
   875  
   876  func TestHelpCommandExecuted(t *testing.T) {
   877  	rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
   878  	rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
   879  
   880  	output, err := executeCommand(rootCmd, "help")
   881  	if err != nil {
   882  		t.Errorf("Unexpected error: %v", err)
   883  	}
   884  
   885  	checkStringContains(t, output, rootCmd.Long)
   886  }
   887  
   888  func TestHelpCommandExecutedOnChild(t *testing.T) {
   889  	rootCmd := &Command{Use: "root", Run: emptyRun}
   890  	childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun}
   891  	rootCmd.AddCommand(childCmd)
   892  
   893  	output, err := executeCommand(rootCmd, "help", "child")
   894  	if err != nil {
   895  		t.Errorf("Unexpected error: %v", err)
   896  	}
   897  
   898  	checkStringContains(t, output, childCmd.Long)
   899  }
   900  
   901  func TestHelpCommandExecutedOnChildWithFlagThatShadowsParentFlag(t *testing.T) {
   902  	parent := &Command{Use: "parent", Run: emptyRun}
   903  	child := &Command{Use: "child", Run: emptyRun}
   904  	parent.AddCommand(child)
   905  
   906  	parent.PersistentFlags().Bool("foo", false, "parent foo usage")
   907  	parent.PersistentFlags().Bool("bar", false, "parent bar usage")
   908  	child.Flags().Bool("foo", false, "child foo usage") // This shadows parent's foo flag
   909  	child.Flags().Bool("baz", false, "child baz usage")
   910  
   911  	got, err := executeCommand(parent, "help", "child")
   912  	if err != nil {
   913  		t.Errorf("Unexpected error: %v", err)
   914  	}
   915  
   916  	expected := `Usage:
   917    parent child [flags]
   918  
   919  Flags:
   920        --baz    child baz usage
   921        --foo    child foo usage
   922    -h, --help   help for child
   923  
   924  Global Flags:
   925        --bar   parent bar usage
   926  `
   927  
   928  	if got != expected {
   929  		t.Errorf("Help text mismatch.\nExpected:\n%s\n\nGot:\n%s\n", expected, got)
   930  	}
   931  }
   932  
   933  func TestSetHelpCommand(t *testing.T) {
   934  	c := &Command{Use: "c", Run: emptyRun}
   935  	c.AddCommand(&Command{Use: "empty", Run: emptyRun})
   936  
   937  	expected := "WORKS"
   938  	c.SetHelpCommand(&Command{
   939  		Use:   "help [command]",
   940  		Short: "Help about any command",
   941  		Long: `Help provides help for any command in the application.
   942  	Simply type ` + c.Name() + ` help [path to command] for full details.`,
   943  		Run: func(c *Command, _ []string) { c.Print(expected) },
   944  	})
   945  
   946  	got, err := executeCommand(c, "help")
   947  	if err != nil {
   948  		t.Errorf("Unexpected error: %v", err)
   949  	}
   950  
   951  	if got != expected {
   952  		t.Errorf("Expected to contain %q, got %q", expected, got)
   953  	}
   954  }
   955  
   956  func TestHelpFlagExecuted(t *testing.T) {
   957  	rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
   958  
   959  	output, err := executeCommand(rootCmd, "--help")
   960  	if err != nil {
   961  		t.Errorf("Unexpected error: %v", err)
   962  	}
   963  
   964  	checkStringContains(t, output, rootCmd.Long)
   965  }
   966  
   967  func TestHelpFlagExecutedOnChild(t *testing.T) {
   968  	rootCmd := &Command{Use: "root", Run: emptyRun}
   969  	childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun}
   970  	rootCmd.AddCommand(childCmd)
   971  
   972  	output, err := executeCommand(rootCmd, "child", "--help")
   973  	if err != nil {
   974  		t.Errorf("Unexpected error: %v", err)
   975  	}
   976  
   977  	checkStringContains(t, output, childCmd.Long)
   978  }
   979  
   980  // TestHelpFlagInHelp checks,
   981  // if '--help' flag is shown in help for child (executing `parent help child`),
   982  // that has no other flags.
   983  // Related to https://github.com/spf13/cobra/issues/302.
   984  func TestHelpFlagInHelp(t *testing.T) {
   985  	parentCmd := &Command{Use: "parent", Run: func(*Command, []string) {}}
   986  
   987  	childCmd := &Command{Use: "child", Run: func(*Command, []string) {}}
   988  	parentCmd.AddCommand(childCmd)
   989  
   990  	output, err := executeCommand(parentCmd, "help", "child")
   991  	if err != nil {
   992  		t.Errorf("Unexpected error: %v", err)
   993  	}
   994  
   995  	checkStringContains(t, output, "[flags]")
   996  }
   997  
   998  func TestFlagsInUsage(t *testing.T) {
   999  	rootCmd := &Command{Use: "root", Args: NoArgs, Run: func(*Command, []string) {}}
  1000  	output, err := executeCommand(rootCmd, "--help")
  1001  	if err != nil {
  1002  		t.Errorf("Unexpected error: %v", err)
  1003  	}
  1004  
  1005  	checkStringContains(t, output, "[flags]")
  1006  }
  1007  
  1008  func TestHelpExecutedOnNonRunnableChild(t *testing.T) {
  1009  	rootCmd := &Command{Use: "root", Run: emptyRun}
  1010  	childCmd := &Command{Use: "child", Long: "Long description"}
  1011  	rootCmd.AddCommand(childCmd)
  1012  
  1013  	output, err := executeCommand(rootCmd, "child")
  1014  	if err != nil {
  1015  		t.Errorf("Unexpected error: %v", err)
  1016  	}
  1017  
  1018  	checkStringContains(t, output, childCmd.Long)
  1019  }
  1020  
  1021  func TestVersionFlagExecuted(t *testing.T) {
  1022  	rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  1023  
  1024  	output, err := executeCommand(rootCmd, "--version", "arg1")
  1025  	if err != nil {
  1026  		t.Errorf("Unexpected error: %v", err)
  1027  	}
  1028  
  1029  	checkStringContains(t, output, "root version 1.0.0")
  1030  }
  1031  
  1032  func TestVersionFlagExecutedWithNoName(t *testing.T) {
  1033  	rootCmd := &Command{Version: "1.0.0", Run: emptyRun}
  1034  
  1035  	output, err := executeCommand(rootCmd, "--version", "arg1")
  1036  	if err != nil {
  1037  		t.Errorf("Unexpected error: %v", err)
  1038  	}
  1039  
  1040  	checkStringContains(t, output, "version 1.0.0")
  1041  }
  1042  
  1043  func TestShortAndLongVersionFlagInHelp(t *testing.T) {
  1044  	rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  1045  
  1046  	output, err := executeCommand(rootCmd, "--help")
  1047  	if err != nil {
  1048  		t.Errorf("Unexpected error: %v", err)
  1049  	}
  1050  
  1051  	checkStringContains(t, output, "-v, --version")
  1052  }
  1053  
  1054  func TestLongVersionFlagOnlyInHelpWhenShortPredefined(t *testing.T) {
  1055  	rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  1056  	rootCmd.Flags().StringP("foo", "v", "", "not a version flag")
  1057  
  1058  	output, err := executeCommand(rootCmd, "--help")
  1059  	if err != nil {
  1060  		t.Errorf("Unexpected error: %v", err)
  1061  	}
  1062  
  1063  	checkStringOmits(t, output, "-v, --version")
  1064  	checkStringContains(t, output, "--version")
  1065  }
  1066  
  1067  func TestShorthandVersionFlagExecuted(t *testing.T) {
  1068  	rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  1069  
  1070  	output, err := executeCommand(rootCmd, "-v", "arg1")
  1071  	if err != nil {
  1072  		t.Errorf("Unexpected error: %v", err)
  1073  	}
  1074  
  1075  	checkStringContains(t, output, "root version 1.0.0")
  1076  }
  1077  
  1078  func TestVersionTemplate(t *testing.T) {
  1079  	rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  1080  	rootCmd.SetVersionTemplate(`customized version: {{.Version}}`)
  1081  
  1082  	output, err := executeCommand(rootCmd, "--version", "arg1")
  1083  	if err != nil {
  1084  		t.Errorf("Unexpected error: %v", err)
  1085  	}
  1086  
  1087  	checkStringContains(t, output, "customized version: 1.0.0")
  1088  }
  1089  
  1090  func TestShorthandVersionTemplate(t *testing.T) {
  1091  	rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  1092  	rootCmd.SetVersionTemplate(`customized version: {{.Version}}`)
  1093  
  1094  	output, err := executeCommand(rootCmd, "-v", "arg1")
  1095  	if err != nil {
  1096  		t.Errorf("Unexpected error: %v", err)
  1097  	}
  1098  
  1099  	checkStringContains(t, output, "customized version: 1.0.0")
  1100  }
  1101  
  1102  func TestVersionFlagExecutedOnSubcommand(t *testing.T) {
  1103  	rootCmd := &Command{Use: "root", Version: "1.0.0"}
  1104  	rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
  1105  
  1106  	output, err := executeCommand(rootCmd, "--version", "sub")
  1107  	if err != nil {
  1108  		t.Errorf("Unexpected error: %v", err)
  1109  	}
  1110  
  1111  	checkStringContains(t, output, "root version 1.0.0")
  1112  }
  1113  
  1114  func TestShorthandVersionFlagExecutedOnSubcommand(t *testing.T) {
  1115  	rootCmd := &Command{Use: "root", Version: "1.0.0"}
  1116  	rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
  1117  
  1118  	output, err := executeCommand(rootCmd, "-v", "sub")
  1119  	if err != nil {
  1120  		t.Errorf("Unexpected error: %v", err)
  1121  	}
  1122  
  1123  	checkStringContains(t, output, "root version 1.0.0")
  1124  }
  1125  
  1126  func TestVersionFlagOnlyAddedToRoot(t *testing.T) {
  1127  	rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  1128  	rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
  1129  
  1130  	_, err := executeCommand(rootCmd, "sub", "--version")
  1131  	if err == nil {
  1132  		t.Errorf("Expected error")
  1133  	}
  1134  
  1135  	checkStringContains(t, err.Error(), "unknown flag: --version")
  1136  }
  1137  
  1138  func TestShortVersionFlagOnlyAddedToRoot(t *testing.T) {
  1139  	rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  1140  	rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
  1141  
  1142  	_, err := executeCommand(rootCmd, "sub", "-v")
  1143  	if err == nil {
  1144  		t.Errorf("Expected error")
  1145  	}
  1146  
  1147  	checkStringContains(t, err.Error(), "unknown shorthand flag: 'v' in -v")
  1148  }
  1149  
  1150  func TestVersionFlagOnlyExistsIfVersionNonEmpty(t *testing.T) {
  1151  	rootCmd := &Command{Use: "root", Run: emptyRun}
  1152  
  1153  	_, err := executeCommand(rootCmd, "--version")
  1154  	if err == nil {
  1155  		t.Errorf("Expected error")
  1156  	}
  1157  	checkStringContains(t, err.Error(), "unknown flag: --version")
  1158  }
  1159  
  1160  func TestShorthandVersionFlagOnlyExistsIfVersionNonEmpty(t *testing.T) {
  1161  	rootCmd := &Command{Use: "root", Run: emptyRun}
  1162  
  1163  	_, err := executeCommand(rootCmd, "-v")
  1164  	if err == nil {
  1165  		t.Errorf("Expected error")
  1166  	}
  1167  	checkStringContains(t, err.Error(), "unknown shorthand flag: 'v' in -v")
  1168  }
  1169  
  1170  func TestShorthandVersionFlagOnlyAddedIfShorthandNotDefined(t *testing.T) {
  1171  	rootCmd := &Command{Use: "root", Run: emptyRun, Version: "1.2.3"}
  1172  	rootCmd.Flags().StringP("notversion", "v", "", "not a version flag")
  1173  
  1174  	_, err := executeCommand(rootCmd, "-v")
  1175  	if err == nil {
  1176  		t.Errorf("Expected error")
  1177  	}
  1178  	check(t, rootCmd.Flags().ShorthandLookup("v").Name, "notversion")
  1179  	checkStringContains(t, err.Error(), "flag needs an argument: 'v' in -v")
  1180  }
  1181  
  1182  func TestShorthandVersionFlagOnlyAddedIfVersionNotDefined(t *testing.T) {
  1183  	rootCmd := &Command{Use: "root", Run: emptyRun, Version: "1.2.3"}
  1184  	rootCmd.Flags().Bool("version", false, "a different kind of version flag")
  1185  
  1186  	_, err := executeCommand(rootCmd, "-v")
  1187  	if err == nil {
  1188  		t.Errorf("Expected error")
  1189  	}
  1190  	checkStringContains(t, err.Error(), "unknown shorthand flag: 'v' in -v")
  1191  }
  1192  
  1193  func TestUsageIsNotPrintedTwice(t *testing.T) {
  1194  	var cmd = &Command{Use: "root"}
  1195  	var sub = &Command{Use: "sub"}
  1196  	cmd.AddCommand(sub)
  1197  
  1198  	output, _ := executeCommand(cmd, "")
  1199  	if strings.Count(output, "Usage:") != 1 {
  1200  		t.Error("Usage output is not printed exactly once")
  1201  	}
  1202  }
  1203  
  1204  func TestVisitParents(t *testing.T) {
  1205  	c := &Command{Use: "app"}
  1206  	sub := &Command{Use: "sub"}
  1207  	dsub := &Command{Use: "dsub"}
  1208  	sub.AddCommand(dsub)
  1209  	c.AddCommand(sub)
  1210  
  1211  	total := 0
  1212  	add := func(x *Command) {
  1213  		total++
  1214  	}
  1215  	sub.VisitParents(add)
  1216  	if total != 1 {
  1217  		t.Errorf("Should have visited 1 parent but visited %d", total)
  1218  	}
  1219  
  1220  	total = 0
  1221  	dsub.VisitParents(add)
  1222  	if total != 2 {
  1223  		t.Errorf("Should have visited 2 parents but visited %d", total)
  1224  	}
  1225  
  1226  	total = 0
  1227  	c.VisitParents(add)
  1228  	if total != 0 {
  1229  		t.Errorf("Should have visited no parents but visited %d", total)
  1230  	}
  1231  }
  1232  
  1233  func TestSuggestions(t *testing.T) {
  1234  	rootCmd := &Command{Use: "root", Run: emptyRun}
  1235  	timesCmd := &Command{
  1236  		Use:        "times",
  1237  		SuggestFor: []string{"counts"},
  1238  		Run:        emptyRun,
  1239  	}
  1240  	rootCmd.AddCommand(timesCmd)
  1241  
  1242  	templateWithSuggestions := "Error: unknown command \"%s\" for \"root\"\n\nDid you mean this?\n\t%s\n\nRun 'root --help' for usage.\n"
  1243  	templateWithoutSuggestions := "Error: unknown command \"%s\" for \"root\"\nRun 'root --help' for usage.\n"
  1244  
  1245  	tests := map[string]string{
  1246  		"time":     "times",
  1247  		"tiems":    "times",
  1248  		"tims":     "times",
  1249  		"timeS":    "times",
  1250  		"rimes":    "times",
  1251  		"ti":       "times",
  1252  		"t":        "times",
  1253  		"timely":   "times",
  1254  		"ri":       "",
  1255  		"timezone": "",
  1256  		"foo":      "",
  1257  		"counts":   "times",
  1258  	}
  1259  
  1260  	for typo, suggestion := range tests {
  1261  		for _, suggestionsDisabled := range []bool{true, false} {
  1262  			rootCmd.DisableSuggestions = suggestionsDisabled
  1263  
  1264  			var expected string
  1265  			output, _ := executeCommand(rootCmd, typo)
  1266  
  1267  			if suggestion == "" || suggestionsDisabled {
  1268  				expected = fmt.Sprintf(templateWithoutSuggestions, typo)
  1269  			} else {
  1270  				expected = fmt.Sprintf(templateWithSuggestions, typo, suggestion)
  1271  			}
  1272  
  1273  			if output != expected {
  1274  				t.Errorf("Unexpected response.\nExpected:\n %q\nGot:\n %q\n", expected, output)
  1275  			}
  1276  		}
  1277  	}
  1278  }
  1279  
  1280  func TestCaseInsensitive(t *testing.T) {
  1281  	rootCmd := &Command{Use: "root", Run: emptyRun}
  1282  	childCmd := &Command{Use: "child", Run: emptyRun, Aliases: []string{"alternative"}}
  1283  	granchildCmd := &Command{Use: "GRANDCHILD", Run: emptyRun, Aliases: []string{"ALIAS"}}
  1284  
  1285  	childCmd.AddCommand(granchildCmd)
  1286  	rootCmd.AddCommand(childCmd)
  1287  
  1288  	tests := []struct {
  1289  		args                []string
  1290  		failWithoutEnabling bool
  1291  	}{
  1292  		{
  1293  			args:                []string{"child"},
  1294  			failWithoutEnabling: false,
  1295  		},
  1296  		{
  1297  			args:                []string{"CHILD"},
  1298  			failWithoutEnabling: true,
  1299  		},
  1300  		{
  1301  			args:                []string{"chILD"},
  1302  			failWithoutEnabling: true,
  1303  		},
  1304  		{
  1305  			args:                []string{"CHIld"},
  1306  			failWithoutEnabling: true,
  1307  		},
  1308  		{
  1309  			args:                []string{"alternative"},
  1310  			failWithoutEnabling: false,
  1311  		},
  1312  		{
  1313  			args:                []string{"ALTERNATIVE"},
  1314  			failWithoutEnabling: true,
  1315  		},
  1316  		{
  1317  			args:                []string{"ALTernatIVE"},
  1318  			failWithoutEnabling: true,
  1319  		},
  1320  		{
  1321  			args:                []string{"alternatiVE"},
  1322  			failWithoutEnabling: true,
  1323  		},
  1324  		{
  1325  			args:                []string{"child", "GRANDCHILD"},
  1326  			failWithoutEnabling: false,
  1327  		},
  1328  		{
  1329  			args:                []string{"child", "grandchild"},
  1330  			failWithoutEnabling: true,
  1331  		},
  1332  		{
  1333  			args:                []string{"CHIld", "GRANdchild"},
  1334  			failWithoutEnabling: true,
  1335  		},
  1336  		{
  1337  			args:                []string{"alternative", "ALIAS"},
  1338  			failWithoutEnabling: false,
  1339  		},
  1340  		{
  1341  			args:                []string{"alternative", "alias"},
  1342  			failWithoutEnabling: true,
  1343  		},
  1344  		{
  1345  			args:                []string{"CHILD", "alias"},
  1346  			failWithoutEnabling: true,
  1347  		},
  1348  		{
  1349  			args:                []string{"CHIld", "aliAS"},
  1350  			failWithoutEnabling: true,
  1351  		},
  1352  	}
  1353  
  1354  	for _, test := range tests {
  1355  		for _, enableCaseInsensitivity := range []bool{true, false} {
  1356  			EnableCaseInsensitive = enableCaseInsensitivity
  1357  
  1358  			output, err := executeCommand(rootCmd, test.args...)
  1359  			expectedFailure := test.failWithoutEnabling && !enableCaseInsensitivity
  1360  
  1361  			if !expectedFailure && output != "" {
  1362  				t.Errorf("Unexpected output: %v", output)
  1363  			}
  1364  			if !expectedFailure && err != nil {
  1365  				t.Errorf("Unexpected error: %v", err)
  1366  			}
  1367  		}
  1368  	}
  1369  
  1370  	EnableCaseInsensitive = defaultCaseInsensitive
  1371  }
  1372  
  1373  // This test make sure we keep backwards-compatibility with respect
  1374  // to command names case sensitivity behavior.
  1375  func TestCaseSensitivityBackwardCompatibility(t *testing.T) {
  1376  	rootCmd := &Command{Use: "root", Run: emptyRun}
  1377  	childCmd := &Command{Use: "child", Run: emptyRun}
  1378  
  1379  	rootCmd.AddCommand(childCmd)
  1380  	_, err := executeCommand(rootCmd, strings.ToUpper(childCmd.Use))
  1381  	if err == nil {
  1382  		t.Error("Expected error on calling a command in upper case while command names are case sensitive. Got nil.")
  1383  	}
  1384  
  1385  }
  1386  
  1387  func TestRemoveCommand(t *testing.T) {
  1388  	rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
  1389  	childCmd := &Command{Use: "child", Run: emptyRun}
  1390  	rootCmd.AddCommand(childCmd)
  1391  	rootCmd.RemoveCommand(childCmd)
  1392  
  1393  	_, err := executeCommand(rootCmd, "child")
  1394  	if err == nil {
  1395  		t.Error("Expected error on calling removed command. Got nil.")
  1396  	}
  1397  }
  1398  
  1399  func TestReplaceCommandWithRemove(t *testing.T) {
  1400  	childUsed := 0
  1401  	rootCmd := &Command{Use: "root", Run: emptyRun}
  1402  	child1Cmd := &Command{
  1403  		Use: "child",
  1404  		Run: func(*Command, []string) { childUsed = 1 },
  1405  	}
  1406  	child2Cmd := &Command{
  1407  		Use: "child",
  1408  		Run: func(*Command, []string) { childUsed = 2 },
  1409  	}
  1410  	rootCmd.AddCommand(child1Cmd)
  1411  	rootCmd.RemoveCommand(child1Cmd)
  1412  	rootCmd.AddCommand(child2Cmd)
  1413  
  1414  	output, err := executeCommand(rootCmd, "child")
  1415  	if output != "" {
  1416  		t.Errorf("Unexpected output: %v", output)
  1417  	}
  1418  	if err != nil {
  1419  		t.Errorf("Unexpected error: %v", err)
  1420  	}
  1421  
  1422  	if childUsed == 1 {
  1423  		t.Error("Removed command shouldn't be called")
  1424  	}
  1425  	if childUsed != 2 {
  1426  		t.Error("Replacing command should have been called but didn't")
  1427  	}
  1428  }
  1429  
  1430  func TestDeprecatedCommand(t *testing.T) {
  1431  	rootCmd := &Command{Use: "root", Run: emptyRun}
  1432  	deprecatedCmd := &Command{
  1433  		Use:        "deprecated",
  1434  		Deprecated: "This command is deprecated",
  1435  		Run:        emptyRun,
  1436  	}
  1437  	rootCmd.AddCommand(deprecatedCmd)
  1438  
  1439  	output, err := executeCommand(rootCmd, "deprecated")
  1440  	if err != nil {
  1441  		t.Errorf("Unexpected error: %v", err)
  1442  	}
  1443  
  1444  	checkStringContains(t, output, deprecatedCmd.Deprecated)
  1445  }
  1446  
  1447  func TestHooks(t *testing.T) {
  1448  	var (
  1449  		persPreArgs  string
  1450  		preArgs      string
  1451  		runArgs      string
  1452  		postArgs     string
  1453  		persPostArgs string
  1454  	)
  1455  
  1456  	c := &Command{
  1457  		Use: "c",
  1458  		PersistentPreRun: func(_ *Command, args []string) {
  1459  			persPreArgs = strings.Join(args, " ")
  1460  		},
  1461  		PreRun: func(_ *Command, args []string) {
  1462  			preArgs = strings.Join(args, " ")
  1463  		},
  1464  		Run: func(_ *Command, args []string) {
  1465  			runArgs = strings.Join(args, " ")
  1466  		},
  1467  		PostRun: func(_ *Command, args []string) {
  1468  			postArgs = strings.Join(args, " ")
  1469  		},
  1470  		PersistentPostRun: func(_ *Command, args []string) {
  1471  			persPostArgs = strings.Join(args, " ")
  1472  		},
  1473  	}
  1474  
  1475  	output, err := executeCommand(c, "one", "two")
  1476  	if output != "" {
  1477  		t.Errorf("Unexpected output: %v", output)
  1478  	}
  1479  	if err != nil {
  1480  		t.Errorf("Unexpected error: %v", err)
  1481  	}
  1482  
  1483  	for _, v := range []struct {
  1484  		name string
  1485  		got  string
  1486  	}{
  1487  		{"persPreArgs", persPreArgs},
  1488  		{"preArgs", preArgs},
  1489  		{"runArgs", runArgs},
  1490  		{"postArgs", postArgs},
  1491  		{"persPostArgs", persPostArgs},
  1492  	} {
  1493  		if v.got != onetwo {
  1494  			t.Errorf("Expected %s %q, got %q", v.name, onetwo, v.got)
  1495  		}
  1496  	}
  1497  }
  1498  
  1499  func TestPersistentHooks(t *testing.T) {
  1500  	var (
  1501  		parentPersPreArgs  string
  1502  		parentPreArgs      string
  1503  		parentRunArgs      string
  1504  		parentPostArgs     string
  1505  		parentPersPostArgs string
  1506  	)
  1507  
  1508  	var (
  1509  		childPersPreArgs  string
  1510  		childPreArgs      string
  1511  		childRunArgs      string
  1512  		childPostArgs     string
  1513  		childPersPostArgs string
  1514  	)
  1515  
  1516  	parentCmd := &Command{
  1517  		Use: "parent",
  1518  		PersistentPreRun: func(_ *Command, args []string) {
  1519  			parentPersPreArgs = strings.Join(args, " ")
  1520  		},
  1521  		PreRun: func(_ *Command, args []string) {
  1522  			parentPreArgs = strings.Join(args, " ")
  1523  		},
  1524  		Run: func(_ *Command, args []string) {
  1525  			parentRunArgs = strings.Join(args, " ")
  1526  		},
  1527  		PostRun: func(_ *Command, args []string) {
  1528  			parentPostArgs = strings.Join(args, " ")
  1529  		},
  1530  		PersistentPostRun: func(_ *Command, args []string) {
  1531  			parentPersPostArgs = strings.Join(args, " ")
  1532  		},
  1533  	}
  1534  
  1535  	childCmd := &Command{
  1536  		Use: "child",
  1537  		PersistentPreRun: func(_ *Command, args []string) {
  1538  			childPersPreArgs = strings.Join(args, " ")
  1539  		},
  1540  		PreRun: func(_ *Command, args []string) {
  1541  			childPreArgs = strings.Join(args, " ")
  1542  		},
  1543  		Run: func(_ *Command, args []string) {
  1544  			childRunArgs = strings.Join(args, " ")
  1545  		},
  1546  		PostRun: func(_ *Command, args []string) {
  1547  			childPostArgs = strings.Join(args, " ")
  1548  		},
  1549  		PersistentPostRun: func(_ *Command, args []string) {
  1550  			childPersPostArgs = strings.Join(args, " ")
  1551  		},
  1552  	}
  1553  	parentCmd.AddCommand(childCmd)
  1554  
  1555  	output, err := executeCommand(parentCmd, "child", "one", "two")
  1556  	if output != "" {
  1557  		t.Errorf("Unexpected output: %v", output)
  1558  	}
  1559  	if err != nil {
  1560  		t.Errorf("Unexpected error: %v", err)
  1561  	}
  1562  
  1563  	for _, v := range []struct {
  1564  		name string
  1565  		got  string
  1566  	}{
  1567  		// TODO: currently PersistentPreRun* defined in parent does not
  1568  		// run if the matching child subcommand has PersistentPreRun.
  1569  		// If the behavior changes (https://github.com/spf13/cobra/issues/252)
  1570  		// this test must be fixed.
  1571  		{"parentPersPreArgs", parentPersPreArgs},
  1572  		{"parentPreArgs", parentPreArgs},
  1573  		{"parentRunArgs", parentRunArgs},
  1574  		{"parentPostArgs", parentPostArgs},
  1575  		// TODO: currently PersistentPostRun* defined in parent does not
  1576  		// run if the matching child subcommand has PersistentPostRun.
  1577  		// If the behavior changes (https://github.com/spf13/cobra/issues/252)
  1578  		// this test must be fixed.
  1579  		{"parentPersPostArgs", parentPersPostArgs},
  1580  	} {
  1581  		if v.got != "" {
  1582  			t.Errorf("Expected blank %s, got %q", v.name, v.got)
  1583  		}
  1584  	}
  1585  
  1586  	for _, v := range []struct {
  1587  		name string
  1588  		got  string
  1589  	}{
  1590  		{"childPersPreArgs", childPersPreArgs},
  1591  		{"childPreArgs", childPreArgs},
  1592  		{"childRunArgs", childRunArgs},
  1593  		{"childPostArgs", childPostArgs},
  1594  		{"childPersPostArgs", childPersPostArgs},
  1595  	} {
  1596  		if v.got != onetwo {
  1597  			t.Errorf("Expected %s %q, got %q", v.name, onetwo, v.got)
  1598  		}
  1599  	}
  1600  }
  1601  
  1602  // Related to https://github.com/spf13/cobra/issues/521.
  1603  func TestGlobalNormFuncPropagation(t *testing.T) {
  1604  	normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1605  		return pflag.NormalizedName(name)
  1606  	}
  1607  
  1608  	rootCmd := &Command{Use: "root", Run: emptyRun}
  1609  	childCmd := &Command{Use: "child", Run: emptyRun}
  1610  	rootCmd.AddCommand(childCmd)
  1611  
  1612  	rootCmd.SetGlobalNormalizationFunc(normFunc)
  1613  	if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() {
  1614  		t.Error("rootCmd seems to have a wrong normalization function")
  1615  	}
  1616  
  1617  	if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(childCmd.GlobalNormalizationFunc()).Pointer() {
  1618  		t.Error("childCmd should have had the normalization function of rootCmd")
  1619  	}
  1620  }
  1621  
  1622  // Related to https://github.com/spf13/cobra/issues/521.
  1623  func TestNormPassedOnLocal(t *testing.T) {
  1624  	toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1625  		return pflag.NormalizedName(strings.ToUpper(name))
  1626  	}
  1627  
  1628  	c := &Command{}
  1629  	c.Flags().Bool("flagname", true, "this is a dummy flag")
  1630  	c.SetGlobalNormalizationFunc(toUpper)
  1631  	if c.LocalFlags().Lookup("flagname") != c.LocalFlags().Lookup("FLAGNAME") {
  1632  		t.Error("Normalization function should be passed on to Local flag set")
  1633  	}
  1634  }
  1635  
  1636  // Related to https://github.com/spf13/cobra/issues/521.
  1637  func TestNormPassedOnInherited(t *testing.T) {
  1638  	toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1639  		return pflag.NormalizedName(strings.ToUpper(name))
  1640  	}
  1641  
  1642  	c := &Command{}
  1643  	c.SetGlobalNormalizationFunc(toUpper)
  1644  
  1645  	child1 := &Command{}
  1646  	c.AddCommand(child1)
  1647  
  1648  	c.PersistentFlags().Bool("flagname", true, "")
  1649  
  1650  	child2 := &Command{}
  1651  	c.AddCommand(child2)
  1652  
  1653  	inherited := child1.InheritedFlags()
  1654  	if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") {
  1655  		t.Error("Normalization function should be passed on to inherited flag set in command added before flag")
  1656  	}
  1657  
  1658  	inherited = child2.InheritedFlags()
  1659  	if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") {
  1660  		t.Error("Normalization function should be passed on to inherited flag set in command added after flag")
  1661  	}
  1662  }
  1663  
  1664  // Related to https://github.com/spf13/cobra/issues/521.
  1665  func TestConsistentNormalizedName(t *testing.T) {
  1666  	toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1667  		return pflag.NormalizedName(strings.ToUpper(name))
  1668  	}
  1669  	n := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1670  		return pflag.NormalizedName(name)
  1671  	}
  1672  
  1673  	c := &Command{}
  1674  	c.Flags().Bool("flagname", true, "")
  1675  	c.SetGlobalNormalizationFunc(toUpper)
  1676  	c.SetGlobalNormalizationFunc(n)
  1677  
  1678  	if c.LocalFlags().Lookup("flagname") == c.LocalFlags().Lookup("FLAGNAME") {
  1679  		t.Error("Normalizing flag names should not result in duplicate flags")
  1680  	}
  1681  }
  1682  
  1683  func TestFlagOnPflagCommandLine(t *testing.T) {
  1684  	flagName := "flagOnCommandLine"
  1685  	pflag.String(flagName, "", "about my flag")
  1686  
  1687  	c := &Command{Use: "c", Run: emptyRun}
  1688  	c.AddCommand(&Command{Use: "child", Run: emptyRun})
  1689  
  1690  	output, _ := executeCommand(c, "--help")
  1691  	checkStringContains(t, output, flagName)
  1692  
  1693  	resetCommandLineFlagSet()
  1694  }
  1695  
  1696  // TestHiddenCommandExecutes checks,
  1697  // if hidden commands run as intended.
  1698  func TestHiddenCommandExecutes(t *testing.T) {
  1699  	executed := false
  1700  	c := &Command{
  1701  		Use:    "c",
  1702  		Hidden: true,
  1703  		Run:    func(*Command, []string) { executed = true },
  1704  	}
  1705  
  1706  	output, err := executeCommand(c)
  1707  	if output != "" {
  1708  		t.Errorf("Unexpected output: %v", output)
  1709  	}
  1710  	if err != nil {
  1711  		t.Errorf("Unexpected error: %v", err)
  1712  	}
  1713  
  1714  	if !executed {
  1715  		t.Error("Hidden command should have been executed")
  1716  	}
  1717  }
  1718  
  1719  // test to ensure hidden commands do not show up in usage/help text
  1720  func TestHiddenCommandIsHidden(t *testing.T) {
  1721  	c := &Command{Use: "c", Hidden: true, Run: emptyRun}
  1722  	if c.IsAvailableCommand() {
  1723  		t.Errorf("Hidden command should be unavailable")
  1724  	}
  1725  }
  1726  
  1727  func TestCommandsAreSorted(t *testing.T) {
  1728  	EnableCommandSorting = true
  1729  
  1730  	originalNames := []string{"middle", "zlast", "afirst"}
  1731  	expectedNames := []string{"afirst", "middle", "zlast"}
  1732  
  1733  	var rootCmd = &Command{Use: "root"}
  1734  
  1735  	for _, name := range originalNames {
  1736  		rootCmd.AddCommand(&Command{Use: name})
  1737  	}
  1738  
  1739  	for i, c := range rootCmd.Commands() {
  1740  		got := c.Name()
  1741  		if expectedNames[i] != got {
  1742  			t.Errorf("Expected: %s, got: %s", expectedNames[i], got)
  1743  		}
  1744  	}
  1745  
  1746  	EnableCommandSorting = defaultCommandSorting
  1747  }
  1748  
  1749  func TestEnableCommandSortingIsDisabled(t *testing.T) {
  1750  	EnableCommandSorting = false
  1751  
  1752  	originalNames := []string{"middle", "zlast", "afirst"}
  1753  
  1754  	var rootCmd = &Command{Use: "root"}
  1755  
  1756  	for _, name := range originalNames {
  1757  		rootCmd.AddCommand(&Command{Use: name})
  1758  	}
  1759  
  1760  	for i, c := range rootCmd.Commands() {
  1761  		got := c.Name()
  1762  		if originalNames[i] != got {
  1763  			t.Errorf("expected: %s, got: %s", originalNames[i], got)
  1764  		}
  1765  	}
  1766  
  1767  	EnableCommandSorting = defaultCommandSorting
  1768  }
  1769  
  1770  func TestSetOutput(t *testing.T) {
  1771  	c := &Command{}
  1772  	c.SetOutput(nil)
  1773  	if out := c.OutOrStdout(); out != os.Stdout {
  1774  		t.Errorf("Expected setting output to nil to revert back to stdout")
  1775  	}
  1776  }
  1777  
  1778  func TestSetOut(t *testing.T) {
  1779  	c := &Command{}
  1780  	c.SetOut(nil)
  1781  	if out := c.OutOrStdout(); out != os.Stdout {
  1782  		t.Errorf("Expected setting output to nil to revert back to stdout")
  1783  	}
  1784  }
  1785  
  1786  func TestSetErr(t *testing.T) {
  1787  	c := &Command{}
  1788  	c.SetErr(nil)
  1789  	if out := c.ErrOrStderr(); out != os.Stderr {
  1790  		t.Errorf("Expected setting error to nil to revert back to stderr")
  1791  	}
  1792  }
  1793  
  1794  func TestSetIn(t *testing.T) {
  1795  	c := &Command{}
  1796  	c.SetIn(nil)
  1797  	if out := c.InOrStdin(); out != os.Stdin {
  1798  		t.Errorf("Expected setting input to nil to revert back to stdin")
  1799  	}
  1800  }
  1801  
  1802  func TestUsageStringRedirected(t *testing.T) {
  1803  	c := &Command{}
  1804  
  1805  	c.usageFunc = func(cmd *Command) error {
  1806  		cmd.Print("[stdout1]")
  1807  		cmd.PrintErr("[stderr2]")
  1808  		cmd.Print("[stdout3]")
  1809  		return nil
  1810  	}
  1811  
  1812  	expected := "[stdout1][stderr2][stdout3]"
  1813  	if got := c.UsageString(); got != expected {
  1814  		t.Errorf("Expected usage string to consider both stdout and stderr")
  1815  	}
  1816  }
  1817  
  1818  func TestCommandPrintRedirection(t *testing.T) {
  1819  	errBuff, outBuff := bytes.NewBuffer(nil), bytes.NewBuffer(nil)
  1820  	root := &Command{
  1821  		Run: func(cmd *Command, args []string) {
  1822  
  1823  			cmd.PrintErr("PrintErr")
  1824  			cmd.PrintErrln("PrintErr", "line")
  1825  			cmd.PrintErrf("PrintEr%s", "r")
  1826  
  1827  			cmd.Print("Print")
  1828  			cmd.Println("Print", "line")
  1829  			cmd.Printf("Prin%s", "t")
  1830  		},
  1831  	}
  1832  
  1833  	root.SetErr(errBuff)
  1834  	root.SetOut(outBuff)
  1835  
  1836  	if err := root.Execute(); err != nil {
  1837  		t.Error(err)
  1838  	}
  1839  
  1840  	gotErrBytes, err := ioutil.ReadAll(errBuff)
  1841  	if err != nil {
  1842  		t.Error(err)
  1843  	}
  1844  
  1845  	gotOutBytes, err := ioutil.ReadAll(outBuff)
  1846  	if err != nil {
  1847  		t.Error(err)
  1848  	}
  1849  
  1850  	if wantErr := []byte("PrintErrPrintErr line\nPrintErr"); !bytes.Equal(gotErrBytes, wantErr) {
  1851  		t.Errorf("got: '%s' want: '%s'", gotErrBytes, wantErr)
  1852  	}
  1853  
  1854  	if wantOut := []byte("PrintPrint line\nPrint"); !bytes.Equal(gotOutBytes, wantOut) {
  1855  		t.Errorf("got: '%s' want: '%s'", gotOutBytes, wantOut)
  1856  	}
  1857  }
  1858  
  1859  func TestFlagErrorFunc(t *testing.T) {
  1860  	c := &Command{Use: "c", Run: emptyRun}
  1861  
  1862  	expectedFmt := "This is expected: %v"
  1863  	c.SetFlagErrorFunc(func(_ *Command, err error) error {
  1864  		return fmt.Errorf(expectedFmt, err)
  1865  	})
  1866  
  1867  	_, err := executeCommand(c, "--unknown-flag")
  1868  
  1869  	got := err.Error()
  1870  	expected := fmt.Sprintf(expectedFmt, "unknown flag: --unknown-flag")
  1871  	if got != expected {
  1872  		t.Errorf("Expected %v, got %v", expected, got)
  1873  	}
  1874  }
  1875  
  1876  func TestFlagErrorFuncHelp(t *testing.T) {
  1877  	c := &Command{Use: "c", Run: emptyRun}
  1878  	c.PersistentFlags().Bool("help", false, "help for c")
  1879  	c.SetFlagErrorFunc(func(_ *Command, err error) error {
  1880  		return fmt.Errorf("wrap error: %w", err)
  1881  	})
  1882  
  1883  	out, err := executeCommand(c, "--help")
  1884  	if err != nil {
  1885  		t.Errorf("--help should not fail: %v", err)
  1886  	}
  1887  
  1888  	expected := `Usage:
  1889    c [flags]
  1890  
  1891  Flags:
  1892        --help   help for c
  1893  `
  1894  	if out != expected {
  1895  		t.Errorf("Expected: %v, got: %v", expected, out)
  1896  	}
  1897  
  1898  	out, err = executeCommand(c, "-h")
  1899  	if err != nil {
  1900  		t.Errorf("-h should not fail: %v", err)
  1901  	}
  1902  
  1903  	if out != expected {
  1904  		t.Errorf("Expected: %v, got: %v", expected, out)
  1905  	}
  1906  }
  1907  
  1908  // TestSortedFlags checks,
  1909  // if cmd.LocalFlags() is unsorted when cmd.Flags().SortFlags set to false.
  1910  // Related to https://github.com/spf13/cobra/issues/404.
  1911  func TestSortedFlags(t *testing.T) {
  1912  	c := &Command{}
  1913  	c.Flags().SortFlags = false
  1914  	names := []string{"C", "B", "A", "D"}
  1915  	for _, name := range names {
  1916  		c.Flags().Bool(name, false, "")
  1917  	}
  1918  
  1919  	i := 0
  1920  	c.LocalFlags().VisitAll(func(f *pflag.Flag) {
  1921  		if i == len(names) {
  1922  			return
  1923  		}
  1924  		if stringInSlice(f.Name, names) {
  1925  			if names[i] != f.Name {
  1926  				t.Errorf("Incorrect order. Expected %v, got %v", names[i], f.Name)
  1927  			}
  1928  			i++
  1929  		}
  1930  	})
  1931  }
  1932  
  1933  // TestMergeCommandLineToFlags checks,
  1934  // if pflag.CommandLine is correctly merged to c.Flags() after first call
  1935  // of c.mergePersistentFlags.
  1936  // Related to https://github.com/spf13/cobra/issues/443.
  1937  func TestMergeCommandLineToFlags(t *testing.T) {
  1938  	pflag.Bool("boolflag", false, "")
  1939  	c := &Command{Use: "c", Run: emptyRun}
  1940  	c.mergePersistentFlags()
  1941  	if c.Flags().Lookup("boolflag") == nil {
  1942  		t.Fatal("Expecting to have flag from CommandLine in c.Flags()")
  1943  	}
  1944  
  1945  	resetCommandLineFlagSet()
  1946  }
  1947  
  1948  // TestUseDeprecatedFlags checks,
  1949  // if cobra.Execute() prints a message, if a deprecated flag is used.
  1950  // Related to https://github.com/spf13/cobra/issues/463.
  1951  func TestUseDeprecatedFlags(t *testing.T) {
  1952  	c := &Command{Use: "c", Run: emptyRun}
  1953  	c.Flags().BoolP("deprecated", "d", false, "deprecated flag")
  1954  	assertNoErr(t, c.Flags().MarkDeprecated("deprecated", "This flag is deprecated"))
  1955  
  1956  	output, err := executeCommand(c, "c", "-d")
  1957  	if err != nil {
  1958  		t.Error("Unexpected error:", err)
  1959  	}
  1960  	checkStringContains(t, output, "This flag is deprecated")
  1961  }
  1962  
  1963  func TestTraverseWithParentFlags(t *testing.T) {
  1964  	rootCmd := &Command{Use: "root", TraverseChildren: true}
  1965  	rootCmd.Flags().String("str", "", "")
  1966  	rootCmd.Flags().BoolP("bool", "b", false, "")
  1967  
  1968  	childCmd := &Command{Use: "child"}
  1969  	childCmd.Flags().Int("int", -1, "")
  1970  
  1971  	rootCmd.AddCommand(childCmd)
  1972  
  1973  	c, args, err := rootCmd.Traverse([]string{"-b", "--str", "ok", "child", "--int"})
  1974  	if err != nil {
  1975  		t.Errorf("Unexpected error: %v", err)
  1976  	}
  1977  	if len(args) != 1 && args[0] != "--add" {
  1978  		t.Errorf("Wrong args: %v", args)
  1979  	}
  1980  	if c.Name() != childCmd.Name() {
  1981  		t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name())
  1982  	}
  1983  }
  1984  
  1985  func TestTraverseNoParentFlags(t *testing.T) {
  1986  	rootCmd := &Command{Use: "root", TraverseChildren: true}
  1987  	rootCmd.Flags().String("foo", "", "foo things")
  1988  
  1989  	childCmd := &Command{Use: "child"}
  1990  	childCmd.Flags().String("str", "", "")
  1991  	rootCmd.AddCommand(childCmd)
  1992  
  1993  	c, args, err := rootCmd.Traverse([]string{"child"})
  1994  	if err != nil {
  1995  		t.Errorf("Unexpected error: %v", err)
  1996  	}
  1997  	if len(args) != 0 {
  1998  		t.Errorf("Wrong args %v", args)
  1999  	}
  2000  	if c.Name() != childCmd.Name() {
  2001  		t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name())
  2002  	}
  2003  }
  2004  
  2005  func TestTraverseWithBadParentFlags(t *testing.T) {
  2006  	rootCmd := &Command{Use: "root", TraverseChildren: true}
  2007  
  2008  	childCmd := &Command{Use: "child"}
  2009  	childCmd.Flags().String("str", "", "")
  2010  	rootCmd.AddCommand(childCmd)
  2011  
  2012  	expected := "unknown flag: --str"
  2013  
  2014  	c, _, err := rootCmd.Traverse([]string{"--str", "ok", "child"})
  2015  	if err == nil || !strings.Contains(err.Error(), expected) {
  2016  		t.Errorf("Expected error, %q, got %q", expected, err)
  2017  	}
  2018  	if c != nil {
  2019  		t.Errorf("Expected nil command")
  2020  	}
  2021  }
  2022  
  2023  func TestTraverseWithBadChildFlag(t *testing.T) {
  2024  	rootCmd := &Command{Use: "root", TraverseChildren: true}
  2025  	rootCmd.Flags().String("str", "", "")
  2026  
  2027  	childCmd := &Command{Use: "child"}
  2028  	rootCmd.AddCommand(childCmd)
  2029  
  2030  	// Expect no error because the last commands args shouldn't be parsed in
  2031  	// Traverse.
  2032  	c, args, err := rootCmd.Traverse([]string{"child", "--str"})
  2033  	if err != nil {
  2034  		t.Errorf("Unexpected error: %v", err)
  2035  	}
  2036  	if len(args) != 1 && args[0] != "--str" {
  2037  		t.Errorf("Wrong args: %v", args)
  2038  	}
  2039  	if c.Name() != childCmd.Name() {
  2040  		t.Errorf("Expected command %q, got: %q", childCmd.Name(), c.Name())
  2041  	}
  2042  }
  2043  
  2044  func TestTraverseWithTwoSubcommands(t *testing.T) {
  2045  	rootCmd := &Command{Use: "root", TraverseChildren: true}
  2046  
  2047  	subCmd := &Command{Use: "sub", TraverseChildren: true}
  2048  	rootCmd.AddCommand(subCmd)
  2049  
  2050  	subsubCmd := &Command{
  2051  		Use: "subsub",
  2052  	}
  2053  	subCmd.AddCommand(subsubCmd)
  2054  
  2055  	c, _, err := rootCmd.Traverse([]string{"sub", "subsub"})
  2056  	if err != nil {
  2057  		t.Fatalf("Unexpected error: %v", err)
  2058  	}
  2059  	if c.Name() != subsubCmd.Name() {
  2060  		t.Fatalf("Expected command: %q, got %q", subsubCmd.Name(), c.Name())
  2061  	}
  2062  }
  2063  
  2064  // TestUpdateName checks if c.Name() updates on changed c.Use.
  2065  // Related to https://github.com/spf13/cobra/pull/422#discussion_r143918343.
  2066  func TestUpdateName(t *testing.T) {
  2067  	c := &Command{Use: "name xyz"}
  2068  	originalName := c.Name()
  2069  
  2070  	c.Use = "changedName abc"
  2071  	if originalName == c.Name() || c.Name() != "changedName" {
  2072  		t.Error("c.Name() should be updated on changed c.Use")
  2073  	}
  2074  }
  2075  
  2076  type calledAsTestcase struct {
  2077  	args []string
  2078  	call string
  2079  	want string
  2080  	epm  bool
  2081  }
  2082  
  2083  func (tc *calledAsTestcase) test(t *testing.T) {
  2084  	defer func(ov bool) { EnablePrefixMatching = ov }(EnablePrefixMatching)
  2085  	EnablePrefixMatching = tc.epm
  2086  
  2087  	var called *Command
  2088  	run := func(c *Command, _ []string) { t.Logf("called: %q", c.Name()); called = c }
  2089  
  2090  	parent := &Command{Use: "parent", Run: run}
  2091  	child1 := &Command{Use: "child1", Run: run, Aliases: []string{"this"}}
  2092  	child2 := &Command{Use: "child2", Run: run, Aliases: []string{"that"}}
  2093  
  2094  	parent.AddCommand(child1)
  2095  	parent.AddCommand(child2)
  2096  	parent.SetArgs(tc.args)
  2097  
  2098  	output := new(bytes.Buffer)
  2099  	parent.SetOut(output)
  2100  	parent.SetErr(output)
  2101  
  2102  	_ = parent.Execute()
  2103  
  2104  	if called == nil {
  2105  		if tc.call != "" {
  2106  			t.Errorf("missing expected call to command: %s", tc.call)
  2107  		}
  2108  		return
  2109  	}
  2110  
  2111  	if called.Name() != tc.call {
  2112  		t.Errorf("called command == %q; Wanted %q", called.Name(), tc.call)
  2113  	} else if got := called.CalledAs(); got != tc.want {
  2114  		t.Errorf("%s.CalledAs() == %q; Wanted: %q", tc.call, got, tc.want)
  2115  	}
  2116  }
  2117  
  2118  func TestCalledAs(t *testing.T) {
  2119  	tests := map[string]calledAsTestcase{
  2120  		"find/no-args":            {nil, "parent", "parent", false},
  2121  		"find/real-name":          {[]string{"child1"}, "child1", "child1", false},
  2122  		"find/full-alias":         {[]string{"that"}, "child2", "that", false},
  2123  		"find/part-no-prefix":     {[]string{"thi"}, "", "", false},
  2124  		"find/part-alias":         {[]string{"thi"}, "child1", "this", true},
  2125  		"find/conflict":           {[]string{"th"}, "", "", true},
  2126  		"traverse/no-args":        {nil, "parent", "parent", false},
  2127  		"traverse/real-name":      {[]string{"child1"}, "child1", "child1", false},
  2128  		"traverse/full-alias":     {[]string{"that"}, "child2", "that", false},
  2129  		"traverse/part-no-prefix": {[]string{"thi"}, "", "", false},
  2130  		"traverse/part-alias":     {[]string{"thi"}, "child1", "this", true},
  2131  		"traverse/conflict":       {[]string{"th"}, "", "", true},
  2132  	}
  2133  
  2134  	for name, tc := range tests {
  2135  		t.Run(name, tc.test)
  2136  	}
  2137  }
  2138  
  2139  func TestFParseErrWhitelistBackwardCompatibility(t *testing.T) {
  2140  	c := &Command{Use: "c", Run: emptyRun}
  2141  	c.Flags().BoolP("boola", "a", false, "a boolean flag")
  2142  
  2143  	output, err := executeCommand(c, "c", "-a", "--unknown", "flag")
  2144  	if err == nil {
  2145  		t.Error("expected unknown flag error")
  2146  	}
  2147  	checkStringContains(t, output, "unknown flag: --unknown")
  2148  }
  2149  
  2150  func TestFParseErrWhitelistSameCommand(t *testing.T) {
  2151  	c := &Command{
  2152  		Use: "c",
  2153  		Run: emptyRun,
  2154  		FParseErrWhitelist: FParseErrWhitelist{
  2155  			UnknownFlags: true,
  2156  		},
  2157  	}
  2158  	c.Flags().BoolP("boola", "a", false, "a boolean flag")
  2159  
  2160  	_, err := executeCommand(c, "c", "-a", "--unknown", "flag")
  2161  	if err != nil {
  2162  		t.Error("unexpected error: ", err)
  2163  	}
  2164  }
  2165  
  2166  func TestFParseErrWhitelistParentCommand(t *testing.T) {
  2167  	root := &Command{
  2168  		Use: "root",
  2169  		Run: emptyRun,
  2170  		FParseErrWhitelist: FParseErrWhitelist{
  2171  			UnknownFlags: true,
  2172  		},
  2173  	}
  2174  
  2175  	c := &Command{
  2176  		Use: "child",
  2177  		Run: emptyRun,
  2178  	}
  2179  	c.Flags().BoolP("boola", "a", false, "a boolean flag")
  2180  
  2181  	root.AddCommand(c)
  2182  
  2183  	output, err := executeCommand(root, "child", "-a", "--unknown", "flag")
  2184  	if err == nil {
  2185  		t.Error("expected unknown flag error")
  2186  	}
  2187  	checkStringContains(t, output, "unknown flag: --unknown")
  2188  }
  2189  
  2190  func TestFParseErrWhitelistChildCommand(t *testing.T) {
  2191  	root := &Command{
  2192  		Use: "root",
  2193  		Run: emptyRun,
  2194  	}
  2195  
  2196  	c := &Command{
  2197  		Use: "child",
  2198  		Run: emptyRun,
  2199  		FParseErrWhitelist: FParseErrWhitelist{
  2200  			UnknownFlags: true,
  2201  		},
  2202  	}
  2203  	c.Flags().BoolP("boola", "a", false, "a boolean flag")
  2204  
  2205  	root.AddCommand(c)
  2206  
  2207  	_, err := executeCommand(root, "child", "-a", "--unknown", "flag")
  2208  	if err != nil {
  2209  		t.Error("unexpected error: ", err.Error())
  2210  	}
  2211  }
  2212  
  2213  func TestFParseErrWhitelistSiblingCommand(t *testing.T) {
  2214  	root := &Command{
  2215  		Use: "root",
  2216  		Run: emptyRun,
  2217  	}
  2218  
  2219  	c := &Command{
  2220  		Use: "child",
  2221  		Run: emptyRun,
  2222  		FParseErrWhitelist: FParseErrWhitelist{
  2223  			UnknownFlags: true,
  2224  		},
  2225  	}
  2226  	c.Flags().BoolP("boola", "a", false, "a boolean flag")
  2227  
  2228  	s := &Command{
  2229  		Use: "sibling",
  2230  		Run: emptyRun,
  2231  	}
  2232  	s.Flags().BoolP("boolb", "b", false, "a boolean flag")
  2233  
  2234  	root.AddCommand(c)
  2235  	root.AddCommand(s)
  2236  
  2237  	output, err := executeCommand(root, "sibling", "-b", "--unknown", "flag")
  2238  	if err == nil {
  2239  		t.Error("expected unknown flag error")
  2240  	}
  2241  	checkStringContains(t, output, "unknown flag: --unknown")
  2242  }
  2243  
  2244  func TestSetContext(t *testing.T) {
  2245  	type key struct{}
  2246  	val := "foobar"
  2247  	root := &Command{
  2248  		Use: "root",
  2249  		Run: func(cmd *Command, args []string) {
  2250  			key := cmd.Context().Value(key{})
  2251  			got, ok := key.(string)
  2252  			if !ok {
  2253  				t.Error("key not found in context")
  2254  			}
  2255  			if got != val {
  2256  				t.Errorf("Expected value: \n %v\nGot:\n %v\n", val, got)
  2257  			}
  2258  		},
  2259  	}
  2260  
  2261  	ctx := context.WithValue(context.Background(), key{}, val)
  2262  	root.SetContext(ctx)
  2263  	err := root.Execute()
  2264  	if err != nil {
  2265  		t.Error(err)
  2266  	}
  2267  }
  2268  
  2269  func TestSetContextPreRun(t *testing.T) {
  2270  	type key struct{}
  2271  	val := "barr"
  2272  	root := &Command{
  2273  		Use: "root",
  2274  		PreRun: func(cmd *Command, args []string) {
  2275  			ctx := context.WithValue(cmd.Context(), key{}, val)
  2276  			cmd.SetContext(ctx)
  2277  		},
  2278  		Run: func(cmd *Command, args []string) {
  2279  			val := cmd.Context().Value(key{})
  2280  			got, ok := val.(string)
  2281  			if !ok {
  2282  				t.Error("key not found in context")
  2283  			}
  2284  			if got != val {
  2285  				t.Errorf("Expected value: \n %v\nGot:\n %v\n", val, got)
  2286  			}
  2287  		},
  2288  	}
  2289  	err := root.Execute()
  2290  	if err != nil {
  2291  		t.Error(err)
  2292  	}
  2293  }
  2294  
  2295  func TestSetContextPreRunOverwrite(t *testing.T) {
  2296  	type key struct{}
  2297  	val := "blah"
  2298  	root := &Command{
  2299  		Use: "root",
  2300  		Run: func(cmd *Command, args []string) {
  2301  			key := cmd.Context().Value(key{})
  2302  			_, ok := key.(string)
  2303  			if ok {
  2304  				t.Error("key found in context when not expected")
  2305  			}
  2306  		},
  2307  	}
  2308  	ctx := context.WithValue(context.Background(), key{}, val)
  2309  	root.SetContext(ctx)
  2310  	err := root.ExecuteContext(context.Background())
  2311  	if err != nil {
  2312  		t.Error(err)
  2313  	}
  2314  }
  2315  
  2316  func TestSetContextPersistentPreRun(t *testing.T) {
  2317  	type key struct{}
  2318  	val := "barbar"
  2319  	root := &Command{
  2320  		Use: "root",
  2321  		PersistentPreRun: func(cmd *Command, args []string) {
  2322  			ctx := context.WithValue(cmd.Context(), key{}, val)
  2323  			cmd.SetContext(ctx)
  2324  		},
  2325  	}
  2326  	child := &Command{
  2327  		Use: "child",
  2328  		Run: func(cmd *Command, args []string) {
  2329  			key := cmd.Context().Value(key{})
  2330  			got, ok := key.(string)
  2331  			if !ok {
  2332  				t.Error("key not found in context")
  2333  			}
  2334  			if got != val {
  2335  				t.Errorf("Expected value: \n %v\nGot:\n %v\n", val, got)
  2336  			}
  2337  		},
  2338  	}
  2339  	root.AddCommand(child)
  2340  	root.SetArgs([]string{"child"})
  2341  	err := root.Execute()
  2342  	if err != nil {
  2343  		t.Error(err)
  2344  	}
  2345  }
  2346  
  2347  const VersionFlag = "--version"
  2348  const HelpFlag = "--help"
  2349  
  2350  func TestNoRootRunCommandExecutedWithVersionSet(t *testing.T) {
  2351  	rootCmd := &Command{Use: "root", Version: "1.0.0", Long: "Long description"}
  2352  	rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
  2353  
  2354  	output, err := executeCommand(rootCmd)
  2355  	if err != nil {
  2356  		t.Errorf("Unexpected error: %v", err)
  2357  	}
  2358  
  2359  	checkStringContains(t, output, rootCmd.Long)
  2360  	checkStringContains(t, output, HelpFlag)
  2361  	checkStringContains(t, output, VersionFlag)
  2362  }
  2363  
  2364  func TestNoRootRunCommandExecutedWithoutVersionSet(t *testing.T) {
  2365  	rootCmd := &Command{Use: "root", Long: "Long description"}
  2366  	rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
  2367  
  2368  	output, err := executeCommand(rootCmd)
  2369  	if err != nil {
  2370  		t.Errorf("Unexpected error: %v", err)
  2371  	}
  2372  
  2373  	checkStringContains(t, output, rootCmd.Long)
  2374  	checkStringContains(t, output, HelpFlag)
  2375  	checkStringOmits(t, output, VersionFlag)
  2376  }
  2377  
  2378  func TestHelpCommandExecutedWithVersionSet(t *testing.T) {
  2379  	rootCmd := &Command{Use: "root", Version: "1.0.0", Long: "Long description", Run: emptyRun}
  2380  	rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
  2381  
  2382  	output, err := executeCommand(rootCmd, "help")
  2383  	if err != nil {
  2384  		t.Errorf("Unexpected error: %v", err)
  2385  	}
  2386  
  2387  	checkStringContains(t, output, rootCmd.Long)
  2388  	checkStringContains(t, output, HelpFlag)
  2389  	checkStringContains(t, output, VersionFlag)
  2390  }
  2391  
  2392  func TestHelpCommandExecutedWithoutVersionSet(t *testing.T) {
  2393  	rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
  2394  	rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
  2395  
  2396  	output, err := executeCommand(rootCmd, "help")
  2397  	if err != nil {
  2398  		t.Errorf("Unexpected error: %v", err)
  2399  	}
  2400  
  2401  	checkStringContains(t, output, rootCmd.Long)
  2402  	checkStringContains(t, output, HelpFlag)
  2403  	checkStringOmits(t, output, VersionFlag)
  2404  }
  2405  
  2406  func TestHelpflagCommandExecutedWithVersionSet(t *testing.T) {
  2407  	rootCmd := &Command{Use: "root", Version: "1.0.0", Long: "Long description", Run: emptyRun}
  2408  	rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
  2409  
  2410  	output, err := executeCommand(rootCmd, HelpFlag)
  2411  	if err != nil {
  2412  		t.Errorf("Unexpected error: %v", err)
  2413  	}
  2414  
  2415  	checkStringContains(t, output, rootCmd.Long)
  2416  	checkStringContains(t, output, HelpFlag)
  2417  	checkStringContains(t, output, VersionFlag)
  2418  }
  2419  
  2420  func TestHelpflagCommandExecutedWithoutVersionSet(t *testing.T) {
  2421  	rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
  2422  	rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
  2423  
  2424  	output, err := executeCommand(rootCmd, HelpFlag)
  2425  	if err != nil {
  2426  		t.Errorf("Unexpected error: %v", err)
  2427  	}
  2428  
  2429  	checkStringContains(t, output, rootCmd.Long)
  2430  	checkStringContains(t, output, HelpFlag)
  2431  	checkStringOmits(t, output, VersionFlag)
  2432  }