12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733 |
- package cobra
- import (
- "bytes"
- "fmt"
- "os"
- "reflect"
- "strings"
- "testing"
- "github.com/spf13/pflag"
- )
- func emptyRun(*Command, []string) {}
- func executeCommand(root *Command, args ...string) (output string, err error) {
- _, output, err = executeCommandC(root, args...)
- return output, err
- }
- func executeCommandC(root *Command, args ...string) (c *Command, output string, err error) {
- buf := new(bytes.Buffer)
- root.SetOutput(buf)
- root.SetArgs(args)
- c, err = root.ExecuteC()
- return c, buf.String(), err
- }
- func resetCommandLineFlagSet() {
- pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
- }
- func checkStringContains(t *testing.T, got, expected string) {
- if !strings.Contains(got, expected) {
- t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expected, got)
- }
- }
- func checkStringOmits(t *testing.T, got, expected string) {
- if strings.Contains(got, expected) {
- t.Errorf("Expected to not contain: \n %v\nGot: %v", expected, got)
- }
- }
- func TestSingleCommand(t *testing.T) {
- var rootCmdArgs []string
- rootCmd := &Command{
- Use: "root",
- Args: ExactArgs(2),
- Run: func(_ *Command, args []string) { rootCmdArgs = args },
- }
- aCmd := &Command{Use: "a", Args: NoArgs, Run: emptyRun}
- bCmd := &Command{Use: "b", Args: NoArgs, Run: emptyRun}
- rootCmd.AddCommand(aCmd, bCmd)
- output, err := executeCommand(rootCmd, "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- got := strings.Join(rootCmdArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("rootCmdArgs expected: %q, got: %q", expected, got)
- }
- }
- func TestChildCommand(t *testing.T) {
- var child1CmdArgs []string
- rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
- child1Cmd := &Command{
- Use: "child1",
- Args: ExactArgs(2),
- Run: func(_ *Command, args []string) { child1CmdArgs = args },
- }
- child2Cmd := &Command{Use: "child2", Args: NoArgs, Run: emptyRun}
- rootCmd.AddCommand(child1Cmd, child2Cmd)
- output, err := executeCommand(rootCmd, "child1", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- got := strings.Join(child1CmdArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("child1CmdArgs expected: %q, got: %q", expected, got)
- }
- }
- func TestCallCommandWithoutSubcommands(t *testing.T) {
- rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
- _, err := executeCommand(rootCmd)
- if err != nil {
- t.Errorf("Calling command without subcommands should not have error: %v", err)
- }
- }
- func TestRootExecuteUnknownCommand(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
- output, _ := executeCommand(rootCmd, "unknown")
- expected := "Error: unknown command \"unknown\" for \"root\"\nRun 'root --help' for usage.\n"
- if output != expected {
- t.Errorf("Expected:\n %q\nGot:\n %q\n", expected, output)
- }
- }
- func TestSubcommandExecuteC(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- childCmd := &Command{Use: "child", Run: emptyRun}
- rootCmd.AddCommand(childCmd)
- c, output, err := executeCommandC(rootCmd, "child")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if c.Name() != "child" {
- t.Errorf(`invalid command returned from ExecuteC: expected "child"', got %q`, c.Name())
- }
- }
- func TestRootUnknownCommandSilenced(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- rootCmd.SilenceErrors = true
- rootCmd.SilenceUsage = true
- rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
- output, _ := executeCommand(rootCmd, "unknown")
- if output != "" {
- t.Errorf("Expected blank output, because of silenced usage.\nGot:\n %q\n", output)
- }
- }
- func TestCommandAlias(t *testing.T) {
- var timesCmdArgs []string
- rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
- echoCmd := &Command{
- Use: "echo",
- Aliases: []string{"say", "tell"},
- Args: NoArgs,
- Run: emptyRun,
- }
- timesCmd := &Command{
- Use: "times",
- Args: ExactArgs(2),
- Run: func(_ *Command, args []string) { timesCmdArgs = args },
- }
- echoCmd.AddCommand(timesCmd)
- rootCmd.AddCommand(echoCmd)
- output, err := executeCommand(rootCmd, "tell", "times", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- got := strings.Join(timesCmdArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got)
- }
- }
- func TestEnablePrefixMatching(t *testing.T) {
- EnablePrefixMatching = true
- var aCmdArgs []string
- rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
- aCmd := &Command{
- Use: "aCmd",
- Args: ExactArgs(2),
- Run: func(_ *Command, args []string) { aCmdArgs = args },
- }
- bCmd := &Command{Use: "bCmd", Args: NoArgs, Run: emptyRun}
- rootCmd.AddCommand(aCmd, bCmd)
- output, err := executeCommand(rootCmd, "a", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- got := strings.Join(aCmdArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("aCmdArgs expected: %q, got: %q", expected, got)
- }
- EnablePrefixMatching = false
- }
- func TestAliasPrefixMatching(t *testing.T) {
- EnablePrefixMatching = true
- var timesCmdArgs []string
- rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
- echoCmd := &Command{
- Use: "echo",
- Aliases: []string{"say", "tell"},
- Args: NoArgs,
- Run: emptyRun,
- }
- timesCmd := &Command{
- Use: "times",
- Args: ExactArgs(2),
- Run: func(_ *Command, args []string) { timesCmdArgs = args },
- }
- echoCmd.AddCommand(timesCmd)
- rootCmd.AddCommand(echoCmd)
- output, err := executeCommand(rootCmd, "sa", "times", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- got := strings.Join(timesCmdArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got)
- }
- EnablePrefixMatching = false
- }
- // TestChildSameName checks the correct behaviour of cobra in cases,
- // when an application with name "foo" and with subcommand "foo"
- // is executed with args "foo foo".
- func TestChildSameName(t *testing.T) {
- var fooCmdArgs []string
- rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun}
- fooCmd := &Command{
- Use: "foo",
- Args: ExactArgs(2),
- Run: func(_ *Command, args []string) { fooCmdArgs = args },
- }
- barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun}
- rootCmd.AddCommand(fooCmd, barCmd)
- output, err := executeCommand(rootCmd, "foo", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- got := strings.Join(fooCmdArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got)
- }
- }
- // TestGrandChildSameName checks the correct behaviour of cobra in cases,
- // when user has a root command and a grand child
- // with the same name.
- func TestGrandChildSameName(t *testing.T) {
- var fooCmdArgs []string
- rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun}
- barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun}
- fooCmd := &Command{
- Use: "foo",
- Args: ExactArgs(2),
- Run: func(_ *Command, args []string) { fooCmdArgs = args },
- }
- barCmd.AddCommand(fooCmd)
- rootCmd.AddCommand(barCmd)
- output, err := executeCommand(rootCmd, "bar", "foo", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- got := strings.Join(fooCmdArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got)
- }
- }
- func TestFlagLong(t *testing.T) {
- var cArgs []string
- c := &Command{
- Use: "c",
- Args: ArbitraryArgs,
- Run: func(_ *Command, args []string) { cArgs = args },
- }
- var intFlagValue int
- var stringFlagValue string
- c.Flags().IntVar(&intFlagValue, "intf", -1, "")
- c.Flags().StringVar(&stringFlagValue, "sf", "", "")
- output, err := executeCommand(c, "--intf=7", "--sf=abc", "one", "--", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", err)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if c.ArgsLenAtDash() != 1 {
- t.Errorf("Expected ArgsLenAtDash: %v but got %v", 1, c.ArgsLenAtDash())
- }
- if intFlagValue != 7 {
- t.Errorf("Expected intFlagValue: %v, got %v", 7, intFlagValue)
- }
- if stringFlagValue != "abc" {
- t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue)
- }
- got := strings.Join(cArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("Expected arguments: %q, got %q", expected, got)
- }
- }
- func TestFlagShort(t *testing.T) {
- var cArgs []string
- c := &Command{
- Use: "c",
- Args: ArbitraryArgs,
- Run: func(_ *Command, args []string) { cArgs = args },
- }
- var intFlagValue int
- var stringFlagValue string
- c.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
- c.Flags().StringVarP(&stringFlagValue, "sf", "s", "", "")
- output, err := executeCommand(c, "-i", "7", "-sabc", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", err)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if intFlagValue != 7 {
- t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
- }
- if stringFlagValue != "abc" {
- t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue)
- }
- got := strings.Join(cArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("Expected arguments: %q, got %q", expected, got)
- }
- }
- func TestChildFlag(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- childCmd := &Command{Use: "child", Run: emptyRun}
- rootCmd.AddCommand(childCmd)
- var intFlagValue int
- childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
- output, err := executeCommand(rootCmd, "child", "-i7")
- if output != "" {
- t.Errorf("Unexpected output: %v", err)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if intFlagValue != 7 {
- t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
- }
- }
- func TestChildFlagWithParentLocalFlag(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- childCmd := &Command{Use: "child", Run: emptyRun}
- rootCmd.AddCommand(childCmd)
- var intFlagValue int
- rootCmd.Flags().StringP("sf", "s", "", "")
- childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
- _, err := executeCommand(rootCmd, "child", "-i7", "-sabc")
- if err == nil {
- t.Errorf("Invalid flag should generate error")
- }
- checkStringContains(t, err.Error(), "unknown shorthand")
- if intFlagValue != 7 {
- t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
- }
- }
- func TestFlagInvalidInput(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- rootCmd.Flags().IntP("intf", "i", -1, "")
- _, err := executeCommand(rootCmd, "-iabc")
- if err == nil {
- t.Errorf("Invalid flag value should generate error")
- }
- checkStringContains(t, err.Error(), "invalid syntax")
- }
- func TestFlagBeforeCommand(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- childCmd := &Command{Use: "child", Run: emptyRun}
- rootCmd.AddCommand(childCmd)
- var flagValue int
- childCmd.Flags().IntVarP(&flagValue, "intf", "i", -1, "")
- // With short flag.
- _, err := executeCommand(rootCmd, "-i7", "child")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if flagValue != 7 {
- t.Errorf("Expected flag value: %v, got %v", 7, flagValue)
- }
- // With long flag.
- _, err = executeCommand(rootCmd, "--intf=8", "child")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if flagValue != 8 {
- t.Errorf("Expected flag value: %v, got %v", 9, flagValue)
- }
- }
- func TestStripFlags(t *testing.T) {
- tests := []struct {
- input []string
- output []string
- }{
- {
- []string{"foo", "bar"},
- []string{"foo", "bar"},
- },
- {
- []string{"foo", "--str", "-s"},
- []string{"foo"},
- },
- {
- []string{"-s", "foo", "--str", "bar"},
- []string{},
- },
- {
- []string{"-i10", "echo"},
- []string{"echo"},
- },
- {
- []string{"-i=10", "echo"},
- []string{"echo"},
- },
- {
- []string{"--int=100", "echo"},
- []string{"echo"},
- },
- {
- []string{"-ib", "echo", "-sfoo", "baz"},
- []string{"echo", "baz"},
- },
- {
- []string{"-i=baz", "bar", "-i", "foo", "blah"},
- []string{"bar", "blah"},
- },
- {
- []string{"--int=baz", "-sbar", "-i", "foo", "blah"},
- []string{"blah"},
- },
- {
- []string{"--bool", "bar", "-i", "foo", "blah"},
- []string{"bar", "blah"},
- },
- {
- []string{"-b", "bar", "-i", "foo", "blah"},
- []string{"bar", "blah"},
- },
- {
- []string{"--persist", "bar"},
- []string{"bar"},
- },
- {
- []string{"-p", "bar"},
- []string{"bar"},
- },
- }
- c := &Command{Use: "c", Run: emptyRun}
- c.PersistentFlags().BoolP("persist", "p", false, "")
- c.Flags().IntP("int", "i", -1, "")
- c.Flags().StringP("str", "s", "", "")
- c.Flags().BoolP("bool", "b", false, "")
- for i, test := range tests {
- got := stripFlags(test.input, c)
- if !reflect.DeepEqual(test.output, got) {
- t.Errorf("(%v) Expected: %v, got: %v", i, test.output, got)
- }
- }
- }
- func TestDisableFlagParsing(t *testing.T) {
- var cArgs []string
- c := &Command{
- Use: "c",
- DisableFlagParsing: true,
- Run: func(_ *Command, args []string) {
- cArgs = args
- },
- }
- args := []string{"cmd", "-v", "-race", "-file", "foo.go"}
- output, err := executeCommand(c, args...)
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if !reflect.DeepEqual(args, cArgs) {
- t.Errorf("Expected: %v, got: %v", args, cArgs)
- }
- }
- func TestPersistentFlagsOnSameCommand(t *testing.T) {
- var rootCmdArgs []string
- rootCmd := &Command{
- Use: "root",
- Args: ArbitraryArgs,
- Run: func(_ *Command, args []string) { rootCmdArgs = args },
- }
- var flagValue int
- rootCmd.PersistentFlags().IntVarP(&flagValue, "intf", "i", -1, "")
- output, err := executeCommand(rootCmd, "-i7", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- got := strings.Join(rootCmdArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("rootCmdArgs expected: %q, got %q", expected, got)
- }
- if flagValue != 7 {
- t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
- }
- }
- // TestEmptyInputs checks,
- // if flags correctly parsed with blank strings in args.
- func TestEmptyInputs(t *testing.T) {
- c := &Command{Use: "c", Run: emptyRun}
- var flagValue int
- c.Flags().IntVarP(&flagValue, "intf", "i", -1, "")
- output, err := executeCommand(c, "", "-i7", "")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if flagValue != 7 {
- t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
- }
- }
- func TestOverwrittenFlag(t *testing.T) {
- // TODO: This test fails, but should work.
- t.Skip()
- parent := &Command{Use: "parent", Run: emptyRun}
- child := &Command{Use: "child", Run: emptyRun}
- parent.PersistentFlags().Bool("boolf", false, "")
- parent.PersistentFlags().Int("intf", -1, "")
- child.Flags().String("strf", "", "")
- child.Flags().Int("intf", -1, "")
- parent.AddCommand(child)
- childInherited := child.InheritedFlags()
- childLocal := child.LocalFlags()
- if childLocal.Lookup("strf") == nil {
- t.Error(`LocalFlags expected to contain "strf", got "nil"`)
- }
- if childInherited.Lookup("boolf") == nil {
- t.Error(`InheritedFlags expected to contain "boolf", got "nil"`)
- }
- if childInherited.Lookup("intf") != nil {
- t.Errorf(`InheritedFlags should not contain overwritten flag "intf"`)
- }
- if childLocal.Lookup("intf") == nil {
- t.Error(`LocalFlags expected to contain "intf", got "nil"`)
- }
- }
- func TestPersistentFlagsOnChild(t *testing.T) {
- var childCmdArgs []string
- rootCmd := &Command{Use: "root", Run: emptyRun}
- childCmd := &Command{
- Use: "child",
- Args: ArbitraryArgs,
- Run: func(_ *Command, args []string) { childCmdArgs = args },
- }
- rootCmd.AddCommand(childCmd)
- var parentFlagValue int
- var childFlagValue int
- rootCmd.PersistentFlags().IntVarP(&parentFlagValue, "parentf", "p", -1, "")
- childCmd.Flags().IntVarP(&childFlagValue, "childf", "c", -1, "")
- output, err := executeCommand(rootCmd, "child", "-c7", "-p8", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- got := strings.Join(childCmdArgs, " ")
- expected := "one two"
- if got != expected {
- t.Errorf("childCmdArgs expected: %q, got %q", expected, got)
- }
- if parentFlagValue != 8 {
- t.Errorf("parentFlagValue expected: %v, got %v", 8, parentFlagValue)
- }
- if childFlagValue != 7 {
- t.Errorf("childFlagValue expected: %v, got %v", 7, childFlagValue)
- }
- }
- func TestRequiredFlags(t *testing.T) {
- c := &Command{Use: "c", Run: emptyRun}
- c.Flags().String("foo1", "", "")
- c.MarkFlagRequired("foo1")
- c.Flags().String("foo2", "", "")
- c.MarkFlagRequired("foo2")
- c.Flags().String("bar", "", "")
- expected := fmt.Sprintf("required flag(s) %q, %q not set", "foo1", "foo2")
- _, err := executeCommand(c)
- got := err.Error()
- if got != expected {
- t.Errorf("Expected error: %q, got: %q", expected, got)
- }
- }
- func TestPersistentRequiredFlags(t *testing.T) {
- parent := &Command{Use: "parent", Run: emptyRun}
- parent.PersistentFlags().String("foo1", "", "")
- parent.MarkPersistentFlagRequired("foo1")
- parent.PersistentFlags().String("foo2", "", "")
- parent.MarkPersistentFlagRequired("foo2")
- parent.Flags().String("foo3", "", "")
- child := &Command{Use: "child", Run: emptyRun}
- child.Flags().String("bar1", "", "")
- child.MarkFlagRequired("bar1")
- child.Flags().String("bar2", "", "")
- child.MarkFlagRequired("bar2")
- child.Flags().String("bar3", "", "")
- parent.AddCommand(child)
- expected := fmt.Sprintf("required flag(s) %q, %q, %q, %q not set", "bar1", "bar2", "foo1", "foo2")
- _, err := executeCommand(parent, "child")
- if err.Error() != expected {
- t.Errorf("Expected %q, got %q", expected, err.Error())
- }
- }
- func TestInitHelpFlagMergesFlags(t *testing.T) {
- usage := "custom flag"
- rootCmd := &Command{Use: "root"}
- rootCmd.PersistentFlags().Bool("help", false, "custom flag")
- childCmd := &Command{Use: "child"}
- rootCmd.AddCommand(childCmd)
- childCmd.InitDefaultHelpFlag()
- got := childCmd.Flags().Lookup("help").Usage
- if got != usage {
- t.Errorf("Expected the help flag from the root command with usage: %v\nGot the default with usage: %v", usage, got)
- }
- }
- func TestHelpCommandExecuted(t *testing.T) {
- rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
- rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
- output, err := executeCommand(rootCmd, "help")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, rootCmd.Long)
- }
- func TestHelpCommandExecutedOnChild(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun}
- rootCmd.AddCommand(childCmd)
- output, err := executeCommand(rootCmd, "help", "child")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, childCmd.Long)
- }
- func TestSetHelpCommand(t *testing.T) {
- c := &Command{Use: "c", Run: emptyRun}
- c.AddCommand(&Command{Use: "empty", Run: emptyRun})
- expected := "WORKS"
- c.SetHelpCommand(&Command{
- Use: "help [command]",
- Short: "Help about any command",
- Long: `Help provides help for any command in the application.
- Simply type ` + c.Name() + ` help [path to command] for full details.`,
- Run: func(c *Command, _ []string) { c.Print(expected) },
- })
- got, err := executeCommand(c, "help")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if got != expected {
- t.Errorf("Expected to contain %q, got %q", expected, got)
- }
- }
- func TestHelpFlagExecuted(t *testing.T) {
- rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
- output, err := executeCommand(rootCmd, "--help")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, rootCmd.Long)
- }
- func TestHelpFlagExecutedOnChild(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun}
- rootCmd.AddCommand(childCmd)
- output, err := executeCommand(rootCmd, "child", "--help")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, childCmd.Long)
- }
- // TestHelpFlagInHelp checks,
- // if '--help' flag is shown in help for child (executing `parent help child`),
- // that has no other flags.
- // Related to https://github.com/spf13/cobra/issues/302.
- func TestHelpFlagInHelp(t *testing.T) {
- parentCmd := &Command{Use: "parent", Run: func(*Command, []string) {}}
- childCmd := &Command{Use: "child", Run: func(*Command, []string) {}}
- parentCmd.AddCommand(childCmd)
- output, err := executeCommand(parentCmd, "help", "child")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, "[flags]")
- }
- func TestFlagsInUsage(t *testing.T) {
- rootCmd := &Command{Use: "root", Args: NoArgs, Run: func(*Command, []string) {}}
- output, err := executeCommand(rootCmd, "--help")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, "[flags]")
- }
- func TestHelpExecutedOnNonRunnableChild(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- childCmd := &Command{Use: "child", Long: "Long description"}
- rootCmd.AddCommand(childCmd)
- output, err := executeCommand(rootCmd, "child")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, childCmd.Long)
- }
- func TestVersionFlagExecuted(t *testing.T) {
- rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
- output, err := executeCommand(rootCmd, "--version", "arg1")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, "root version 1.0.0")
- }
- func TestVersionTemplate(t *testing.T) {
- rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
- rootCmd.SetVersionTemplate(`customized version: {{.Version}}`)
- output, err := executeCommand(rootCmd, "--version", "arg1")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, "customized version: 1.0.0")
- }
- func TestVersionFlagExecutedOnSubcommand(t *testing.T) {
- rootCmd := &Command{Use: "root", Version: "1.0.0"}
- rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
- output, err := executeCommand(rootCmd, "--version", "sub")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, "root version 1.0.0")
- }
- func TestVersionFlagOnlyAddedToRoot(t *testing.T) {
- rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
- rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
- _, err := executeCommand(rootCmd, "sub", "--version")
- if err == nil {
- t.Errorf("Expected error")
- }
- checkStringContains(t, err.Error(), "unknown flag: --version")
- }
- func TestVersionFlagOnlyExistsIfVersionNonEmpty(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- _, err := executeCommand(rootCmd, "--version")
- if err == nil {
- t.Errorf("Expected error")
- }
- checkStringContains(t, err.Error(), "unknown flag: --version")
- }
- func TestUsageIsNotPrintedTwice(t *testing.T) {
- var cmd = &Command{Use: "root"}
- var sub = &Command{Use: "sub"}
- cmd.AddCommand(sub)
- output, _ := executeCommand(cmd, "")
- if strings.Count(output, "Usage:") != 1 {
- t.Error("Usage output is not printed exactly once")
- }
- }
- func TestVisitParents(t *testing.T) {
- c := &Command{Use: "app"}
- sub := &Command{Use: "sub"}
- dsub := &Command{Use: "dsub"}
- sub.AddCommand(dsub)
- c.AddCommand(sub)
- total := 0
- add := func(x *Command) {
- total++
- }
- sub.VisitParents(add)
- if total != 1 {
- t.Errorf("Should have visited 1 parent but visited %d", total)
- }
- total = 0
- dsub.VisitParents(add)
- if total != 2 {
- t.Errorf("Should have visited 2 parents but visited %d", total)
- }
- total = 0
- c.VisitParents(add)
- if total != 0 {
- t.Errorf("Should have visited no parents but visited %d", total)
- }
- }
- func TestSuggestions(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- timesCmd := &Command{
- Use: "times",
- SuggestFor: []string{"counts"},
- Run: emptyRun,
- }
- rootCmd.AddCommand(timesCmd)
- templateWithSuggestions := "Error: unknown command \"%s\" for \"root\"\n\nDid you mean this?\n\t%s\n\nRun 'root --help' for usage.\n"
- templateWithoutSuggestions := "Error: unknown command \"%s\" for \"root\"\nRun 'root --help' for usage.\n"
- tests := map[string]string{
- "time": "times",
- "tiems": "times",
- "tims": "times",
- "timeS": "times",
- "rimes": "times",
- "ti": "times",
- "t": "times",
- "timely": "times",
- "ri": "",
- "timezone": "",
- "foo": "",
- "counts": "times",
- }
- for typo, suggestion := range tests {
- for _, suggestionsDisabled := range []bool{true, false} {
- rootCmd.DisableSuggestions = suggestionsDisabled
- var expected string
- output, _ := executeCommand(rootCmd, typo)
- if suggestion == "" || suggestionsDisabled {
- expected = fmt.Sprintf(templateWithoutSuggestions, typo)
- } else {
- expected = fmt.Sprintf(templateWithSuggestions, typo, suggestion)
- }
- if output != expected {
- t.Errorf("Unexpected response.\nExpected:\n %q\nGot:\n %q\n", expected, output)
- }
- }
- }
- }
- func TestRemoveCommand(t *testing.T) {
- rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
- childCmd := &Command{Use: "child", Run: emptyRun}
- rootCmd.AddCommand(childCmd)
- rootCmd.RemoveCommand(childCmd)
- _, err := executeCommand(rootCmd, "child")
- if err == nil {
- t.Error("Expected error on calling removed command. Got nil.")
- }
- }
- func TestReplaceCommandWithRemove(t *testing.T) {
- childUsed := 0
- rootCmd := &Command{Use: "root", Run: emptyRun}
- child1Cmd := &Command{
- Use: "child",
- Run: func(*Command, []string) { childUsed = 1 },
- }
- child2Cmd := &Command{
- Use: "child",
- Run: func(*Command, []string) { childUsed = 2 },
- }
- rootCmd.AddCommand(child1Cmd)
- rootCmd.RemoveCommand(child1Cmd)
- rootCmd.AddCommand(child2Cmd)
- output, err := executeCommand(rootCmd, "child")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if childUsed == 1 {
- t.Error("Removed command shouldn't be called")
- }
- if childUsed != 2 {
- t.Error("Replacing command should have been called but didn't")
- }
- }
- func TestDeprecatedCommand(t *testing.T) {
- rootCmd := &Command{Use: "root", Run: emptyRun}
- deprecatedCmd := &Command{
- Use: "deprecated",
- Deprecated: "This command is deprecated",
- Run: emptyRun,
- }
- rootCmd.AddCommand(deprecatedCmd)
- output, err := executeCommand(rootCmd, "deprecated")
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- checkStringContains(t, output, deprecatedCmd.Deprecated)
- }
- func TestHooks(t *testing.T) {
- var (
- persPreArgs string
- preArgs string
- runArgs string
- postArgs string
- persPostArgs string
- )
- c := &Command{
- Use: "c",
- PersistentPreRun: func(_ *Command, args []string) {
- persPreArgs = strings.Join(args, " ")
- },
- PreRun: func(_ *Command, args []string) {
- preArgs = strings.Join(args, " ")
- },
- Run: func(_ *Command, args []string) {
- runArgs = strings.Join(args, " ")
- },
- PostRun: func(_ *Command, args []string) {
- postArgs = strings.Join(args, " ")
- },
- PersistentPostRun: func(_ *Command, args []string) {
- persPostArgs = strings.Join(args, " ")
- },
- }
- output, err := executeCommand(c, "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if persPreArgs != "one two" {
- t.Errorf("Expected persPreArgs %q, got %q", "one two", persPreArgs)
- }
- if preArgs != "one two" {
- t.Errorf("Expected preArgs %q, got %q", "one two", preArgs)
- }
- if runArgs != "one two" {
- t.Errorf("Expected runArgs %q, got %q", "one two", runArgs)
- }
- if postArgs != "one two" {
- t.Errorf("Expected postArgs %q, got %q", "one two", postArgs)
- }
- if persPostArgs != "one two" {
- t.Errorf("Expected persPostArgs %q, got %q", "one two", persPostArgs)
- }
- }
- func TestPersistentHooks(t *testing.T) {
- var (
- parentPersPreArgs string
- parentPreArgs string
- parentRunArgs string
- parentPostArgs string
- parentPersPostArgs string
- )
- var (
- childPersPreArgs string
- childPreArgs string
- childRunArgs string
- childPostArgs string
- childPersPostArgs string
- )
- parentCmd := &Command{
- Use: "parent",
- PersistentPreRun: func(_ *Command, args []string) {
- parentPersPreArgs = strings.Join(args, " ")
- },
- PreRun: func(_ *Command, args []string) {
- parentPreArgs = strings.Join(args, " ")
- },
- Run: func(_ *Command, args []string) {
- parentRunArgs = strings.Join(args, " ")
- },
- PostRun: func(_ *Command, args []string) {
- parentPostArgs = strings.Join(args, " ")
- },
- PersistentPostRun: func(_ *Command, args []string) {
- parentPersPostArgs = strings.Join(args, " ")
- },
- }
- childCmd := &Command{
- Use: "child",
- PersistentPreRun: func(_ *Command, args []string) {
- childPersPreArgs = strings.Join(args, " ")
- },
- PreRun: func(_ *Command, args []string) {
- childPreArgs = strings.Join(args, " ")
- },
- Run: func(_ *Command, args []string) {
- childRunArgs = strings.Join(args, " ")
- },
- PostRun: func(_ *Command, args []string) {
- childPostArgs = strings.Join(args, " ")
- },
- PersistentPostRun: func(_ *Command, args []string) {
- childPersPostArgs = strings.Join(args, " ")
- },
- }
- parentCmd.AddCommand(childCmd)
- output, err := executeCommand(parentCmd, "child", "one", "two")
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- // TODO: This test fails, but should not.
- // Related to https://github.com/spf13/cobra/issues/252.
- //
- // if parentPersPreArgs != "one two" {
- // t.Errorf("Expected parentPersPreArgs %q, got %q", "one two", parentPersPreArgs)
- // }
- if parentPreArgs != "" {
- t.Errorf("Expected blank parentPreArgs, got %q", parentPreArgs)
- }
- if parentRunArgs != "" {
- t.Errorf("Expected blank parentRunArgs, got %q", parentRunArgs)
- }
- if parentPostArgs != "" {
- t.Errorf("Expected blank parentPostArgs, got %q", parentPostArgs)
- }
- // TODO: This test fails, but should not.
- // Related to https://github.com/spf13/cobra/issues/252.
- //
- // if parentPersPostArgs != "one two" {
- // t.Errorf("Expected parentPersPostArgs %q, got %q", "one two", parentPersPostArgs)
- // }
- if childPersPreArgs != "one two" {
- t.Errorf("Expected childPersPreArgs %q, got %q", "one two", childPersPreArgs)
- }
- if childPreArgs != "one two" {
- t.Errorf("Expected childPreArgs %q, got %q", "one two", childPreArgs)
- }
- if childRunArgs != "one two" {
- t.Errorf("Expected childRunArgs %q, got %q", "one two", childRunArgs)
- }
- if childPostArgs != "one two" {
- t.Errorf("Expected childPostArgs %q, got %q", "one two", childPostArgs)
- }
- if childPersPostArgs != "one two" {
- t.Errorf("Expected childPersPostArgs %q, got %q", "one two", childPersPostArgs)
- }
- }
- // Related to https://github.com/spf13/cobra/issues/521.
- func TestGlobalNormFuncPropagation(t *testing.T) {
- normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
- return pflag.NormalizedName(name)
- }
- rootCmd := &Command{Use: "root", Run: emptyRun}
- childCmd := &Command{Use: "child", Run: emptyRun}
- rootCmd.AddCommand(childCmd)
- rootCmd.SetGlobalNormalizationFunc(normFunc)
- if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() {
- t.Error("rootCmd seems to have a wrong normalization function")
- }
- if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(childCmd.GlobalNormalizationFunc()).Pointer() {
- t.Error("childCmd should have had the normalization function of rootCmd")
- }
- }
- // Related to https://github.com/spf13/cobra/issues/521.
- func TestNormPassedOnLocal(t *testing.T) {
- toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
- return pflag.NormalizedName(strings.ToUpper(name))
- }
- c := &Command{}
- c.Flags().Bool("flagname", true, "this is a dummy flag")
- c.SetGlobalNormalizationFunc(toUpper)
- if c.LocalFlags().Lookup("flagname") != c.LocalFlags().Lookup("FLAGNAME") {
- t.Error("Normalization function should be passed on to Local flag set")
- }
- }
- // Related to https://github.com/spf13/cobra/issues/521.
- func TestNormPassedOnInherited(t *testing.T) {
- toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
- return pflag.NormalizedName(strings.ToUpper(name))
- }
- c := &Command{}
- c.SetGlobalNormalizationFunc(toUpper)
- child1 := &Command{}
- c.AddCommand(child1)
- c.PersistentFlags().Bool("flagname", true, "")
- child2 := &Command{}
- c.AddCommand(child2)
- inherited := child1.InheritedFlags()
- if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") {
- t.Error("Normalization function should be passed on to inherited flag set in command added before flag")
- }
- inherited = child2.InheritedFlags()
- if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") {
- t.Error("Normalization function should be passed on to inherited flag set in command added after flag")
- }
- }
- // Related to https://github.com/spf13/cobra/issues/521.
- func TestConsistentNormalizedName(t *testing.T) {
- toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
- return pflag.NormalizedName(strings.ToUpper(name))
- }
- n := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
- return pflag.NormalizedName(name)
- }
- c := &Command{}
- c.Flags().Bool("flagname", true, "")
- c.SetGlobalNormalizationFunc(toUpper)
- c.SetGlobalNormalizationFunc(n)
- if c.LocalFlags().Lookup("flagname") == c.LocalFlags().Lookup("FLAGNAME") {
- t.Error("Normalizing flag names should not result in duplicate flags")
- }
- }
- func TestFlagOnPflagCommandLine(t *testing.T) {
- flagName := "flagOnCommandLine"
- pflag.String(flagName, "", "about my flag")
- c := &Command{Use: "c", Run: emptyRun}
- c.AddCommand(&Command{Use: "child", Run: emptyRun})
- output, _ := executeCommand(c, "--help")
- checkStringContains(t, output, flagName)
- resetCommandLineFlagSet()
- }
- // TestHiddenCommandExecutes checks,
- // if hidden commands run as intended.
- func TestHiddenCommandExecutes(t *testing.T) {
- executed := false
- c := &Command{
- Use: "c",
- Hidden: true,
- Run: func(*Command, []string) { executed = true },
- }
- output, err := executeCommand(c)
- if output != "" {
- t.Errorf("Unexpected output: %v", output)
- }
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if !executed {
- t.Error("Hidden command should have been executed")
- }
- }
- // test to ensure hidden commands do not show up in usage/help text
- func TestHiddenCommandIsHidden(t *testing.T) {
- c := &Command{Use: "c", Hidden: true, Run: emptyRun}
- if c.IsAvailableCommand() {
- t.Errorf("Hidden command should be unavailable")
- }
- }
- func TestCommandsAreSorted(t *testing.T) {
- EnableCommandSorting = true
- originalNames := []string{"middle", "zlast", "afirst"}
- expectedNames := []string{"afirst", "middle", "zlast"}
- var rootCmd = &Command{Use: "root"}
- for _, name := range originalNames {
- rootCmd.AddCommand(&Command{Use: name})
- }
- for i, c := range rootCmd.Commands() {
- got := c.Name()
- if expectedNames[i] != got {
- t.Errorf("Expected: %s, got: %s", expectedNames[i], got)
- }
- }
- EnableCommandSorting = true
- }
- func TestEnableCommandSortingIsDisabled(t *testing.T) {
- EnableCommandSorting = false
- originalNames := []string{"middle", "zlast", "afirst"}
- var rootCmd = &Command{Use: "root"}
- for _, name := range originalNames {
- rootCmd.AddCommand(&Command{Use: name})
- }
- for i, c := range rootCmd.Commands() {
- got := c.Name()
- if originalNames[i] != got {
- t.Errorf("expected: %s, got: %s", originalNames[i], got)
- }
- }
- EnableCommandSorting = true
- }
- func TestSetOutput(t *testing.T) {
- c := &Command{}
- c.SetOutput(nil)
- if out := c.OutOrStdout(); out != os.Stdout {
- t.Errorf("Expected setting output to nil to revert back to stdout")
- }
- }
- func TestFlagErrorFunc(t *testing.T) {
- c := &Command{Use: "c", Run: emptyRun}
- expectedFmt := "This is expected: %v"
- c.SetFlagErrorFunc(func(_ *Command, err error) error {
- return fmt.Errorf(expectedFmt, err)
- })
- _, err := executeCommand(c, "--unknown-flag")
- got := err.Error()
- expected := fmt.Sprintf(expectedFmt, "unknown flag: --unknown-flag")
- if got != expected {
- t.Errorf("Expected %v, got %v", expected, got)
- }
- }
- // TestSortedFlags checks,
- // if cmd.LocalFlags() is unsorted when cmd.Flags().SortFlags set to false.
- // Related to https://github.com/spf13/cobra/issues/404.
- func TestSortedFlags(t *testing.T) {
- c := &Command{}
- c.Flags().SortFlags = false
- names := []string{"C", "B", "A", "D"}
- for _, name := range names {
- c.Flags().Bool(name, false, "")
- }
- i := 0
- c.LocalFlags().VisitAll(func(f *pflag.Flag) {
- if i == len(names) {
- return
- }
- if stringInSlice(f.Name, names) {
- if names[i] != f.Name {
- t.Errorf("Incorrect order. Expected %v, got %v", names[i], f.Name)
- }
- i++
- }
- })
- }
- // TestMergeCommandLineToFlags checks,
- // if pflag.CommandLine is correctly merged to c.Flags() after first call
- // of c.mergePersistentFlags.
- // Related to https://github.com/spf13/cobra/issues/443.
- func TestMergeCommandLineToFlags(t *testing.T) {
- pflag.Bool("boolflag", false, "")
- c := &Command{Use: "c", Run: emptyRun}
- c.mergePersistentFlags()
- if c.Flags().Lookup("boolflag") == nil {
- t.Fatal("Expecting to have flag from CommandLine in c.Flags()")
- }
- resetCommandLineFlagSet()
- }
- // TestUseDeprecatedFlags checks,
- // if cobra.Execute() prints a message, if a deprecated flag is used.
- // Related to https://github.com/spf13/cobra/issues/463.
- func TestUseDeprecatedFlags(t *testing.T) {
- c := &Command{Use: "c", Run: emptyRun}
- c.Flags().BoolP("deprecated", "d", false, "deprecated flag")
- c.Flags().MarkDeprecated("deprecated", "This flag is deprecated")
- output, err := executeCommand(c, "c", "-d")
- if err != nil {
- t.Error("Unexpected error:", err)
- }
- checkStringContains(t, output, "This flag is deprecated")
- }
- func TestTraverseWithParentFlags(t *testing.T) {
- rootCmd := &Command{Use: "root", TraverseChildren: true}
- rootCmd.Flags().String("str", "", "")
- rootCmd.Flags().BoolP("bool", "b", false, "")
- childCmd := &Command{Use: "child"}
- childCmd.Flags().Int("int", -1, "")
- rootCmd.AddCommand(childCmd)
- c, args, err := rootCmd.Traverse([]string{"-b", "--str", "ok", "child", "--int"})
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if len(args) != 1 && args[0] != "--add" {
- t.Errorf("Wrong args: %v", args)
- }
- if c.Name() != childCmd.Name() {
- t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name())
- }
- }
- func TestTraverseNoParentFlags(t *testing.T) {
- rootCmd := &Command{Use: "root", TraverseChildren: true}
- rootCmd.Flags().String("foo", "", "foo things")
- childCmd := &Command{Use: "child"}
- childCmd.Flags().String("str", "", "")
- rootCmd.AddCommand(childCmd)
- c, args, err := rootCmd.Traverse([]string{"child"})
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if len(args) != 0 {
- t.Errorf("Wrong args %v", args)
- }
- if c.Name() != childCmd.Name() {
- t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name())
- }
- }
- func TestTraverseWithBadParentFlags(t *testing.T) {
- rootCmd := &Command{Use: "root", TraverseChildren: true}
- childCmd := &Command{Use: "child"}
- childCmd.Flags().String("str", "", "")
- rootCmd.AddCommand(childCmd)
- expected := "unknown flag: --str"
- c, _, err := rootCmd.Traverse([]string{"--str", "ok", "child"})
- if err == nil || !strings.Contains(err.Error(), expected) {
- t.Errorf("Expected error, %q, got %q", expected, err)
- }
- if c != nil {
- t.Errorf("Expected nil command")
- }
- }
- func TestTraverseWithBadChildFlag(t *testing.T) {
- rootCmd := &Command{Use: "root", TraverseChildren: true}
- rootCmd.Flags().String("str", "", "")
- childCmd := &Command{Use: "child"}
- rootCmd.AddCommand(childCmd)
- // Expect no error because the last commands args shouldn't be parsed in
- // Traverse.
- c, args, err := rootCmd.Traverse([]string{"child", "--str"})
- if err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if len(args) != 1 && args[0] != "--str" {
- t.Errorf("Wrong args: %v", args)
- }
- if c.Name() != childCmd.Name() {
- t.Errorf("Expected command %q, got: %q", childCmd.Name(), c.Name())
- }
- }
- func TestTraverseWithTwoSubcommands(t *testing.T) {
- rootCmd := &Command{Use: "root", TraverseChildren: true}
- subCmd := &Command{Use: "sub", TraverseChildren: true}
- rootCmd.AddCommand(subCmd)
- subsubCmd := &Command{
- Use: "subsub",
- }
- subCmd.AddCommand(subsubCmd)
- c, _, err := rootCmd.Traverse([]string{"sub", "subsub"})
- if err != nil {
- t.Fatalf("Unexpected error: %v", err)
- }
- if c.Name() != subsubCmd.Name() {
- t.Fatalf("Expected command: %q, got %q", subsubCmd.Name(), c.Name())
- }
- }
- // TestUpdateName checks if c.Name() updates on changed c.Use.
- // Related to https://github.com/spf13/cobra/pull/422#discussion_r143918343.
- func TestUpdateName(t *testing.T) {
- c := &Command{Use: "name xyz"}
- originalName := c.Name()
- c.Use = "changedName abc"
- if originalName == c.Name() || c.Name() != "changedName" {
- t.Error("c.Name() should be updated on changed c.Use")
- }
- }
- type calledAsTestcase struct {
- args []string
- call string
- want string
- epm bool
- tc bool
- }
- func (tc *calledAsTestcase) test(t *testing.T) {
- defer func(ov bool) { EnablePrefixMatching = ov }(EnablePrefixMatching)
- EnablePrefixMatching = tc.epm
- var called *Command
- run := func(c *Command, _ []string) { t.Logf("called: %q", c.Name()); called = c }
- parent := &Command{Use: "parent", Run: run}
- child1 := &Command{Use: "child1", Run: run, Aliases: []string{"this"}}
- child2 := &Command{Use: "child2", Run: run, Aliases: []string{"that"}}
- parent.AddCommand(child1)
- parent.AddCommand(child2)
- parent.SetArgs(tc.args)
- output := new(bytes.Buffer)
- parent.SetOutput(output)
- parent.Execute()
- if called == nil {
- if tc.call != "" {
- t.Errorf("missing expected call to command: %s", tc.call)
- }
- return
- }
- if called.Name() != tc.call {
- t.Errorf("called command == %q; Wanted %q", called.Name(), tc.call)
- } else if got := called.CalledAs(); got != tc.want {
- t.Errorf("%s.CalledAs() == %q; Wanted: %q", tc.call, got, tc.want)
- }
- }
- func TestCalledAs(t *testing.T) {
- tests := map[string]calledAsTestcase{
- "find/no-args": {nil, "parent", "parent", false, false},
- "find/real-name": {[]string{"child1"}, "child1", "child1", false, false},
- "find/full-alias": {[]string{"that"}, "child2", "that", false, false},
- "find/part-no-prefix": {[]string{"thi"}, "", "", false, false},
- "find/part-alias": {[]string{"thi"}, "child1", "this", true, false},
- "find/conflict": {[]string{"th"}, "", "", true, false},
- "traverse/no-args": {nil, "parent", "parent", false, true},
- "traverse/real-name": {[]string{"child1"}, "child1", "child1", false, true},
- "traverse/full-alias": {[]string{"that"}, "child2", "that", false, true},
- "traverse/part-no-prefix": {[]string{"thi"}, "", "", false, true},
- "traverse/part-alias": {[]string{"thi"}, "child1", "this", true, true},
- "traverse/conflict": {[]string{"th"}, "", "", true, true},
- }
- for name, tc := range tests {
- t.Run(name, tc.test)
- }
- }
- func TestFParseErrWhitelistBackwardCompatibility(t *testing.T) {
- c := &Command{Use: "c", Run: emptyRun}
- c.Flags().BoolP("boola", "a", false, "a boolean flag")
- output, err := executeCommand(c, "c", "-a", "--unknown", "flag")
- if err == nil {
- t.Error("expected unknown flag error")
- }
- checkStringContains(t, output, "unknown flag: --unknown")
- }
- func TestFParseErrWhitelistSameCommand(t *testing.T) {
- c := &Command{
- Use: "c",
- Run: emptyRun,
- FParseErrWhitelist: FParseErrWhitelist{
- UnknownFlags: true,
- },
- }
- c.Flags().BoolP("boola", "a", false, "a boolean flag")
- _, err := executeCommand(c, "c", "-a", "--unknown", "flag")
- if err != nil {
- t.Error("unexpected error: ", err)
- }
- }
- func TestFParseErrWhitelistParentCommand(t *testing.T) {
- root := &Command{
- Use: "root",
- Run: emptyRun,
- FParseErrWhitelist: FParseErrWhitelist{
- UnknownFlags: true,
- },
- }
- c := &Command{
- Use: "child",
- Run: emptyRun,
- }
- c.Flags().BoolP("boola", "a", false, "a boolean flag")
- root.AddCommand(c)
- output, err := executeCommand(root, "child", "-a", "--unknown", "flag")
- if err == nil {
- t.Error("expected unknown flag error")
- }
- checkStringContains(t, output, "unknown flag: --unknown")
- }
- func TestFParseErrWhitelistChildCommand(t *testing.T) {
- root := &Command{
- Use: "root",
- Run: emptyRun,
- }
- c := &Command{
- Use: "child",
- Run: emptyRun,
- FParseErrWhitelist: FParseErrWhitelist{
- UnknownFlags: true,
- },
- }
- c.Flags().BoolP("boola", "a", false, "a boolean flag")
- root.AddCommand(c)
- _, err := executeCommand(root, "child", "-a", "--unknown", "flag")
- if err != nil {
- t.Error("unexpected error: ", err.Error())
- }
- }
- func TestFParseErrWhitelistSiblingCommand(t *testing.T) {
- root := &Command{
- Use: "root",
- Run: emptyRun,
- }
- c := &Command{
- Use: "child",
- Run: emptyRun,
- FParseErrWhitelist: FParseErrWhitelist{
- UnknownFlags: true,
- },
- }
- c.Flags().BoolP("boola", "a", false, "a boolean flag")
- s := &Command{
- Use: "sibling",
- Run: emptyRun,
- }
- s.Flags().BoolP("boolb", "b", false, "a boolean flag")
- root.AddCommand(c)
- root.AddCommand(s)
- output, err := executeCommand(root, "sibling", "-b", "--unknown", "flag")
- if err == nil {
- t.Error("expected unknown flag error")
- }
- checkStringContains(t, output, "unknown flag: --unknown")
- }
|