command_test.go 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733
  1. package cobra
  2. import (
  3. "bytes"
  4. "fmt"
  5. "os"
  6. "reflect"
  7. "strings"
  8. "testing"
  9. "github.com/spf13/pflag"
  10. )
  11. func emptyRun(*Command, []string) {}
  12. func executeCommand(root *Command, args ...string) (output string, err error) {
  13. _, output, err = executeCommandC(root, args...)
  14. return output, err
  15. }
  16. func executeCommandC(root *Command, args ...string) (c *Command, output string, err error) {
  17. buf := new(bytes.Buffer)
  18. root.SetOutput(buf)
  19. root.SetArgs(args)
  20. c, err = root.ExecuteC()
  21. return c, buf.String(), err
  22. }
  23. func resetCommandLineFlagSet() {
  24. pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
  25. }
  26. func checkStringContains(t *testing.T, got, expected string) {
  27. if !strings.Contains(got, expected) {
  28. t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expected, got)
  29. }
  30. }
  31. func checkStringOmits(t *testing.T, got, expected string) {
  32. if strings.Contains(got, expected) {
  33. t.Errorf("Expected to not contain: \n %v\nGot: %v", expected, got)
  34. }
  35. }
  36. func TestSingleCommand(t *testing.T) {
  37. var rootCmdArgs []string
  38. rootCmd := &Command{
  39. Use: "root",
  40. Args: ExactArgs(2),
  41. Run: func(_ *Command, args []string) { rootCmdArgs = args },
  42. }
  43. aCmd := &Command{Use: "a", Args: NoArgs, Run: emptyRun}
  44. bCmd := &Command{Use: "b", Args: NoArgs, Run: emptyRun}
  45. rootCmd.AddCommand(aCmd, bCmd)
  46. output, err := executeCommand(rootCmd, "one", "two")
  47. if output != "" {
  48. t.Errorf("Unexpected output: %v", output)
  49. }
  50. if err != nil {
  51. t.Errorf("Unexpected error: %v", err)
  52. }
  53. got := strings.Join(rootCmdArgs, " ")
  54. expected := "one two"
  55. if got != expected {
  56. t.Errorf("rootCmdArgs expected: %q, got: %q", expected, got)
  57. }
  58. }
  59. func TestChildCommand(t *testing.T) {
  60. var child1CmdArgs []string
  61. rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
  62. child1Cmd := &Command{
  63. Use: "child1",
  64. Args: ExactArgs(2),
  65. Run: func(_ *Command, args []string) { child1CmdArgs = args },
  66. }
  67. child2Cmd := &Command{Use: "child2", Args: NoArgs, Run: emptyRun}
  68. rootCmd.AddCommand(child1Cmd, child2Cmd)
  69. output, err := executeCommand(rootCmd, "child1", "one", "two")
  70. if output != "" {
  71. t.Errorf("Unexpected output: %v", output)
  72. }
  73. if err != nil {
  74. t.Errorf("Unexpected error: %v", err)
  75. }
  76. got := strings.Join(child1CmdArgs, " ")
  77. expected := "one two"
  78. if got != expected {
  79. t.Errorf("child1CmdArgs expected: %q, got: %q", expected, got)
  80. }
  81. }
  82. func TestCallCommandWithoutSubcommands(t *testing.T) {
  83. rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
  84. _, err := executeCommand(rootCmd)
  85. if err != nil {
  86. t.Errorf("Calling command without subcommands should not have error: %v", err)
  87. }
  88. }
  89. func TestRootExecuteUnknownCommand(t *testing.T) {
  90. rootCmd := &Command{Use: "root", Run: emptyRun}
  91. rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
  92. output, _ := executeCommand(rootCmd, "unknown")
  93. expected := "Error: unknown command \"unknown\" for \"root\"\nRun 'root --help' for usage.\n"
  94. if output != expected {
  95. t.Errorf("Expected:\n %q\nGot:\n %q\n", expected, output)
  96. }
  97. }
  98. func TestSubcommandExecuteC(t *testing.T) {
  99. rootCmd := &Command{Use: "root", Run: emptyRun}
  100. childCmd := &Command{Use: "child", Run: emptyRun}
  101. rootCmd.AddCommand(childCmd)
  102. c, output, err := executeCommandC(rootCmd, "child")
  103. if output != "" {
  104. t.Errorf("Unexpected output: %v", output)
  105. }
  106. if err != nil {
  107. t.Errorf("Unexpected error: %v", err)
  108. }
  109. if c.Name() != "child" {
  110. t.Errorf(`invalid command returned from ExecuteC: expected "child"', got %q`, c.Name())
  111. }
  112. }
  113. func TestRootUnknownCommandSilenced(t *testing.T) {
  114. rootCmd := &Command{Use: "root", Run: emptyRun}
  115. rootCmd.SilenceErrors = true
  116. rootCmd.SilenceUsage = true
  117. rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
  118. output, _ := executeCommand(rootCmd, "unknown")
  119. if output != "" {
  120. t.Errorf("Expected blank output, because of silenced usage.\nGot:\n %q\n", output)
  121. }
  122. }
  123. func TestCommandAlias(t *testing.T) {
  124. var timesCmdArgs []string
  125. rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
  126. echoCmd := &Command{
  127. Use: "echo",
  128. Aliases: []string{"say", "tell"},
  129. Args: NoArgs,
  130. Run: emptyRun,
  131. }
  132. timesCmd := &Command{
  133. Use: "times",
  134. Args: ExactArgs(2),
  135. Run: func(_ *Command, args []string) { timesCmdArgs = args },
  136. }
  137. echoCmd.AddCommand(timesCmd)
  138. rootCmd.AddCommand(echoCmd)
  139. output, err := executeCommand(rootCmd, "tell", "times", "one", "two")
  140. if output != "" {
  141. t.Errorf("Unexpected output: %v", output)
  142. }
  143. if err != nil {
  144. t.Errorf("Unexpected error: %v", err)
  145. }
  146. got := strings.Join(timesCmdArgs, " ")
  147. expected := "one two"
  148. if got != expected {
  149. t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got)
  150. }
  151. }
  152. func TestEnablePrefixMatching(t *testing.T) {
  153. EnablePrefixMatching = true
  154. var aCmdArgs []string
  155. rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
  156. aCmd := &Command{
  157. Use: "aCmd",
  158. Args: ExactArgs(2),
  159. Run: func(_ *Command, args []string) { aCmdArgs = args },
  160. }
  161. bCmd := &Command{Use: "bCmd", Args: NoArgs, Run: emptyRun}
  162. rootCmd.AddCommand(aCmd, bCmd)
  163. output, err := executeCommand(rootCmd, "a", "one", "two")
  164. if output != "" {
  165. t.Errorf("Unexpected output: %v", output)
  166. }
  167. if err != nil {
  168. t.Errorf("Unexpected error: %v", err)
  169. }
  170. got := strings.Join(aCmdArgs, " ")
  171. expected := "one two"
  172. if got != expected {
  173. t.Errorf("aCmdArgs expected: %q, got: %q", expected, got)
  174. }
  175. EnablePrefixMatching = false
  176. }
  177. func TestAliasPrefixMatching(t *testing.T) {
  178. EnablePrefixMatching = true
  179. var timesCmdArgs []string
  180. rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
  181. echoCmd := &Command{
  182. Use: "echo",
  183. Aliases: []string{"say", "tell"},
  184. Args: NoArgs,
  185. Run: emptyRun,
  186. }
  187. timesCmd := &Command{
  188. Use: "times",
  189. Args: ExactArgs(2),
  190. Run: func(_ *Command, args []string) { timesCmdArgs = args },
  191. }
  192. echoCmd.AddCommand(timesCmd)
  193. rootCmd.AddCommand(echoCmd)
  194. output, err := executeCommand(rootCmd, "sa", "times", "one", "two")
  195. if output != "" {
  196. t.Errorf("Unexpected output: %v", output)
  197. }
  198. if err != nil {
  199. t.Errorf("Unexpected error: %v", err)
  200. }
  201. got := strings.Join(timesCmdArgs, " ")
  202. expected := "one two"
  203. if got != expected {
  204. t.Errorf("timesCmdArgs expected: %v, got: %v", expected, got)
  205. }
  206. EnablePrefixMatching = false
  207. }
  208. // TestChildSameName checks the correct behaviour of cobra in cases,
  209. // when an application with name "foo" and with subcommand "foo"
  210. // is executed with args "foo foo".
  211. func TestChildSameName(t *testing.T) {
  212. var fooCmdArgs []string
  213. rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun}
  214. fooCmd := &Command{
  215. Use: "foo",
  216. Args: ExactArgs(2),
  217. Run: func(_ *Command, args []string) { fooCmdArgs = args },
  218. }
  219. barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun}
  220. rootCmd.AddCommand(fooCmd, barCmd)
  221. output, err := executeCommand(rootCmd, "foo", "one", "two")
  222. if output != "" {
  223. t.Errorf("Unexpected output: %v", output)
  224. }
  225. if err != nil {
  226. t.Errorf("Unexpected error: %v", err)
  227. }
  228. got := strings.Join(fooCmdArgs, " ")
  229. expected := "one two"
  230. if got != expected {
  231. t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got)
  232. }
  233. }
  234. // TestGrandChildSameName checks the correct behaviour of cobra in cases,
  235. // when user has a root command and a grand child
  236. // with the same name.
  237. func TestGrandChildSameName(t *testing.T) {
  238. var fooCmdArgs []string
  239. rootCmd := &Command{Use: "foo", Args: NoArgs, Run: emptyRun}
  240. barCmd := &Command{Use: "bar", Args: NoArgs, Run: emptyRun}
  241. fooCmd := &Command{
  242. Use: "foo",
  243. Args: ExactArgs(2),
  244. Run: func(_ *Command, args []string) { fooCmdArgs = args },
  245. }
  246. barCmd.AddCommand(fooCmd)
  247. rootCmd.AddCommand(barCmd)
  248. output, err := executeCommand(rootCmd, "bar", "foo", "one", "two")
  249. if output != "" {
  250. t.Errorf("Unexpected output: %v", output)
  251. }
  252. if err != nil {
  253. t.Errorf("Unexpected error: %v", err)
  254. }
  255. got := strings.Join(fooCmdArgs, " ")
  256. expected := "one two"
  257. if got != expected {
  258. t.Errorf("fooCmdArgs expected: %v, got: %v", expected, got)
  259. }
  260. }
  261. func TestFlagLong(t *testing.T) {
  262. var cArgs []string
  263. c := &Command{
  264. Use: "c",
  265. Args: ArbitraryArgs,
  266. Run: func(_ *Command, args []string) { cArgs = args },
  267. }
  268. var intFlagValue int
  269. var stringFlagValue string
  270. c.Flags().IntVar(&intFlagValue, "intf", -1, "")
  271. c.Flags().StringVar(&stringFlagValue, "sf", "", "")
  272. output, err := executeCommand(c, "--intf=7", "--sf=abc", "one", "--", "two")
  273. if output != "" {
  274. t.Errorf("Unexpected output: %v", err)
  275. }
  276. if err != nil {
  277. t.Errorf("Unexpected error: %v", err)
  278. }
  279. if c.ArgsLenAtDash() != 1 {
  280. t.Errorf("Expected ArgsLenAtDash: %v but got %v", 1, c.ArgsLenAtDash())
  281. }
  282. if intFlagValue != 7 {
  283. t.Errorf("Expected intFlagValue: %v, got %v", 7, intFlagValue)
  284. }
  285. if stringFlagValue != "abc" {
  286. t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue)
  287. }
  288. got := strings.Join(cArgs, " ")
  289. expected := "one two"
  290. if got != expected {
  291. t.Errorf("Expected arguments: %q, got %q", expected, got)
  292. }
  293. }
  294. func TestFlagShort(t *testing.T) {
  295. var cArgs []string
  296. c := &Command{
  297. Use: "c",
  298. Args: ArbitraryArgs,
  299. Run: func(_ *Command, args []string) { cArgs = args },
  300. }
  301. var intFlagValue int
  302. var stringFlagValue string
  303. c.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
  304. c.Flags().StringVarP(&stringFlagValue, "sf", "s", "", "")
  305. output, err := executeCommand(c, "-i", "7", "-sabc", "one", "two")
  306. if output != "" {
  307. t.Errorf("Unexpected output: %v", err)
  308. }
  309. if err != nil {
  310. t.Errorf("Unexpected error: %v", err)
  311. }
  312. if intFlagValue != 7 {
  313. t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
  314. }
  315. if stringFlagValue != "abc" {
  316. t.Errorf("Expected stringFlagValue: %q, got %q", "abc", stringFlagValue)
  317. }
  318. got := strings.Join(cArgs, " ")
  319. expected := "one two"
  320. if got != expected {
  321. t.Errorf("Expected arguments: %q, got %q", expected, got)
  322. }
  323. }
  324. func TestChildFlag(t *testing.T) {
  325. rootCmd := &Command{Use: "root", Run: emptyRun}
  326. childCmd := &Command{Use: "child", Run: emptyRun}
  327. rootCmd.AddCommand(childCmd)
  328. var intFlagValue int
  329. childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
  330. output, err := executeCommand(rootCmd, "child", "-i7")
  331. if output != "" {
  332. t.Errorf("Unexpected output: %v", err)
  333. }
  334. if err != nil {
  335. t.Errorf("Unexpected error: %v", err)
  336. }
  337. if intFlagValue != 7 {
  338. t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
  339. }
  340. }
  341. func TestChildFlagWithParentLocalFlag(t *testing.T) {
  342. rootCmd := &Command{Use: "root", Run: emptyRun}
  343. childCmd := &Command{Use: "child", Run: emptyRun}
  344. rootCmd.AddCommand(childCmd)
  345. var intFlagValue int
  346. rootCmd.Flags().StringP("sf", "s", "", "")
  347. childCmd.Flags().IntVarP(&intFlagValue, "intf", "i", -1, "")
  348. _, err := executeCommand(rootCmd, "child", "-i7", "-sabc")
  349. if err == nil {
  350. t.Errorf("Invalid flag should generate error")
  351. }
  352. checkStringContains(t, err.Error(), "unknown shorthand")
  353. if intFlagValue != 7 {
  354. t.Errorf("Expected flag value: %v, got %v", 7, intFlagValue)
  355. }
  356. }
  357. func TestFlagInvalidInput(t *testing.T) {
  358. rootCmd := &Command{Use: "root", Run: emptyRun}
  359. rootCmd.Flags().IntP("intf", "i", -1, "")
  360. _, err := executeCommand(rootCmd, "-iabc")
  361. if err == nil {
  362. t.Errorf("Invalid flag value should generate error")
  363. }
  364. checkStringContains(t, err.Error(), "invalid syntax")
  365. }
  366. func TestFlagBeforeCommand(t *testing.T) {
  367. rootCmd := &Command{Use: "root", Run: emptyRun}
  368. childCmd := &Command{Use: "child", Run: emptyRun}
  369. rootCmd.AddCommand(childCmd)
  370. var flagValue int
  371. childCmd.Flags().IntVarP(&flagValue, "intf", "i", -1, "")
  372. // With short flag.
  373. _, err := executeCommand(rootCmd, "-i7", "child")
  374. if err != nil {
  375. t.Errorf("Unexpected error: %v", err)
  376. }
  377. if flagValue != 7 {
  378. t.Errorf("Expected flag value: %v, got %v", 7, flagValue)
  379. }
  380. // With long flag.
  381. _, err = executeCommand(rootCmd, "--intf=8", "child")
  382. if err != nil {
  383. t.Errorf("Unexpected error: %v", err)
  384. }
  385. if flagValue != 8 {
  386. t.Errorf("Expected flag value: %v, got %v", 9, flagValue)
  387. }
  388. }
  389. func TestStripFlags(t *testing.T) {
  390. tests := []struct {
  391. input []string
  392. output []string
  393. }{
  394. {
  395. []string{"foo", "bar"},
  396. []string{"foo", "bar"},
  397. },
  398. {
  399. []string{"foo", "--str", "-s"},
  400. []string{"foo"},
  401. },
  402. {
  403. []string{"-s", "foo", "--str", "bar"},
  404. []string{},
  405. },
  406. {
  407. []string{"-i10", "echo"},
  408. []string{"echo"},
  409. },
  410. {
  411. []string{"-i=10", "echo"},
  412. []string{"echo"},
  413. },
  414. {
  415. []string{"--int=100", "echo"},
  416. []string{"echo"},
  417. },
  418. {
  419. []string{"-ib", "echo", "-sfoo", "baz"},
  420. []string{"echo", "baz"},
  421. },
  422. {
  423. []string{"-i=baz", "bar", "-i", "foo", "blah"},
  424. []string{"bar", "blah"},
  425. },
  426. {
  427. []string{"--int=baz", "-sbar", "-i", "foo", "blah"},
  428. []string{"blah"},
  429. },
  430. {
  431. []string{"--bool", "bar", "-i", "foo", "blah"},
  432. []string{"bar", "blah"},
  433. },
  434. {
  435. []string{"-b", "bar", "-i", "foo", "blah"},
  436. []string{"bar", "blah"},
  437. },
  438. {
  439. []string{"--persist", "bar"},
  440. []string{"bar"},
  441. },
  442. {
  443. []string{"-p", "bar"},
  444. []string{"bar"},
  445. },
  446. }
  447. c := &Command{Use: "c", Run: emptyRun}
  448. c.PersistentFlags().BoolP("persist", "p", false, "")
  449. c.Flags().IntP("int", "i", -1, "")
  450. c.Flags().StringP("str", "s", "", "")
  451. c.Flags().BoolP("bool", "b", false, "")
  452. for i, test := range tests {
  453. got := stripFlags(test.input, c)
  454. if !reflect.DeepEqual(test.output, got) {
  455. t.Errorf("(%v) Expected: %v, got: %v", i, test.output, got)
  456. }
  457. }
  458. }
  459. func TestDisableFlagParsing(t *testing.T) {
  460. var cArgs []string
  461. c := &Command{
  462. Use: "c",
  463. DisableFlagParsing: true,
  464. Run: func(_ *Command, args []string) {
  465. cArgs = args
  466. },
  467. }
  468. args := []string{"cmd", "-v", "-race", "-file", "foo.go"}
  469. output, err := executeCommand(c, args...)
  470. if output != "" {
  471. t.Errorf("Unexpected output: %v", output)
  472. }
  473. if err != nil {
  474. t.Errorf("Unexpected error: %v", err)
  475. }
  476. if !reflect.DeepEqual(args, cArgs) {
  477. t.Errorf("Expected: %v, got: %v", args, cArgs)
  478. }
  479. }
  480. func TestPersistentFlagsOnSameCommand(t *testing.T) {
  481. var rootCmdArgs []string
  482. rootCmd := &Command{
  483. Use: "root",
  484. Args: ArbitraryArgs,
  485. Run: func(_ *Command, args []string) { rootCmdArgs = args },
  486. }
  487. var flagValue int
  488. rootCmd.PersistentFlags().IntVarP(&flagValue, "intf", "i", -1, "")
  489. output, err := executeCommand(rootCmd, "-i7", "one", "two")
  490. if output != "" {
  491. t.Errorf("Unexpected output: %v", output)
  492. }
  493. if err != nil {
  494. t.Errorf("Unexpected error: %v", err)
  495. }
  496. got := strings.Join(rootCmdArgs, " ")
  497. expected := "one two"
  498. if got != expected {
  499. t.Errorf("rootCmdArgs expected: %q, got %q", expected, got)
  500. }
  501. if flagValue != 7 {
  502. t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
  503. }
  504. }
  505. // TestEmptyInputs checks,
  506. // if flags correctly parsed with blank strings in args.
  507. func TestEmptyInputs(t *testing.T) {
  508. c := &Command{Use: "c", Run: emptyRun}
  509. var flagValue int
  510. c.Flags().IntVarP(&flagValue, "intf", "i", -1, "")
  511. output, err := executeCommand(c, "", "-i7", "")
  512. if output != "" {
  513. t.Errorf("Unexpected output: %v", output)
  514. }
  515. if err != nil {
  516. t.Errorf("Unexpected error: %v", err)
  517. }
  518. if flagValue != 7 {
  519. t.Errorf("flagValue expected: %v, got %v", 7, flagValue)
  520. }
  521. }
  522. func TestOverwrittenFlag(t *testing.T) {
  523. // TODO: This test fails, but should work.
  524. t.Skip()
  525. parent := &Command{Use: "parent", Run: emptyRun}
  526. child := &Command{Use: "child", Run: emptyRun}
  527. parent.PersistentFlags().Bool("boolf", false, "")
  528. parent.PersistentFlags().Int("intf", -1, "")
  529. child.Flags().String("strf", "", "")
  530. child.Flags().Int("intf", -1, "")
  531. parent.AddCommand(child)
  532. childInherited := child.InheritedFlags()
  533. childLocal := child.LocalFlags()
  534. if childLocal.Lookup("strf") == nil {
  535. t.Error(`LocalFlags expected to contain "strf", got "nil"`)
  536. }
  537. if childInherited.Lookup("boolf") == nil {
  538. t.Error(`InheritedFlags expected to contain "boolf", got "nil"`)
  539. }
  540. if childInherited.Lookup("intf") != nil {
  541. t.Errorf(`InheritedFlags should not contain overwritten flag "intf"`)
  542. }
  543. if childLocal.Lookup("intf") == nil {
  544. t.Error(`LocalFlags expected to contain "intf", got "nil"`)
  545. }
  546. }
  547. func TestPersistentFlagsOnChild(t *testing.T) {
  548. var childCmdArgs []string
  549. rootCmd := &Command{Use: "root", Run: emptyRun}
  550. childCmd := &Command{
  551. Use: "child",
  552. Args: ArbitraryArgs,
  553. Run: func(_ *Command, args []string) { childCmdArgs = args },
  554. }
  555. rootCmd.AddCommand(childCmd)
  556. var parentFlagValue int
  557. var childFlagValue int
  558. rootCmd.PersistentFlags().IntVarP(&parentFlagValue, "parentf", "p", -1, "")
  559. childCmd.Flags().IntVarP(&childFlagValue, "childf", "c", -1, "")
  560. output, err := executeCommand(rootCmd, "child", "-c7", "-p8", "one", "two")
  561. if output != "" {
  562. t.Errorf("Unexpected output: %v", output)
  563. }
  564. if err != nil {
  565. t.Errorf("Unexpected error: %v", err)
  566. }
  567. got := strings.Join(childCmdArgs, " ")
  568. expected := "one two"
  569. if got != expected {
  570. t.Errorf("childCmdArgs expected: %q, got %q", expected, got)
  571. }
  572. if parentFlagValue != 8 {
  573. t.Errorf("parentFlagValue expected: %v, got %v", 8, parentFlagValue)
  574. }
  575. if childFlagValue != 7 {
  576. t.Errorf("childFlagValue expected: %v, got %v", 7, childFlagValue)
  577. }
  578. }
  579. func TestRequiredFlags(t *testing.T) {
  580. c := &Command{Use: "c", Run: emptyRun}
  581. c.Flags().String("foo1", "", "")
  582. c.MarkFlagRequired("foo1")
  583. c.Flags().String("foo2", "", "")
  584. c.MarkFlagRequired("foo2")
  585. c.Flags().String("bar", "", "")
  586. expected := fmt.Sprintf("required flag(s) %q, %q not set", "foo1", "foo2")
  587. _, err := executeCommand(c)
  588. got := err.Error()
  589. if got != expected {
  590. t.Errorf("Expected error: %q, got: %q", expected, got)
  591. }
  592. }
  593. func TestPersistentRequiredFlags(t *testing.T) {
  594. parent := &Command{Use: "parent", Run: emptyRun}
  595. parent.PersistentFlags().String("foo1", "", "")
  596. parent.MarkPersistentFlagRequired("foo1")
  597. parent.PersistentFlags().String("foo2", "", "")
  598. parent.MarkPersistentFlagRequired("foo2")
  599. parent.Flags().String("foo3", "", "")
  600. child := &Command{Use: "child", Run: emptyRun}
  601. child.Flags().String("bar1", "", "")
  602. child.MarkFlagRequired("bar1")
  603. child.Flags().String("bar2", "", "")
  604. child.MarkFlagRequired("bar2")
  605. child.Flags().String("bar3", "", "")
  606. parent.AddCommand(child)
  607. expected := fmt.Sprintf("required flag(s) %q, %q, %q, %q not set", "bar1", "bar2", "foo1", "foo2")
  608. _, err := executeCommand(parent, "child")
  609. if err.Error() != expected {
  610. t.Errorf("Expected %q, got %q", expected, err.Error())
  611. }
  612. }
  613. func TestInitHelpFlagMergesFlags(t *testing.T) {
  614. usage := "custom flag"
  615. rootCmd := &Command{Use: "root"}
  616. rootCmd.PersistentFlags().Bool("help", false, "custom flag")
  617. childCmd := &Command{Use: "child"}
  618. rootCmd.AddCommand(childCmd)
  619. childCmd.InitDefaultHelpFlag()
  620. got := childCmd.Flags().Lookup("help").Usage
  621. if got != usage {
  622. t.Errorf("Expected the help flag from the root command with usage: %v\nGot the default with usage: %v", usage, got)
  623. }
  624. }
  625. func TestHelpCommandExecuted(t *testing.T) {
  626. rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
  627. rootCmd.AddCommand(&Command{Use: "child", Run: emptyRun})
  628. output, err := executeCommand(rootCmd, "help")
  629. if err != nil {
  630. t.Errorf("Unexpected error: %v", err)
  631. }
  632. checkStringContains(t, output, rootCmd.Long)
  633. }
  634. func TestHelpCommandExecutedOnChild(t *testing.T) {
  635. rootCmd := &Command{Use: "root", Run: emptyRun}
  636. childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun}
  637. rootCmd.AddCommand(childCmd)
  638. output, err := executeCommand(rootCmd, "help", "child")
  639. if err != nil {
  640. t.Errorf("Unexpected error: %v", err)
  641. }
  642. checkStringContains(t, output, childCmd.Long)
  643. }
  644. func TestSetHelpCommand(t *testing.T) {
  645. c := &Command{Use: "c", Run: emptyRun}
  646. c.AddCommand(&Command{Use: "empty", Run: emptyRun})
  647. expected := "WORKS"
  648. c.SetHelpCommand(&Command{
  649. Use: "help [command]",
  650. Short: "Help about any command",
  651. Long: `Help provides help for any command in the application.
  652. Simply type ` + c.Name() + ` help [path to command] for full details.`,
  653. Run: func(c *Command, _ []string) { c.Print(expected) },
  654. })
  655. got, err := executeCommand(c, "help")
  656. if err != nil {
  657. t.Errorf("Unexpected error: %v", err)
  658. }
  659. if got != expected {
  660. t.Errorf("Expected to contain %q, got %q", expected, got)
  661. }
  662. }
  663. func TestHelpFlagExecuted(t *testing.T) {
  664. rootCmd := &Command{Use: "root", Long: "Long description", Run: emptyRun}
  665. output, err := executeCommand(rootCmd, "--help")
  666. if err != nil {
  667. t.Errorf("Unexpected error: %v", err)
  668. }
  669. checkStringContains(t, output, rootCmd.Long)
  670. }
  671. func TestHelpFlagExecutedOnChild(t *testing.T) {
  672. rootCmd := &Command{Use: "root", Run: emptyRun}
  673. childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun}
  674. rootCmd.AddCommand(childCmd)
  675. output, err := executeCommand(rootCmd, "child", "--help")
  676. if err != nil {
  677. t.Errorf("Unexpected error: %v", err)
  678. }
  679. checkStringContains(t, output, childCmd.Long)
  680. }
  681. // TestHelpFlagInHelp checks,
  682. // if '--help' flag is shown in help for child (executing `parent help child`),
  683. // that has no other flags.
  684. // Related to https://github.com/spf13/cobra/issues/302.
  685. func TestHelpFlagInHelp(t *testing.T) {
  686. parentCmd := &Command{Use: "parent", Run: func(*Command, []string) {}}
  687. childCmd := &Command{Use: "child", Run: func(*Command, []string) {}}
  688. parentCmd.AddCommand(childCmd)
  689. output, err := executeCommand(parentCmd, "help", "child")
  690. if err != nil {
  691. t.Errorf("Unexpected error: %v", err)
  692. }
  693. checkStringContains(t, output, "[flags]")
  694. }
  695. func TestFlagsInUsage(t *testing.T) {
  696. rootCmd := &Command{Use: "root", Args: NoArgs, Run: func(*Command, []string) {}}
  697. output, err := executeCommand(rootCmd, "--help")
  698. if err != nil {
  699. t.Errorf("Unexpected error: %v", err)
  700. }
  701. checkStringContains(t, output, "[flags]")
  702. }
  703. func TestHelpExecutedOnNonRunnableChild(t *testing.T) {
  704. rootCmd := &Command{Use: "root", Run: emptyRun}
  705. childCmd := &Command{Use: "child", Long: "Long description"}
  706. rootCmd.AddCommand(childCmd)
  707. output, err := executeCommand(rootCmd, "child")
  708. if err != nil {
  709. t.Errorf("Unexpected error: %v", err)
  710. }
  711. checkStringContains(t, output, childCmd.Long)
  712. }
  713. func TestVersionFlagExecuted(t *testing.T) {
  714. rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  715. output, err := executeCommand(rootCmd, "--version", "arg1")
  716. if err != nil {
  717. t.Errorf("Unexpected error: %v", err)
  718. }
  719. checkStringContains(t, output, "root version 1.0.0")
  720. }
  721. func TestVersionTemplate(t *testing.T) {
  722. rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  723. rootCmd.SetVersionTemplate(`customized version: {{.Version}}`)
  724. output, err := executeCommand(rootCmd, "--version", "arg1")
  725. if err != nil {
  726. t.Errorf("Unexpected error: %v", err)
  727. }
  728. checkStringContains(t, output, "customized version: 1.0.0")
  729. }
  730. func TestVersionFlagExecutedOnSubcommand(t *testing.T) {
  731. rootCmd := &Command{Use: "root", Version: "1.0.0"}
  732. rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
  733. output, err := executeCommand(rootCmd, "--version", "sub")
  734. if err != nil {
  735. t.Errorf("Unexpected error: %v", err)
  736. }
  737. checkStringContains(t, output, "root version 1.0.0")
  738. }
  739. func TestVersionFlagOnlyAddedToRoot(t *testing.T) {
  740. rootCmd := &Command{Use: "root", Version: "1.0.0", Run: emptyRun}
  741. rootCmd.AddCommand(&Command{Use: "sub", Run: emptyRun})
  742. _, err := executeCommand(rootCmd, "sub", "--version")
  743. if err == nil {
  744. t.Errorf("Expected error")
  745. }
  746. checkStringContains(t, err.Error(), "unknown flag: --version")
  747. }
  748. func TestVersionFlagOnlyExistsIfVersionNonEmpty(t *testing.T) {
  749. rootCmd := &Command{Use: "root", Run: emptyRun}
  750. _, err := executeCommand(rootCmd, "--version")
  751. if err == nil {
  752. t.Errorf("Expected error")
  753. }
  754. checkStringContains(t, err.Error(), "unknown flag: --version")
  755. }
  756. func TestUsageIsNotPrintedTwice(t *testing.T) {
  757. var cmd = &Command{Use: "root"}
  758. var sub = &Command{Use: "sub"}
  759. cmd.AddCommand(sub)
  760. output, _ := executeCommand(cmd, "")
  761. if strings.Count(output, "Usage:") != 1 {
  762. t.Error("Usage output is not printed exactly once")
  763. }
  764. }
  765. func TestVisitParents(t *testing.T) {
  766. c := &Command{Use: "app"}
  767. sub := &Command{Use: "sub"}
  768. dsub := &Command{Use: "dsub"}
  769. sub.AddCommand(dsub)
  770. c.AddCommand(sub)
  771. total := 0
  772. add := func(x *Command) {
  773. total++
  774. }
  775. sub.VisitParents(add)
  776. if total != 1 {
  777. t.Errorf("Should have visited 1 parent but visited %d", total)
  778. }
  779. total = 0
  780. dsub.VisitParents(add)
  781. if total != 2 {
  782. t.Errorf("Should have visited 2 parents but visited %d", total)
  783. }
  784. total = 0
  785. c.VisitParents(add)
  786. if total != 0 {
  787. t.Errorf("Should have visited no parents but visited %d", total)
  788. }
  789. }
  790. func TestSuggestions(t *testing.T) {
  791. rootCmd := &Command{Use: "root", Run: emptyRun}
  792. timesCmd := &Command{
  793. Use: "times",
  794. SuggestFor: []string{"counts"},
  795. Run: emptyRun,
  796. }
  797. rootCmd.AddCommand(timesCmd)
  798. templateWithSuggestions := "Error: unknown command \"%s\" for \"root\"\n\nDid you mean this?\n\t%s\n\nRun 'root --help' for usage.\n"
  799. templateWithoutSuggestions := "Error: unknown command \"%s\" for \"root\"\nRun 'root --help' for usage.\n"
  800. tests := map[string]string{
  801. "time": "times",
  802. "tiems": "times",
  803. "tims": "times",
  804. "timeS": "times",
  805. "rimes": "times",
  806. "ti": "times",
  807. "t": "times",
  808. "timely": "times",
  809. "ri": "",
  810. "timezone": "",
  811. "foo": "",
  812. "counts": "times",
  813. }
  814. for typo, suggestion := range tests {
  815. for _, suggestionsDisabled := range []bool{true, false} {
  816. rootCmd.DisableSuggestions = suggestionsDisabled
  817. var expected string
  818. output, _ := executeCommand(rootCmd, typo)
  819. if suggestion == "" || suggestionsDisabled {
  820. expected = fmt.Sprintf(templateWithoutSuggestions, typo)
  821. } else {
  822. expected = fmt.Sprintf(templateWithSuggestions, typo, suggestion)
  823. }
  824. if output != expected {
  825. t.Errorf("Unexpected response.\nExpected:\n %q\nGot:\n %q\n", expected, output)
  826. }
  827. }
  828. }
  829. }
  830. func TestRemoveCommand(t *testing.T) {
  831. rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
  832. childCmd := &Command{Use: "child", Run: emptyRun}
  833. rootCmd.AddCommand(childCmd)
  834. rootCmd.RemoveCommand(childCmd)
  835. _, err := executeCommand(rootCmd, "child")
  836. if err == nil {
  837. t.Error("Expected error on calling removed command. Got nil.")
  838. }
  839. }
  840. func TestReplaceCommandWithRemove(t *testing.T) {
  841. childUsed := 0
  842. rootCmd := &Command{Use: "root", Run: emptyRun}
  843. child1Cmd := &Command{
  844. Use: "child",
  845. Run: func(*Command, []string) { childUsed = 1 },
  846. }
  847. child2Cmd := &Command{
  848. Use: "child",
  849. Run: func(*Command, []string) { childUsed = 2 },
  850. }
  851. rootCmd.AddCommand(child1Cmd)
  852. rootCmd.RemoveCommand(child1Cmd)
  853. rootCmd.AddCommand(child2Cmd)
  854. output, err := executeCommand(rootCmd, "child")
  855. if output != "" {
  856. t.Errorf("Unexpected output: %v", output)
  857. }
  858. if err != nil {
  859. t.Errorf("Unexpected error: %v", err)
  860. }
  861. if childUsed == 1 {
  862. t.Error("Removed command shouldn't be called")
  863. }
  864. if childUsed != 2 {
  865. t.Error("Replacing command should have been called but didn't")
  866. }
  867. }
  868. func TestDeprecatedCommand(t *testing.T) {
  869. rootCmd := &Command{Use: "root", Run: emptyRun}
  870. deprecatedCmd := &Command{
  871. Use: "deprecated",
  872. Deprecated: "This command is deprecated",
  873. Run: emptyRun,
  874. }
  875. rootCmd.AddCommand(deprecatedCmd)
  876. output, err := executeCommand(rootCmd, "deprecated")
  877. if err != nil {
  878. t.Errorf("Unexpected error: %v", err)
  879. }
  880. checkStringContains(t, output, deprecatedCmd.Deprecated)
  881. }
  882. func TestHooks(t *testing.T) {
  883. var (
  884. persPreArgs string
  885. preArgs string
  886. runArgs string
  887. postArgs string
  888. persPostArgs string
  889. )
  890. c := &Command{
  891. Use: "c",
  892. PersistentPreRun: func(_ *Command, args []string) {
  893. persPreArgs = strings.Join(args, " ")
  894. },
  895. PreRun: func(_ *Command, args []string) {
  896. preArgs = strings.Join(args, " ")
  897. },
  898. Run: func(_ *Command, args []string) {
  899. runArgs = strings.Join(args, " ")
  900. },
  901. PostRun: func(_ *Command, args []string) {
  902. postArgs = strings.Join(args, " ")
  903. },
  904. PersistentPostRun: func(_ *Command, args []string) {
  905. persPostArgs = strings.Join(args, " ")
  906. },
  907. }
  908. output, err := executeCommand(c, "one", "two")
  909. if output != "" {
  910. t.Errorf("Unexpected output: %v", output)
  911. }
  912. if err != nil {
  913. t.Errorf("Unexpected error: %v", err)
  914. }
  915. if persPreArgs != "one two" {
  916. t.Errorf("Expected persPreArgs %q, got %q", "one two", persPreArgs)
  917. }
  918. if preArgs != "one two" {
  919. t.Errorf("Expected preArgs %q, got %q", "one two", preArgs)
  920. }
  921. if runArgs != "one two" {
  922. t.Errorf("Expected runArgs %q, got %q", "one two", runArgs)
  923. }
  924. if postArgs != "one two" {
  925. t.Errorf("Expected postArgs %q, got %q", "one two", postArgs)
  926. }
  927. if persPostArgs != "one two" {
  928. t.Errorf("Expected persPostArgs %q, got %q", "one two", persPostArgs)
  929. }
  930. }
  931. func TestPersistentHooks(t *testing.T) {
  932. var (
  933. parentPersPreArgs string
  934. parentPreArgs string
  935. parentRunArgs string
  936. parentPostArgs string
  937. parentPersPostArgs string
  938. )
  939. var (
  940. childPersPreArgs string
  941. childPreArgs string
  942. childRunArgs string
  943. childPostArgs string
  944. childPersPostArgs string
  945. )
  946. parentCmd := &Command{
  947. Use: "parent",
  948. PersistentPreRun: func(_ *Command, args []string) {
  949. parentPersPreArgs = strings.Join(args, " ")
  950. },
  951. PreRun: func(_ *Command, args []string) {
  952. parentPreArgs = strings.Join(args, " ")
  953. },
  954. Run: func(_ *Command, args []string) {
  955. parentRunArgs = strings.Join(args, " ")
  956. },
  957. PostRun: func(_ *Command, args []string) {
  958. parentPostArgs = strings.Join(args, " ")
  959. },
  960. PersistentPostRun: func(_ *Command, args []string) {
  961. parentPersPostArgs = strings.Join(args, " ")
  962. },
  963. }
  964. childCmd := &Command{
  965. Use: "child",
  966. PersistentPreRun: func(_ *Command, args []string) {
  967. childPersPreArgs = strings.Join(args, " ")
  968. },
  969. PreRun: func(_ *Command, args []string) {
  970. childPreArgs = strings.Join(args, " ")
  971. },
  972. Run: func(_ *Command, args []string) {
  973. childRunArgs = strings.Join(args, " ")
  974. },
  975. PostRun: func(_ *Command, args []string) {
  976. childPostArgs = strings.Join(args, " ")
  977. },
  978. PersistentPostRun: func(_ *Command, args []string) {
  979. childPersPostArgs = strings.Join(args, " ")
  980. },
  981. }
  982. parentCmd.AddCommand(childCmd)
  983. output, err := executeCommand(parentCmd, "child", "one", "two")
  984. if output != "" {
  985. t.Errorf("Unexpected output: %v", output)
  986. }
  987. if err != nil {
  988. t.Errorf("Unexpected error: %v", err)
  989. }
  990. // TODO: This test fails, but should not.
  991. // Related to https://github.com/spf13/cobra/issues/252.
  992. //
  993. // if parentPersPreArgs != "one two" {
  994. // t.Errorf("Expected parentPersPreArgs %q, got %q", "one two", parentPersPreArgs)
  995. // }
  996. if parentPreArgs != "" {
  997. t.Errorf("Expected blank parentPreArgs, got %q", parentPreArgs)
  998. }
  999. if parentRunArgs != "" {
  1000. t.Errorf("Expected blank parentRunArgs, got %q", parentRunArgs)
  1001. }
  1002. if parentPostArgs != "" {
  1003. t.Errorf("Expected blank parentPostArgs, got %q", parentPostArgs)
  1004. }
  1005. // TODO: This test fails, but should not.
  1006. // Related to https://github.com/spf13/cobra/issues/252.
  1007. //
  1008. // if parentPersPostArgs != "one two" {
  1009. // t.Errorf("Expected parentPersPostArgs %q, got %q", "one two", parentPersPostArgs)
  1010. // }
  1011. if childPersPreArgs != "one two" {
  1012. t.Errorf("Expected childPersPreArgs %q, got %q", "one two", childPersPreArgs)
  1013. }
  1014. if childPreArgs != "one two" {
  1015. t.Errorf("Expected childPreArgs %q, got %q", "one two", childPreArgs)
  1016. }
  1017. if childRunArgs != "one two" {
  1018. t.Errorf("Expected childRunArgs %q, got %q", "one two", childRunArgs)
  1019. }
  1020. if childPostArgs != "one two" {
  1021. t.Errorf("Expected childPostArgs %q, got %q", "one two", childPostArgs)
  1022. }
  1023. if childPersPostArgs != "one two" {
  1024. t.Errorf("Expected childPersPostArgs %q, got %q", "one two", childPersPostArgs)
  1025. }
  1026. }
  1027. // Related to https://github.com/spf13/cobra/issues/521.
  1028. func TestGlobalNormFuncPropagation(t *testing.T) {
  1029. normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1030. return pflag.NormalizedName(name)
  1031. }
  1032. rootCmd := &Command{Use: "root", Run: emptyRun}
  1033. childCmd := &Command{Use: "child", Run: emptyRun}
  1034. rootCmd.AddCommand(childCmd)
  1035. rootCmd.SetGlobalNormalizationFunc(normFunc)
  1036. if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(rootCmd.GlobalNormalizationFunc()).Pointer() {
  1037. t.Error("rootCmd seems to have a wrong normalization function")
  1038. }
  1039. if reflect.ValueOf(normFunc).Pointer() != reflect.ValueOf(childCmd.GlobalNormalizationFunc()).Pointer() {
  1040. t.Error("childCmd should have had the normalization function of rootCmd")
  1041. }
  1042. }
  1043. // Related to https://github.com/spf13/cobra/issues/521.
  1044. func TestNormPassedOnLocal(t *testing.T) {
  1045. toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1046. return pflag.NormalizedName(strings.ToUpper(name))
  1047. }
  1048. c := &Command{}
  1049. c.Flags().Bool("flagname", true, "this is a dummy flag")
  1050. c.SetGlobalNormalizationFunc(toUpper)
  1051. if c.LocalFlags().Lookup("flagname") != c.LocalFlags().Lookup("FLAGNAME") {
  1052. t.Error("Normalization function should be passed on to Local flag set")
  1053. }
  1054. }
  1055. // Related to https://github.com/spf13/cobra/issues/521.
  1056. func TestNormPassedOnInherited(t *testing.T) {
  1057. toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1058. return pflag.NormalizedName(strings.ToUpper(name))
  1059. }
  1060. c := &Command{}
  1061. c.SetGlobalNormalizationFunc(toUpper)
  1062. child1 := &Command{}
  1063. c.AddCommand(child1)
  1064. c.PersistentFlags().Bool("flagname", true, "")
  1065. child2 := &Command{}
  1066. c.AddCommand(child2)
  1067. inherited := child1.InheritedFlags()
  1068. if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") {
  1069. t.Error("Normalization function should be passed on to inherited flag set in command added before flag")
  1070. }
  1071. inherited = child2.InheritedFlags()
  1072. if inherited.Lookup("flagname") == nil || inherited.Lookup("flagname") != inherited.Lookup("FLAGNAME") {
  1073. t.Error("Normalization function should be passed on to inherited flag set in command added after flag")
  1074. }
  1075. }
  1076. // Related to https://github.com/spf13/cobra/issues/521.
  1077. func TestConsistentNormalizedName(t *testing.T) {
  1078. toUpper := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1079. return pflag.NormalizedName(strings.ToUpper(name))
  1080. }
  1081. n := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
  1082. return pflag.NormalizedName(name)
  1083. }
  1084. c := &Command{}
  1085. c.Flags().Bool("flagname", true, "")
  1086. c.SetGlobalNormalizationFunc(toUpper)
  1087. c.SetGlobalNormalizationFunc(n)
  1088. if c.LocalFlags().Lookup("flagname") == c.LocalFlags().Lookup("FLAGNAME") {
  1089. t.Error("Normalizing flag names should not result in duplicate flags")
  1090. }
  1091. }
  1092. func TestFlagOnPflagCommandLine(t *testing.T) {
  1093. flagName := "flagOnCommandLine"
  1094. pflag.String(flagName, "", "about my flag")
  1095. c := &Command{Use: "c", Run: emptyRun}
  1096. c.AddCommand(&Command{Use: "child", Run: emptyRun})
  1097. output, _ := executeCommand(c, "--help")
  1098. checkStringContains(t, output, flagName)
  1099. resetCommandLineFlagSet()
  1100. }
  1101. // TestHiddenCommandExecutes checks,
  1102. // if hidden commands run as intended.
  1103. func TestHiddenCommandExecutes(t *testing.T) {
  1104. executed := false
  1105. c := &Command{
  1106. Use: "c",
  1107. Hidden: true,
  1108. Run: func(*Command, []string) { executed = true },
  1109. }
  1110. output, err := executeCommand(c)
  1111. if output != "" {
  1112. t.Errorf("Unexpected output: %v", output)
  1113. }
  1114. if err != nil {
  1115. t.Errorf("Unexpected error: %v", err)
  1116. }
  1117. if !executed {
  1118. t.Error("Hidden command should have been executed")
  1119. }
  1120. }
  1121. // test to ensure hidden commands do not show up in usage/help text
  1122. func TestHiddenCommandIsHidden(t *testing.T) {
  1123. c := &Command{Use: "c", Hidden: true, Run: emptyRun}
  1124. if c.IsAvailableCommand() {
  1125. t.Errorf("Hidden command should be unavailable")
  1126. }
  1127. }
  1128. func TestCommandsAreSorted(t *testing.T) {
  1129. EnableCommandSorting = true
  1130. originalNames := []string{"middle", "zlast", "afirst"}
  1131. expectedNames := []string{"afirst", "middle", "zlast"}
  1132. var rootCmd = &Command{Use: "root"}
  1133. for _, name := range originalNames {
  1134. rootCmd.AddCommand(&Command{Use: name})
  1135. }
  1136. for i, c := range rootCmd.Commands() {
  1137. got := c.Name()
  1138. if expectedNames[i] != got {
  1139. t.Errorf("Expected: %s, got: %s", expectedNames[i], got)
  1140. }
  1141. }
  1142. EnableCommandSorting = true
  1143. }
  1144. func TestEnableCommandSortingIsDisabled(t *testing.T) {
  1145. EnableCommandSorting = false
  1146. originalNames := []string{"middle", "zlast", "afirst"}
  1147. var rootCmd = &Command{Use: "root"}
  1148. for _, name := range originalNames {
  1149. rootCmd.AddCommand(&Command{Use: name})
  1150. }
  1151. for i, c := range rootCmd.Commands() {
  1152. got := c.Name()
  1153. if originalNames[i] != got {
  1154. t.Errorf("expected: %s, got: %s", originalNames[i], got)
  1155. }
  1156. }
  1157. EnableCommandSorting = true
  1158. }
  1159. func TestSetOutput(t *testing.T) {
  1160. c := &Command{}
  1161. c.SetOutput(nil)
  1162. if out := c.OutOrStdout(); out != os.Stdout {
  1163. t.Errorf("Expected setting output to nil to revert back to stdout")
  1164. }
  1165. }
  1166. func TestFlagErrorFunc(t *testing.T) {
  1167. c := &Command{Use: "c", Run: emptyRun}
  1168. expectedFmt := "This is expected: %v"
  1169. c.SetFlagErrorFunc(func(_ *Command, err error) error {
  1170. return fmt.Errorf(expectedFmt, err)
  1171. })
  1172. _, err := executeCommand(c, "--unknown-flag")
  1173. got := err.Error()
  1174. expected := fmt.Sprintf(expectedFmt, "unknown flag: --unknown-flag")
  1175. if got != expected {
  1176. t.Errorf("Expected %v, got %v", expected, got)
  1177. }
  1178. }
  1179. // TestSortedFlags checks,
  1180. // if cmd.LocalFlags() is unsorted when cmd.Flags().SortFlags set to false.
  1181. // Related to https://github.com/spf13/cobra/issues/404.
  1182. func TestSortedFlags(t *testing.T) {
  1183. c := &Command{}
  1184. c.Flags().SortFlags = false
  1185. names := []string{"C", "B", "A", "D"}
  1186. for _, name := range names {
  1187. c.Flags().Bool(name, false, "")
  1188. }
  1189. i := 0
  1190. c.LocalFlags().VisitAll(func(f *pflag.Flag) {
  1191. if i == len(names) {
  1192. return
  1193. }
  1194. if stringInSlice(f.Name, names) {
  1195. if names[i] != f.Name {
  1196. t.Errorf("Incorrect order. Expected %v, got %v", names[i], f.Name)
  1197. }
  1198. i++
  1199. }
  1200. })
  1201. }
  1202. // TestMergeCommandLineToFlags checks,
  1203. // if pflag.CommandLine is correctly merged to c.Flags() after first call
  1204. // of c.mergePersistentFlags.
  1205. // Related to https://github.com/spf13/cobra/issues/443.
  1206. func TestMergeCommandLineToFlags(t *testing.T) {
  1207. pflag.Bool("boolflag", false, "")
  1208. c := &Command{Use: "c", Run: emptyRun}
  1209. c.mergePersistentFlags()
  1210. if c.Flags().Lookup("boolflag") == nil {
  1211. t.Fatal("Expecting to have flag from CommandLine in c.Flags()")
  1212. }
  1213. resetCommandLineFlagSet()
  1214. }
  1215. // TestUseDeprecatedFlags checks,
  1216. // if cobra.Execute() prints a message, if a deprecated flag is used.
  1217. // Related to https://github.com/spf13/cobra/issues/463.
  1218. func TestUseDeprecatedFlags(t *testing.T) {
  1219. c := &Command{Use: "c", Run: emptyRun}
  1220. c.Flags().BoolP("deprecated", "d", false, "deprecated flag")
  1221. c.Flags().MarkDeprecated("deprecated", "This flag is deprecated")
  1222. output, err := executeCommand(c, "c", "-d")
  1223. if err != nil {
  1224. t.Error("Unexpected error:", err)
  1225. }
  1226. checkStringContains(t, output, "This flag is deprecated")
  1227. }
  1228. func TestTraverseWithParentFlags(t *testing.T) {
  1229. rootCmd := &Command{Use: "root", TraverseChildren: true}
  1230. rootCmd.Flags().String("str", "", "")
  1231. rootCmd.Flags().BoolP("bool", "b", false, "")
  1232. childCmd := &Command{Use: "child"}
  1233. childCmd.Flags().Int("int", -1, "")
  1234. rootCmd.AddCommand(childCmd)
  1235. c, args, err := rootCmd.Traverse([]string{"-b", "--str", "ok", "child", "--int"})
  1236. if err != nil {
  1237. t.Errorf("Unexpected error: %v", err)
  1238. }
  1239. if len(args) != 1 && args[0] != "--add" {
  1240. t.Errorf("Wrong args: %v", args)
  1241. }
  1242. if c.Name() != childCmd.Name() {
  1243. t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name())
  1244. }
  1245. }
  1246. func TestTraverseNoParentFlags(t *testing.T) {
  1247. rootCmd := &Command{Use: "root", TraverseChildren: true}
  1248. rootCmd.Flags().String("foo", "", "foo things")
  1249. childCmd := &Command{Use: "child"}
  1250. childCmd.Flags().String("str", "", "")
  1251. rootCmd.AddCommand(childCmd)
  1252. c, args, err := rootCmd.Traverse([]string{"child"})
  1253. if err != nil {
  1254. t.Errorf("Unexpected error: %v", err)
  1255. }
  1256. if len(args) != 0 {
  1257. t.Errorf("Wrong args %v", args)
  1258. }
  1259. if c.Name() != childCmd.Name() {
  1260. t.Errorf("Expected command: %q, got: %q", childCmd.Name(), c.Name())
  1261. }
  1262. }
  1263. func TestTraverseWithBadParentFlags(t *testing.T) {
  1264. rootCmd := &Command{Use: "root", TraverseChildren: true}
  1265. childCmd := &Command{Use: "child"}
  1266. childCmd.Flags().String("str", "", "")
  1267. rootCmd.AddCommand(childCmd)
  1268. expected := "unknown flag: --str"
  1269. c, _, err := rootCmd.Traverse([]string{"--str", "ok", "child"})
  1270. if err == nil || !strings.Contains(err.Error(), expected) {
  1271. t.Errorf("Expected error, %q, got %q", expected, err)
  1272. }
  1273. if c != nil {
  1274. t.Errorf("Expected nil command")
  1275. }
  1276. }
  1277. func TestTraverseWithBadChildFlag(t *testing.T) {
  1278. rootCmd := &Command{Use: "root", TraverseChildren: true}
  1279. rootCmd.Flags().String("str", "", "")
  1280. childCmd := &Command{Use: "child"}
  1281. rootCmd.AddCommand(childCmd)
  1282. // Expect no error because the last commands args shouldn't be parsed in
  1283. // Traverse.
  1284. c, args, err := rootCmd.Traverse([]string{"child", "--str"})
  1285. if err != nil {
  1286. t.Errorf("Unexpected error: %v", err)
  1287. }
  1288. if len(args) != 1 && args[0] != "--str" {
  1289. t.Errorf("Wrong args: %v", args)
  1290. }
  1291. if c.Name() != childCmd.Name() {
  1292. t.Errorf("Expected command %q, got: %q", childCmd.Name(), c.Name())
  1293. }
  1294. }
  1295. func TestTraverseWithTwoSubcommands(t *testing.T) {
  1296. rootCmd := &Command{Use: "root", TraverseChildren: true}
  1297. subCmd := &Command{Use: "sub", TraverseChildren: true}
  1298. rootCmd.AddCommand(subCmd)
  1299. subsubCmd := &Command{
  1300. Use: "subsub",
  1301. }
  1302. subCmd.AddCommand(subsubCmd)
  1303. c, _, err := rootCmd.Traverse([]string{"sub", "subsub"})
  1304. if err != nil {
  1305. t.Fatalf("Unexpected error: %v", err)
  1306. }
  1307. if c.Name() != subsubCmd.Name() {
  1308. t.Fatalf("Expected command: %q, got %q", subsubCmd.Name(), c.Name())
  1309. }
  1310. }
  1311. // TestUpdateName checks if c.Name() updates on changed c.Use.
  1312. // Related to https://github.com/spf13/cobra/pull/422#discussion_r143918343.
  1313. func TestUpdateName(t *testing.T) {
  1314. c := &Command{Use: "name xyz"}
  1315. originalName := c.Name()
  1316. c.Use = "changedName abc"
  1317. if originalName == c.Name() || c.Name() != "changedName" {
  1318. t.Error("c.Name() should be updated on changed c.Use")
  1319. }
  1320. }
  1321. type calledAsTestcase struct {
  1322. args []string
  1323. call string
  1324. want string
  1325. epm bool
  1326. tc bool
  1327. }
  1328. func (tc *calledAsTestcase) test(t *testing.T) {
  1329. defer func(ov bool) { EnablePrefixMatching = ov }(EnablePrefixMatching)
  1330. EnablePrefixMatching = tc.epm
  1331. var called *Command
  1332. run := func(c *Command, _ []string) { t.Logf("called: %q", c.Name()); called = c }
  1333. parent := &Command{Use: "parent", Run: run}
  1334. child1 := &Command{Use: "child1", Run: run, Aliases: []string{"this"}}
  1335. child2 := &Command{Use: "child2", Run: run, Aliases: []string{"that"}}
  1336. parent.AddCommand(child1)
  1337. parent.AddCommand(child2)
  1338. parent.SetArgs(tc.args)
  1339. output := new(bytes.Buffer)
  1340. parent.SetOutput(output)
  1341. parent.Execute()
  1342. if called == nil {
  1343. if tc.call != "" {
  1344. t.Errorf("missing expected call to command: %s", tc.call)
  1345. }
  1346. return
  1347. }
  1348. if called.Name() != tc.call {
  1349. t.Errorf("called command == %q; Wanted %q", called.Name(), tc.call)
  1350. } else if got := called.CalledAs(); got != tc.want {
  1351. t.Errorf("%s.CalledAs() == %q; Wanted: %q", tc.call, got, tc.want)
  1352. }
  1353. }
  1354. func TestCalledAs(t *testing.T) {
  1355. tests := map[string]calledAsTestcase{
  1356. "find/no-args": {nil, "parent", "parent", false, false},
  1357. "find/real-name": {[]string{"child1"}, "child1", "child1", false, false},
  1358. "find/full-alias": {[]string{"that"}, "child2", "that", false, false},
  1359. "find/part-no-prefix": {[]string{"thi"}, "", "", false, false},
  1360. "find/part-alias": {[]string{"thi"}, "child1", "this", true, false},
  1361. "find/conflict": {[]string{"th"}, "", "", true, false},
  1362. "traverse/no-args": {nil, "parent", "parent", false, true},
  1363. "traverse/real-name": {[]string{"child1"}, "child1", "child1", false, true},
  1364. "traverse/full-alias": {[]string{"that"}, "child2", "that", false, true},
  1365. "traverse/part-no-prefix": {[]string{"thi"}, "", "", false, true},
  1366. "traverse/part-alias": {[]string{"thi"}, "child1", "this", true, true},
  1367. "traverse/conflict": {[]string{"th"}, "", "", true, true},
  1368. }
  1369. for name, tc := range tests {
  1370. t.Run(name, tc.test)
  1371. }
  1372. }
  1373. func TestFParseErrWhitelistBackwardCompatibility(t *testing.T) {
  1374. c := &Command{Use: "c", Run: emptyRun}
  1375. c.Flags().BoolP("boola", "a", false, "a boolean flag")
  1376. output, err := executeCommand(c, "c", "-a", "--unknown", "flag")
  1377. if err == nil {
  1378. t.Error("expected unknown flag error")
  1379. }
  1380. checkStringContains(t, output, "unknown flag: --unknown")
  1381. }
  1382. func TestFParseErrWhitelistSameCommand(t *testing.T) {
  1383. c := &Command{
  1384. Use: "c",
  1385. Run: emptyRun,
  1386. FParseErrWhitelist: FParseErrWhitelist{
  1387. UnknownFlags: true,
  1388. },
  1389. }
  1390. c.Flags().BoolP("boola", "a", false, "a boolean flag")
  1391. _, err := executeCommand(c, "c", "-a", "--unknown", "flag")
  1392. if err != nil {
  1393. t.Error("unexpected error: ", err)
  1394. }
  1395. }
  1396. func TestFParseErrWhitelistParentCommand(t *testing.T) {
  1397. root := &Command{
  1398. Use: "root",
  1399. Run: emptyRun,
  1400. FParseErrWhitelist: FParseErrWhitelist{
  1401. UnknownFlags: true,
  1402. },
  1403. }
  1404. c := &Command{
  1405. Use: "child",
  1406. Run: emptyRun,
  1407. }
  1408. c.Flags().BoolP("boola", "a", false, "a boolean flag")
  1409. root.AddCommand(c)
  1410. output, err := executeCommand(root, "child", "-a", "--unknown", "flag")
  1411. if err == nil {
  1412. t.Error("expected unknown flag error")
  1413. }
  1414. checkStringContains(t, output, "unknown flag: --unknown")
  1415. }
  1416. func TestFParseErrWhitelistChildCommand(t *testing.T) {
  1417. root := &Command{
  1418. Use: "root",
  1419. Run: emptyRun,
  1420. }
  1421. c := &Command{
  1422. Use: "child",
  1423. Run: emptyRun,
  1424. FParseErrWhitelist: FParseErrWhitelist{
  1425. UnknownFlags: true,
  1426. },
  1427. }
  1428. c.Flags().BoolP("boola", "a", false, "a boolean flag")
  1429. root.AddCommand(c)
  1430. _, err := executeCommand(root, "child", "-a", "--unknown", "flag")
  1431. if err != nil {
  1432. t.Error("unexpected error: ", err.Error())
  1433. }
  1434. }
  1435. func TestFParseErrWhitelistSiblingCommand(t *testing.T) {
  1436. root := &Command{
  1437. Use: "root",
  1438. Run: emptyRun,
  1439. }
  1440. c := &Command{
  1441. Use: "child",
  1442. Run: emptyRun,
  1443. FParseErrWhitelist: FParseErrWhitelist{
  1444. UnknownFlags: true,
  1445. },
  1446. }
  1447. c.Flags().BoolP("boola", "a", false, "a boolean flag")
  1448. s := &Command{
  1449. Use: "sibling",
  1450. Run: emptyRun,
  1451. }
  1452. s.Flags().BoolP("boolb", "b", false, "a boolean flag")
  1453. root.AddCommand(c)
  1454. root.AddCommand(s)
  1455. output, err := executeCommand(root, "sibling", "-b", "--unknown", "flag")
  1456. if err == nil {
  1457. t.Error("expected unknown flag error")
  1458. }
  1459. checkStringContains(t, output, "unknown flag: --unknown")
  1460. }