docopt_test.go 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519
  1. /*
  2. Based of off docopt.py: https://github.com/docopt/docopt
  3. Licensed under terms of MIT license (see LICENSE-MIT)
  4. Copyright (c) 2013 Keith Batten, kbatten@gmail.com
  5. */
  6. package docopt
  7. import (
  8. "bytes"
  9. "encoding/json"
  10. "fmt"
  11. "io/ioutil"
  12. "os"
  13. "reflect"
  14. "regexp"
  15. "strings"
  16. "testing"
  17. )
  18. var testParser = &Parser{HelpHandler: NoHelpHandler}
  19. func TestPatternFlat(t *testing.T) {
  20. q := patternList{
  21. newArgument("N", nil),
  22. newOption("-a", "", 0, false),
  23. newArgument("M", nil)}
  24. p, err := newRequired(
  25. newOneOrMore(newArgument("N", nil)),
  26. newOption("-a", "", 0, false),
  27. newArgument("M", nil)).flat(patternDefault)
  28. if reflect.DeepEqual(p, q) != true {
  29. t.Error(err)
  30. }
  31. q = patternList{newOptionsShortcut()}
  32. p, err = newRequired(
  33. newOptional(newOptionsShortcut()),
  34. newOptional(newOption("-a", "", 0, false))).flat(patternOptionSSHORTCUT)
  35. if reflect.DeepEqual(p, q) != true {
  36. t.Error(err)
  37. }
  38. return
  39. }
  40. func TestOption(t *testing.T) {
  41. if !parseOption("-h").eq(newOption("-h", "", 0, false)) {
  42. t.Fail()
  43. }
  44. if !parseOption("--help").eq(newOption("", "--help", 0, false)) {
  45. t.Fail()
  46. }
  47. if !parseOption("-h --help").eq(newOption("-h", "--help", 0, false)) {
  48. t.Fail()
  49. }
  50. if !parseOption("-h, --help").eq(newOption("-h", "--help", 0, false)) {
  51. t.Fail()
  52. }
  53. if !parseOption("-h TOPIC").eq(newOption("-h", "", 1, false)) {
  54. t.Fail()
  55. }
  56. if !parseOption("--help TOPIC").eq(newOption("", "--help", 1, false)) {
  57. t.Fail()
  58. }
  59. if !parseOption("-h TOPIC --help TOPIC").eq(newOption("-h", "--help", 1, false)) {
  60. t.Fail()
  61. }
  62. if !parseOption("-h TOPIC, --help TOPIC").eq(newOption("-h", "--help", 1, false)) {
  63. t.Fail()
  64. }
  65. if !parseOption("-h TOPIC, --help=TOPIC").eq(newOption("-h", "--help", 1, false)) {
  66. t.Fail()
  67. }
  68. if !parseOption("-h Description...").eq(newOption("-h", "", 0, false)) {
  69. t.Fail()
  70. }
  71. if !parseOption("-h --help Description...").eq(newOption("-h", "--help", 0, false)) {
  72. t.Fail()
  73. }
  74. if !parseOption("-h TOPIC Description...").eq(newOption("-h", "", 1, false)) {
  75. t.Fail()
  76. }
  77. if !parseOption(" -h").eq(newOption("-h", "", 0, false)) {
  78. t.Fail()
  79. }
  80. if !parseOption("-h TOPIC Description... [default: 2]").eq(newOption("-h", "", 1, "2")) {
  81. t.Fail()
  82. }
  83. if !parseOption("-h TOPIC Descripton... [default: topic-1]").eq(newOption("-h", "", 1, "topic-1")) {
  84. t.Fail()
  85. }
  86. if !parseOption("--help=TOPIC ... [default: 3.14]").eq(newOption("", "--help", 1, "3.14")) {
  87. t.Fail()
  88. }
  89. if !parseOption("-h, --help=DIR ... [default: ./]").eq(newOption("-h", "--help", 1, "./")) {
  90. t.Fail()
  91. }
  92. if !parseOption("-h TOPIC Descripton... [dEfAuLt: 2]").eq(newOption("-h", "", 1, "2")) {
  93. t.Fail()
  94. }
  95. return
  96. }
  97. func TestOptionName(t *testing.T) {
  98. if newOption("-h", "", 0, false).name != "-h" {
  99. t.Fail()
  100. }
  101. if newOption("-h", "--help", 0, false).name != "--help" {
  102. t.Fail()
  103. }
  104. if newOption("", "--help", 0, false).name != "--help" {
  105. t.Fail()
  106. }
  107. return
  108. }
  109. func TestCommands(t *testing.T) {
  110. if v, err := testParser.ParseArgs("Usage: prog add", []string{"add"}, ""); reflect.DeepEqual(v, Opts{"add": true}) != true {
  111. t.Error(err)
  112. }
  113. if v, err := testParser.ParseArgs("Usage: prog [add]", []string{}, ""); reflect.DeepEqual(v, Opts{"add": false}) != true {
  114. t.Error(err)
  115. }
  116. if v, err := testParser.ParseArgs("Usage: prog [add]", []string{"add"}, ""); reflect.DeepEqual(v, Opts{"add": true}) != true {
  117. t.Error(err)
  118. }
  119. if v, err := testParser.ParseArgs("Usage: prog (add|rm)", []string{"add"}, ""); reflect.DeepEqual(v, Opts{"add": true, "rm": false}) != true {
  120. t.Error(err)
  121. }
  122. if v, err := testParser.ParseArgs("Usage: prog (add|rm)", []string{"rm"}, ""); reflect.DeepEqual(v, Opts{"add": false, "rm": true}) != true {
  123. t.Error(err)
  124. }
  125. if v, err := testParser.ParseArgs("Usage: prog a b", []string{"a", "b"}, ""); reflect.DeepEqual(v, Opts{"a": true, "b": true}) != true {
  126. t.Error(err)
  127. }
  128. _, err := testParser.ParseArgs("Usage: prog a b", []string{"b", "a"}, "")
  129. if _, ok := err.(*UserError); !ok {
  130. t.Error(err)
  131. }
  132. return
  133. }
  134. func TestFormalUsage(t *testing.T) {
  135. doc := `
  136. Usage: prog [-hv] ARG
  137. prog N M
  138. prog is a program`
  139. usage := parseSection("usage:", doc)[0]
  140. if usage != "Usage: prog [-hv] ARG\n prog N M" {
  141. t.FailNow()
  142. }
  143. formal, err := formalUsage(usage)
  144. if err != nil {
  145. t.Fatal(err)
  146. }
  147. if formal != "( [-hv] ARG ) | ( N M )" {
  148. t.Fail()
  149. }
  150. return
  151. }
  152. func TestParseArgv(t *testing.T) {
  153. o := patternList{
  154. newOption("-h", "", 0, false),
  155. newOption("-v", "--verbose", 0, false),
  156. newOption("-f", "--file", 1, false),
  157. }
  158. p, err := parseArgv(tokenListFromString(""), &o, false)
  159. q := patternList{}
  160. if reflect.DeepEqual(p, q) != true {
  161. t.Error(err)
  162. }
  163. p, err = parseArgv(tokenListFromString("-h"), &o, false)
  164. q = patternList{newOption("-h", "", 0, true)}
  165. if reflect.DeepEqual(p, q) != true {
  166. t.Error(err)
  167. }
  168. p, err = parseArgv(tokenListFromString("-h --verbose"), &o, false)
  169. q = patternList{
  170. newOption("-h", "", 0, true),
  171. newOption("-v", "--verbose", 0, true),
  172. }
  173. if reflect.DeepEqual(p, q) != true {
  174. t.Error(err)
  175. }
  176. p, err = parseArgv(tokenListFromString("-h --file f.txt"), &o, false)
  177. q = patternList{
  178. newOption("-h", "", 0, true),
  179. newOption("-f", "--file", 1, "f.txt"),
  180. }
  181. if reflect.DeepEqual(p, q) != true {
  182. t.Error(err)
  183. }
  184. p, err = parseArgv(tokenListFromString("-h --file f.txt arg"), &o, false)
  185. q = patternList{
  186. newOption("-h", "", 0, true),
  187. newOption("-f", "--file", 1, "f.txt"),
  188. newArgument("", "arg"),
  189. }
  190. if reflect.DeepEqual(p, q) != true {
  191. t.Error(err)
  192. }
  193. p, err = parseArgv(tokenListFromString("-h --file f.txt arg arg2"), &o, false)
  194. q = patternList{
  195. newOption("-h", "", 0, true),
  196. newOption("-f", "--file", 1, "f.txt"),
  197. newArgument("", "arg"),
  198. newArgument("", "arg2"),
  199. }
  200. if reflect.DeepEqual(p, q) != true {
  201. t.Error(err)
  202. }
  203. p, err = parseArgv(tokenListFromString("-h arg -- -v"), &o, false)
  204. q = patternList{
  205. newOption("-h", "", 0, true),
  206. newArgument("", "arg"),
  207. newArgument("", "--"),
  208. newArgument("", "-v"),
  209. }
  210. if reflect.DeepEqual(p, q) != true {
  211. t.Error(err)
  212. }
  213. }
  214. func TestParsePattern(t *testing.T) {
  215. o := patternList{
  216. newOption("-h", "", 0, false),
  217. newOption("-v", "--verbose", 0, false),
  218. newOption("-f", "--file", 1, false),
  219. }
  220. p, err := parsePattern("[ -h ]", &o)
  221. q := newRequired(newOptional(newOption("-h", "", 0, false)))
  222. if p.eq(q) != true {
  223. t.Error(err)
  224. }
  225. p, err = parsePattern("[ ARG ... ]", &o)
  226. q = newRequired(newOptional(
  227. newOneOrMore(
  228. newArgument("ARG", nil))))
  229. if p.eq(q) != true {
  230. t.Error(err)
  231. }
  232. p, err = parsePattern("[ -h | -v ]", &o)
  233. q = newRequired(
  234. newOptional(
  235. newEither(
  236. newOption("-h", "", 0, false),
  237. newOption("-v", "--verbose", 0, false))))
  238. if p.eq(q) != true {
  239. t.Error(err)
  240. }
  241. p, err = parsePattern("( -h | -v [ --file <f> ] )", &o)
  242. q = newRequired(
  243. newRequired(
  244. newEither(
  245. newOption("-h", "", 0, false),
  246. newRequired(
  247. newOption("-v", "--verbose", 0, false),
  248. newOptional(
  249. newOption("-f", "--file", 1, nil))))))
  250. if p.eq(q) != true {
  251. t.Error(err)
  252. }
  253. p, err = parsePattern("(-h|-v[--file=<f>]N...)", &o)
  254. q = newRequired(
  255. newRequired(
  256. newEither(
  257. newOption("-h", "", 0, false),
  258. newRequired(
  259. newOption("-v", "--verbose", 0, false),
  260. newOptional(
  261. newOption("-f", "--file", 1, nil)),
  262. newOneOrMore(
  263. newArgument("N", nil))))))
  264. if p.eq(q) != true {
  265. t.Error(err)
  266. }
  267. p, err = parsePattern("(N [M | (K | L)] | O P)", &o)
  268. q = newRequired(
  269. newRequired(
  270. newEither(
  271. newRequired(
  272. newArgument("N", nil),
  273. newOptional(
  274. newEither(
  275. newArgument("M", nil),
  276. newRequired(
  277. newEither(
  278. newArgument("K", nil),
  279. newArgument("L", nil)))))),
  280. newRequired(
  281. newArgument("O", nil),
  282. newArgument("P", nil)))))
  283. if p.eq(q) != true {
  284. t.Error(err)
  285. }
  286. p, err = parsePattern("[ -h ] [N]", &o)
  287. q = newRequired(
  288. newOptional(
  289. newOption("-h", "", 0, false)),
  290. newOptional(
  291. newArgument("N", nil)))
  292. if p.eq(q) != true {
  293. t.Error(err)
  294. }
  295. p, err = parsePattern("[options]", &o)
  296. q = newRequired(
  297. newOptional(
  298. newOptionsShortcut()))
  299. if p.eq(q) != true {
  300. t.Error(err)
  301. }
  302. p, err = parsePattern("[options] A", &o)
  303. q = newRequired(
  304. newOptional(
  305. newOptionsShortcut()),
  306. newArgument("A", nil))
  307. if p.eq(q) != true {
  308. t.Error(err)
  309. }
  310. p, err = parsePattern("-v [options]", &o)
  311. q = newRequired(
  312. newOption("-v", "--verbose", 0, false),
  313. newOptional(
  314. newOptionsShortcut()))
  315. if p.eq(q) != true {
  316. t.Error(err)
  317. }
  318. p, err = parsePattern("ADD", &o)
  319. q = newRequired(newArgument("ADD", nil))
  320. if p.eq(q) != true {
  321. t.Error(err)
  322. }
  323. p, err = parsePattern("<add>", &o)
  324. q = newRequired(newArgument("<add>", nil))
  325. if p.eq(q) != true {
  326. t.Error(err)
  327. }
  328. p, err = parsePattern("add", &o)
  329. q = newRequired(newCommand("add", false))
  330. if p.eq(q) != true {
  331. t.Error(err)
  332. }
  333. }
  334. func TestOptionMatch(t *testing.T) {
  335. v, w, x := newOption("-a", "", 0, false).match(
  336. &patternList{newOption("-a", "", 0, true)}, nil)
  337. y := patternList{newOption("-a", "", 0, true)}
  338. if v != true ||
  339. reflect.DeepEqual(*w, patternList{}) != true ||
  340. reflect.DeepEqual(*x, y) != true {
  341. t.Fail()
  342. }
  343. v, w, x = newOption("-a", "", 0, false).match(
  344. &patternList{newOption("-x", "", 0, false)}, nil)
  345. y = patternList{newOption("-x", "", 0, false)}
  346. if v != false ||
  347. reflect.DeepEqual(*w, y) != true ||
  348. reflect.DeepEqual(*x, patternList{}) != true {
  349. t.Fail()
  350. }
  351. v, w, x = newOption("-a", "", 0, false).match(
  352. &patternList{newOption("-x", "", 0, false)}, nil)
  353. y = patternList{newOption("-x", "", 0, false)}
  354. if v != false ||
  355. reflect.DeepEqual(*w, y) != true ||
  356. reflect.DeepEqual(*x, patternList{}) != true {
  357. t.Fail()
  358. }
  359. v, w, x = newOption("-a", "", 0, false).match(
  360. &patternList{newArgument("N", nil)}, nil)
  361. y = patternList{newArgument("N", nil)}
  362. if v != false ||
  363. reflect.DeepEqual(*w, y) != true ||
  364. reflect.DeepEqual(*x, patternList{}) != true {
  365. t.Fail()
  366. }
  367. v, w, x = newOption("-a", "", 0, false).match(
  368. &patternList{
  369. newOption("-x", "", 0, false),
  370. newOption("-a", "", 0, false),
  371. newArgument("N", nil)}, nil)
  372. y = patternList{
  373. newOption("-x", "", 0, false),
  374. newArgument("N", nil)}
  375. z := patternList{newOption("-a", "", 0, false)}
  376. if v != true ||
  377. reflect.DeepEqual(*w, y) != true ||
  378. reflect.DeepEqual(*x, z) != true {
  379. t.Fail()
  380. }
  381. v, w, x = newOption("-a", "", 0, false).match(
  382. &patternList{
  383. newOption("-a", "", 0, true),
  384. newOption("-a", "", 0, false)}, nil)
  385. y = patternList{newOption("-a", "", 0, false)}
  386. z = patternList{newOption("-a", "", 0, true)}
  387. if v != true ||
  388. reflect.DeepEqual(*w, y) != true ||
  389. reflect.DeepEqual(*x, z) != true {
  390. t.Fail()
  391. }
  392. }
  393. func TestArgumentMatch(t *testing.T) {
  394. v, w, x := newArgument("N", nil).match(
  395. &patternList{newArgument("N", 9)}, nil)
  396. y := patternList{newArgument("N", 9)}
  397. if v != true ||
  398. reflect.DeepEqual(*w, patternList{}) != true ||
  399. reflect.DeepEqual(*x, y) != true {
  400. t.Fail()
  401. }
  402. v, w, x = newArgument("N", nil).match(
  403. &patternList{newOption("-x", "", 0, false)}, nil)
  404. y = patternList{newOption("-x", "", 0, false)}
  405. if v != false ||
  406. reflect.DeepEqual(*w, y) != true ||
  407. reflect.DeepEqual(*x, patternList{}) != true {
  408. t.Fail()
  409. }
  410. v, w, x = newArgument("N", nil).match(
  411. &patternList{newOption("-x", "", 0, false),
  412. newOption("-a", "", 0, false),
  413. newArgument("", 5)}, nil)
  414. y = patternList{newOption("-x", "", 0, false),
  415. newOption("-a", "", 0, false)}
  416. z := patternList{newArgument("N", 5)}
  417. if v != true ||
  418. reflect.DeepEqual(*w, y) != true ||
  419. reflect.DeepEqual(*x, z) != true {
  420. t.Fail()
  421. }
  422. v, w, x = newArgument("N", nil).match(
  423. &patternList{newArgument("", 9),
  424. newArgument("", 0)}, nil)
  425. y = patternList{newArgument("", 0)}
  426. z = patternList{newArgument("N", 9)}
  427. if v != true ||
  428. reflect.DeepEqual(*w, y) != true ||
  429. reflect.DeepEqual(*x, z) != true {
  430. t.Fail()
  431. }
  432. }
  433. func TestCommandMatch(t *testing.T) {
  434. v, w, x := newCommand("c", false).match(
  435. &patternList{newArgument("", "c")}, nil)
  436. y := patternList{newCommand("c", true)}
  437. if v != true ||
  438. reflect.DeepEqual(*w, patternList{}) != true ||
  439. reflect.DeepEqual(*x, y) != true {
  440. t.Fail()
  441. }
  442. v, w, x = newCommand("c", false).match(
  443. &patternList{newOption("-x", "", 0, false)}, nil)
  444. y = patternList{newOption("-x", "", 0, false)}
  445. if v != false ||
  446. reflect.DeepEqual(*w, y) != true ||
  447. reflect.DeepEqual(*x, patternList{}) != true {
  448. t.Fail()
  449. }
  450. v, w, x = newCommand("c", false).match(
  451. &patternList{
  452. newOption("-x", "", 0, false),
  453. newOption("-a", "", 0, false),
  454. newArgument("", "c")}, nil)
  455. y = patternList{newOption("-x", "", 0, false),
  456. newOption("-a", "", 0, false)}
  457. z := patternList{newCommand("c", true)}
  458. if v != true ||
  459. reflect.DeepEqual(*w, y) != true ||
  460. reflect.DeepEqual(*x, z) != true {
  461. t.Fail()
  462. }
  463. v, w, x = newEither(
  464. newCommand("add", false),
  465. newCommand("rm", false)).match(
  466. &patternList{newArgument("", "rm")}, nil)
  467. y = patternList{newCommand("rm", true)}
  468. if v != true ||
  469. reflect.DeepEqual(*w, patternList{}) != true ||
  470. reflect.DeepEqual(*x, y) != true {
  471. t.Fail()
  472. }
  473. }
  474. func TestOptionalMatch(t *testing.T) {
  475. v, w, x := newOptional(newOption("-a", "", 0, false)).match(
  476. &patternList{newOption("-a", "", 0, false)}, nil)
  477. y := patternList{newOption("-a", "", 0, false)}
  478. if v != true ||
  479. reflect.DeepEqual(*w, patternList{}) != true ||
  480. reflect.DeepEqual(*x, y) != true {
  481. t.Fail()
  482. }
  483. v, w, x = newOptional(newOption("-a", "", 0, false)).match(
  484. &patternList{}, nil)
  485. if v != true ||
  486. reflect.DeepEqual(*w, patternList{}) != true ||
  487. reflect.DeepEqual(*x, patternList{}) != true {
  488. t.Fail()
  489. }
  490. v, w, x = newOptional(newOption("-a", "", 0, false)).match(
  491. &patternList{newOption("-x", "", 0, false)}, nil)
  492. y = patternList{newOption("-x", "", 0, false)}
  493. if v != true ||
  494. reflect.DeepEqual(*w, y) != true ||
  495. reflect.DeepEqual(*x, patternList{}) != true {
  496. t.Fail()
  497. }
  498. v, w, x = newOptional(newOption("-a", "", 0, false),
  499. newOption("-b", "", 0, false)).match(
  500. &patternList{newOption("-a", "", 0, false)}, nil)
  501. y = patternList{newOption("-a", "", 0, false)}
  502. if v != true ||
  503. reflect.DeepEqual(*w, patternList{}) != true ||
  504. reflect.DeepEqual(*x, y) != true {
  505. t.Fail()
  506. }
  507. v, w, x = newOptional(newOption("-a", "", 0, false),
  508. newOption("-b", "", 0, false)).match(
  509. &patternList{newOption("-b", "", 0, false)}, nil)
  510. y = patternList{newOption("-b", "", 0, false)}
  511. if v != true ||
  512. reflect.DeepEqual(*w, patternList{}) != true ||
  513. reflect.DeepEqual(*x, y) != true {
  514. t.Fail()
  515. }
  516. v, w, x = newOptional(newOption("-a", "", 0, false),
  517. newOption("-b", "", 0, false)).match(
  518. &patternList{newOption("-x", "", 0, false)}, nil)
  519. y = patternList{newOption("-x", "", 0, false)}
  520. if v != true ||
  521. reflect.DeepEqual(*w, y) != true ||
  522. reflect.DeepEqual(*x, patternList{}) != true {
  523. t.Fail()
  524. }
  525. v, w, x = newOptional(newArgument("N", nil)).match(
  526. &patternList{newArgument("", 9)}, nil)
  527. y = patternList{newArgument("N", 9)}
  528. if v != true ||
  529. reflect.DeepEqual(*w, patternList{}) != true ||
  530. reflect.DeepEqual(*x, y) != true {
  531. t.Fail()
  532. }
  533. v, w, x = newOptional(newOption("-a", "", 0, false),
  534. newOption("-b", "", 0, false)).match(
  535. &patternList{newOption("-b", "", 0, false),
  536. newOption("-x", "", 0, false),
  537. newOption("-a", "", 0, false)}, nil)
  538. y = patternList{newOption("-x", "", 0, false)}
  539. z := patternList{newOption("-a", "", 0, false),
  540. newOption("-b", "", 0, false)}
  541. if v != true ||
  542. reflect.DeepEqual(*w, y) != true ||
  543. reflect.DeepEqual(*x, z) != true {
  544. t.Fail()
  545. }
  546. }
  547. func TestRequiredMatch(t *testing.T) {
  548. v, w, x := newRequired(newOption("-a", "", 0, false)).match(
  549. &patternList{newOption("-a", "", 0, false)}, nil)
  550. y := patternList{newOption("-a", "", 0, false)}
  551. if v != true ||
  552. reflect.DeepEqual(*w, patternList{}) != true ||
  553. reflect.DeepEqual(*x, y) != true {
  554. t.Fail()
  555. }
  556. v, w, x = newRequired(newOption("-a", "", 0, false)).match(&patternList{}, nil)
  557. if v != false ||
  558. reflect.DeepEqual(*w, patternList{}) != true ||
  559. reflect.DeepEqual(*x, patternList{}) != true {
  560. t.Fail()
  561. }
  562. v, w, x = newRequired(newOption("-a", "", 0, false)).match(
  563. &patternList{newOption("-x", "", 0, false)}, nil)
  564. y = patternList{newOption("-x", "", 0, false)}
  565. if v != false ||
  566. reflect.DeepEqual(*w, y) != true ||
  567. reflect.DeepEqual(*x, patternList{}) != true {
  568. t.Fail()
  569. }
  570. v, w, x = newRequired(newOption("-a", "", 0, false),
  571. newOption("-b", "", 0, false)).match(
  572. &patternList{newOption("-a", "", 0, false)}, nil)
  573. y = patternList{newOption("-a", "", 0, false)}
  574. if v != false ||
  575. reflect.DeepEqual(*w, y) != true ||
  576. reflect.DeepEqual(*x, patternList{}) != true {
  577. t.Fail()
  578. }
  579. }
  580. func TestEitherMatch(t *testing.T) {
  581. v, w, x := newEither(
  582. newOption("-a", "", 0, false),
  583. newOption("-b", "", 0, false)).match(
  584. &patternList{newOption("-a", "", 0, false)}, nil)
  585. y := patternList{newOption("-a", "", 0, false)}
  586. if v != true ||
  587. reflect.DeepEqual(*w, patternList{}) != true ||
  588. reflect.DeepEqual(*x, y) != true {
  589. t.Fail()
  590. }
  591. v, w, x = newEither(
  592. newOption("-a", "", 0, false),
  593. newOption("-b", "", 0, false)).match(&patternList{
  594. newOption("-a", "", 0, false),
  595. newOption("-b", "", 0, false)}, nil)
  596. y = patternList{newOption("-b", "", 0, false)}
  597. z := patternList{newOption("-a", "", 0, false)}
  598. if v != true ||
  599. reflect.DeepEqual(*w, y) != true ||
  600. reflect.DeepEqual(*x, z) != true {
  601. t.Fail()
  602. }
  603. v, w, x = newEither(
  604. newOption("-a", "", 0, false),
  605. newOption("-b", "", 0, false)).match(&patternList{
  606. newOption("-x", "", 0, false)}, nil)
  607. y = patternList{newOption("-x", "", 0, false)}
  608. z = patternList{}
  609. if v != false ||
  610. reflect.DeepEqual(*w, y) != true ||
  611. reflect.DeepEqual(*x, z) != true {
  612. t.Fail()
  613. }
  614. v, w, x = newEither(
  615. newOption("-a", "", 0, false),
  616. newOption("-b", "", 0, false),
  617. newOption("-c", "", 0, false)).match(&patternList{
  618. newOption("-x", "", 0, false),
  619. newOption("-b", "", 0, false)}, nil)
  620. y = patternList{newOption("-x", "", 0, false)}
  621. z = patternList{newOption("-b", "", 0, false)}
  622. if v != true ||
  623. reflect.DeepEqual(*w, y) != true ||
  624. reflect.DeepEqual(*x, z) != true {
  625. t.Fail()
  626. }
  627. v, w, x = newEither(
  628. newArgument("M", nil),
  629. newRequired(newArgument("N", nil),
  630. newArgument("M", nil))).match(&patternList{
  631. newArgument("", 1),
  632. newArgument("", 2)}, nil)
  633. y = patternList{}
  634. z = patternList{newArgument("N", 1), newArgument("M", 2)}
  635. if v != true ||
  636. reflect.DeepEqual(*w, y) != true ||
  637. reflect.DeepEqual(*x, z) != true {
  638. t.Fail()
  639. }
  640. }
  641. func TestOneOrMoreMatch(t *testing.T) {
  642. v, w, x := newOneOrMore(newArgument("N", nil)).match(
  643. &patternList{newArgument("", 9)}, nil)
  644. y := patternList{newArgument("N", 9)}
  645. if v != true ||
  646. reflect.DeepEqual(*w, patternList{}) != true ||
  647. reflect.DeepEqual(*x, y) != true {
  648. t.Fail()
  649. }
  650. v, w, x = newOneOrMore(newArgument("N", nil)).match(
  651. &patternList{}, nil)
  652. y = patternList{}
  653. z := patternList{}
  654. if v != false ||
  655. reflect.DeepEqual(*w, y) != true ||
  656. reflect.DeepEqual(*x, z) != true {
  657. t.Fail()
  658. }
  659. v, w, x = newOneOrMore(newArgument("N", nil)).match(
  660. &patternList{newOption("-x", "", 0, false)}, nil)
  661. y = patternList{newOption("-x", "", 0, false)}
  662. z = patternList{}
  663. if v != false ||
  664. reflect.DeepEqual(*w, y) != true ||
  665. reflect.DeepEqual(*x, z) != true {
  666. t.Fail()
  667. }
  668. v, w, x = newOneOrMore(newArgument("N", nil)).match(
  669. &patternList{newArgument("", 9), newArgument("", 8)}, nil)
  670. y = patternList{}
  671. z = patternList{newArgument("N", 9), newArgument("N", 8)}
  672. if v != true ||
  673. reflect.DeepEqual(*w, y) != true ||
  674. reflect.DeepEqual(*x, z) != true {
  675. t.Fail()
  676. }
  677. v, w, x = newOneOrMore(newArgument("N", nil)).match(&patternList{
  678. newArgument("", 9),
  679. newOption("-x", "", 0, false),
  680. newArgument("", 8)}, nil)
  681. y = patternList{newOption("-x", "", 0, false)}
  682. z = patternList{newArgument("N", 9), newArgument("N", 8)}
  683. if v != true ||
  684. reflect.DeepEqual(*w, y) != true ||
  685. reflect.DeepEqual(*x, z) != true {
  686. t.Fail()
  687. }
  688. v, w, x = newOneOrMore(newOption("-a", "", 0, false)).match(&patternList{
  689. newOption("-a", "", 0, false),
  690. newArgument("", 8),
  691. newOption("-a", "", 0, false)}, nil)
  692. y = patternList{newArgument("", 8)}
  693. z = patternList{newOption("-a", "", 0, false), newOption("-a", "", 0, false)}
  694. if v != true ||
  695. reflect.DeepEqual(*w, y) != true ||
  696. reflect.DeepEqual(*x, z) != true {
  697. t.Fail()
  698. }
  699. v, w, x = newOneOrMore(newOption("-a", "", 0, false)).match(&patternList{
  700. newArgument("", 8),
  701. newOption("-x", "", 0, false)}, nil)
  702. y = patternList{newArgument("", 8), newOption("-x", "", 0, false)}
  703. z = patternList{}
  704. if v != false ||
  705. reflect.DeepEqual(*w, y) != true ||
  706. reflect.DeepEqual(*x, z) != true {
  707. t.Fail()
  708. }
  709. v, w, x = newOneOrMore(newRequired(newOption("-a", "", 0, false),
  710. newArgument("N", nil))).match(&patternList{
  711. newOption("-a", "", 0, false),
  712. newArgument("", 1),
  713. newOption("-x", "", 0, false),
  714. newOption("-a", "", 0, false),
  715. newArgument("", 2)}, nil)
  716. y = patternList{newOption("-x", "", 0, false)}
  717. z = patternList{newOption("-a", "", 0, false),
  718. newArgument("N", 1),
  719. newOption("-a", "", 0, false),
  720. newArgument("N", 2)}
  721. if v != true ||
  722. reflect.DeepEqual(*w, y) != true ||
  723. reflect.DeepEqual(*x, z) != true {
  724. t.Fail()
  725. }
  726. v, w, x = newOneOrMore(newOptional(newArgument("N", nil))).match(
  727. &patternList{newArgument("", 9)}, nil)
  728. y = patternList{}
  729. z = patternList{newArgument("N", 9)}
  730. if v != true ||
  731. reflect.DeepEqual(*w, y) != true ||
  732. reflect.DeepEqual(*x, z) != true {
  733. t.Fail()
  734. }
  735. }
  736. func TestListArgumentMatch(t *testing.T) {
  737. p := newRequired(
  738. newArgument("N", nil),
  739. newArgument("N", nil))
  740. p.fix()
  741. v, w, x := p.match(&patternList{newArgument("", "1"),
  742. newArgument("", "2")}, nil)
  743. y := patternList{newArgument("N", []string{"1", "2"})}
  744. if v != true ||
  745. reflect.DeepEqual(*w, patternList{}) != true ||
  746. reflect.DeepEqual(*x, y) != true {
  747. t.Fail()
  748. }
  749. p = newOneOrMore(newArgument("N", nil))
  750. p.fix()
  751. v, w, x = p.match(&patternList{newArgument("", "1"),
  752. newArgument("", "2"), newArgument("", "3")}, nil)
  753. y = patternList{newArgument("N", []string{"1", "2", "3"})}
  754. if v != true ||
  755. reflect.DeepEqual(*w, patternList{}) != true ||
  756. reflect.DeepEqual(*x, y) != true {
  757. t.Fail()
  758. }
  759. p = newRequired(newArgument("N", nil),
  760. newOneOrMore(newArgument("N", nil)))
  761. p.fix()
  762. v, w, x = p.match(&patternList{
  763. newArgument("", "1"),
  764. newArgument("", "2"),
  765. newArgument("", "3")}, nil)
  766. y = patternList{newArgument("N", []string{"1", "2", "3"})}
  767. if v != true ||
  768. reflect.DeepEqual(*w, patternList{}) != true ||
  769. reflect.DeepEqual(*x, y) != true {
  770. t.Fail()
  771. }
  772. p = newRequired(newArgument("N", nil),
  773. newRequired(newArgument("N", nil)))
  774. p.fix()
  775. v, w, x = p.match(&patternList{
  776. newArgument("", "1"),
  777. newArgument("", "2")}, nil)
  778. y = patternList{newArgument("N", []string{"1", "2"})}
  779. if v != true ||
  780. reflect.DeepEqual(*w, patternList{}) != true ||
  781. reflect.DeepEqual(*x, y) != true {
  782. t.Fail()
  783. }
  784. }
  785. func TestBasicPatternMatching(t *testing.T) {
  786. // ( -a N [ -x Z ] )
  787. p := newRequired(
  788. newOption("-a", "", 0, false),
  789. newArgument("N", nil),
  790. newOptional(
  791. newOption("-x", "", 0, false),
  792. newArgument("Z", nil)))
  793. // -a N
  794. q := patternList{newOption("-a", "", 0, false), newArgument("", 9)}
  795. y := patternList{newOption("-a", "", 0, false), newArgument("N", 9)}
  796. v, w, x := p.match(&q, nil)
  797. if v != true ||
  798. reflect.DeepEqual(*w, patternList{}) != true ||
  799. reflect.DeepEqual(*x, y) != true {
  800. t.Fail()
  801. }
  802. // -a -x N Z
  803. q = patternList{newOption("-a", "", 0, false),
  804. newOption("-x", "", 0, false),
  805. newArgument("", 9), newArgument("", 5)}
  806. y = patternList{}
  807. z := patternList{newOption("-a", "", 0, false), newArgument("N", 9),
  808. newOption("-x", "", 0, false), newArgument("Z", 5)}
  809. v, w, x = p.match(&q, nil)
  810. if v != true ||
  811. reflect.DeepEqual(*w, y) != true ||
  812. reflect.DeepEqual(*x, z) != true {
  813. t.Fail()
  814. }
  815. // -x N Z # BZZ!
  816. q = patternList{newOption("-x", "", 0, false),
  817. newArgument("", 9), newArgument("", 5)}
  818. y = patternList{newOption("-x", "", 0, false),
  819. newArgument("", 9), newArgument("", 5)}
  820. z = patternList{}
  821. v, w, x = p.match(&q, nil)
  822. if v != false ||
  823. reflect.DeepEqual(*w, y) != true ||
  824. reflect.DeepEqual(*x, z) != true {
  825. t.Fail()
  826. }
  827. }
  828. func TestPatternEither(t *testing.T) {
  829. p := newOption("-a", "", 0, false).transform()
  830. q := newEither(newRequired(
  831. newOption("-a", "", 0, false)))
  832. if p.eq(q) != true {
  833. t.Fail()
  834. }
  835. p = newArgument("A", nil).transform()
  836. q = newEither(newRequired(
  837. newArgument("A", nil)))
  838. if p.eq(q) != true {
  839. t.Fail()
  840. }
  841. p = newRequired(
  842. newEither(
  843. newOption("-a", "", 0, false),
  844. newOption("-b", "", 0, false)),
  845. newOption("-c", "", 0, false)).transform()
  846. q = newEither(
  847. newRequired(
  848. newOption("-a", "", 0, false),
  849. newOption("-c", "", 0, false)),
  850. newRequired(
  851. newOption("-b", "", 0, false),
  852. newOption("-c", "", 0, false)))
  853. if p.eq(q) != true {
  854. t.Fail()
  855. }
  856. p = newOptional(newOption("-a", "", 0, false),
  857. newEither(newOption("-b", "", 0, false),
  858. newOption("-c", "", 0, false))).transform()
  859. q = newEither(
  860. newRequired(
  861. newOption("-b", "", 0, false), newOption("-a", "", 0, false)),
  862. newRequired(
  863. newOption("-c", "", 0, false), newOption("-a", "", 0, false)))
  864. if p.eq(q) != true {
  865. t.Fail()
  866. }
  867. p = newEither(newOption("-x", "", 0, false),
  868. newEither(newOption("-y", "", 0, false),
  869. newOption("-z", "", 0, false))).transform()
  870. q = newEither(
  871. newRequired(newOption("-x", "", 0, false)),
  872. newRequired(newOption("-y", "", 0, false)),
  873. newRequired(newOption("-z", "", 0, false)))
  874. if p.eq(q) != true {
  875. t.Fail()
  876. }
  877. p = newOneOrMore(newArgument("N", nil),
  878. newArgument("M", nil)).transform()
  879. q = newEither(
  880. newRequired(newArgument("N", nil), newArgument("M", nil),
  881. newArgument("N", nil), newArgument("M", nil)))
  882. if p.eq(q) != true {
  883. t.Fail()
  884. }
  885. }
  886. func TestPatternFixRepeatingArguments(t *testing.T) {
  887. p := newOption("-a", "", 0, false)
  888. p.fixRepeatingArguments()
  889. if p.eq(newOption("-a", "", 0, false)) != true {
  890. t.Fail()
  891. }
  892. p = newArgument("N", nil)
  893. p.fixRepeatingArguments()
  894. if p.eq(newArgument("N", nil)) != true {
  895. t.Fail()
  896. }
  897. p = newRequired(
  898. newArgument("N", nil),
  899. newArgument("N", nil))
  900. q := newRequired(
  901. newArgument("N", []string{}),
  902. newArgument("N", []string{}))
  903. p.fixRepeatingArguments()
  904. if p.eq(q) != true {
  905. t.Fail()
  906. }
  907. p = newEither(
  908. newArgument("N", nil),
  909. newOneOrMore(newArgument("N", nil)))
  910. q = newEither(
  911. newArgument("N", []string{}),
  912. newOneOrMore(newArgument("N", []string{})))
  913. p.fix()
  914. if p.eq(q) != true {
  915. t.Fail()
  916. }
  917. }
  918. func TestSet(t *testing.T) {
  919. p := newArgument("N", nil)
  920. q := newArgument("N", nil)
  921. if reflect.DeepEqual(p, q) != true {
  922. t.Fail()
  923. }
  924. pl := patternList{newArgument("N", nil), newArgument("N", nil)}
  925. ql := patternList{newArgument("N", nil)}
  926. if reflect.DeepEqual(pl.unique(), ql.unique()) != true {
  927. t.Fail()
  928. }
  929. }
  930. func TestPatternFixIdentities1(t *testing.T) {
  931. p := newRequired(
  932. newArgument("N", nil),
  933. newArgument("N", nil))
  934. if len(p.children) < 2 {
  935. t.FailNow()
  936. }
  937. if p.children[0].eq(p.children[1]) != true {
  938. t.Fail()
  939. }
  940. if p.children[0] == p.children[1] {
  941. t.Fail()
  942. }
  943. p.fixIdentities(nil)
  944. if p.children[0] != p.children[1] {
  945. t.Fail()
  946. }
  947. }
  948. func TestPatternFixIdentities2(t *testing.T) {
  949. p := newRequired(
  950. newOptional(
  951. newArgument("X", nil),
  952. newArgument("N", nil)),
  953. newArgument("N", nil))
  954. if len(p.children) < 2 {
  955. t.FailNow()
  956. }
  957. if len(p.children[0].children) < 2 {
  958. t.FailNow()
  959. }
  960. if p.children[0].children[1].eq(p.children[1]) != true {
  961. t.Fail()
  962. }
  963. if p.children[0].children[1] == p.children[1] {
  964. t.Fail()
  965. }
  966. p.fixIdentities(nil)
  967. if p.children[0].children[1] != p.children[1] {
  968. t.Fail()
  969. }
  970. }
  971. func TestLongOptionsErrorHandling(t *testing.T) {
  972. _, err := testParser.ParseArgs("Usage: prog", []string{"--non-existent"}, "")
  973. if _, ok := err.(*UserError); !ok {
  974. t.Error(fmt.Sprintf("(%s) %s", reflect.TypeOf(err), err))
  975. }
  976. _, err = testParser.ParseArgs("Usage: prog [--version --verbose]\nOptions: --version\n --verbose", []string{"--ver"}, "")
  977. if _, ok := err.(*UserError); !ok {
  978. t.Error(err)
  979. }
  980. _, err = testParser.ParseArgs("Usage: prog --long\nOptions: --long ARG", []string{}, "")
  981. if _, ok := err.(*LanguageError); !ok {
  982. t.Error(err)
  983. }
  984. _, err = testParser.ParseArgs("Usage: prog --long ARG\nOptions: --long ARG", []string{"--long"}, "")
  985. if _, ok := err.(*UserError); !ok {
  986. t.Error(fmt.Sprintf("(%s) %s", reflect.TypeOf(err), err))
  987. }
  988. _, err = testParser.ParseArgs("Usage: prog --long=ARG\nOptions: --long", []string{}, "")
  989. if _, ok := err.(*LanguageError); !ok {
  990. t.Error(err)
  991. }
  992. _, err = testParser.ParseArgs("Usage: prog --long\nOptions: --long", []string{}, "--long=ARG")
  993. if _, ok := err.(*UserError); !ok {
  994. t.Error(err)
  995. }
  996. }
  997. func TestShortOptionsErrorHandling(t *testing.T) {
  998. _, err := testParser.ParseArgs("Usage: prog -x\nOptions: -x this\n -x that", []string{}, "")
  999. if _, ok := err.(*LanguageError); !ok {
  1000. t.Error(fmt.Sprintf("(%s) %s", reflect.TypeOf(err), err))
  1001. }
  1002. _, err = testParser.ParseArgs("Usage: prog", []string{"-x"}, "")
  1003. if _, ok := err.(*UserError); !ok {
  1004. t.Error(err)
  1005. }
  1006. _, err = testParser.ParseArgs("Usage: prog -o\nOptions: -o ARG", []string{}, "")
  1007. if _, ok := err.(*LanguageError); !ok {
  1008. t.Error(err)
  1009. }
  1010. _, err = testParser.ParseArgs("Usage: prog -o ARG\nOptions: -o ARG", []string{"-o"}, "")
  1011. if _, ok := err.(*UserError); !ok {
  1012. t.Error(err)
  1013. }
  1014. }
  1015. func TestMatchingParen(t *testing.T) {
  1016. _, err := testParser.ParseArgs("Usage: prog [a [b]", []string{}, "")
  1017. if _, ok := err.(*LanguageError); !ok {
  1018. t.Error(err)
  1019. }
  1020. _, err = testParser.ParseArgs("Usage: prog [a [b] ] c )", []string{}, "")
  1021. if _, ok := err.(*LanguageError); !ok {
  1022. t.Error(err)
  1023. }
  1024. }
  1025. func TestAllowDoubleDash(t *testing.T) {
  1026. if v, err := testParser.ParseArgs("usage: prog [-o] [--] <arg>\noptions: -o", []string{"--", "-o"}, ""); reflect.DeepEqual(v, Opts{"-o": false, "<arg>": "-o", "--": true}) != true {
  1027. t.Error(err)
  1028. }
  1029. if v, err := testParser.ParseArgs("usage: prog [-o] [--] <arg>\noptions: -o", []string{"-o", "1"}, ""); reflect.DeepEqual(v, Opts{"-o": true, "<arg>": "1", "--": false}) != true {
  1030. t.Error(err)
  1031. }
  1032. _, err := testParser.ParseArgs("usage: prog [-o] <arg>\noptions:-o", []string{"-o"}, "")
  1033. if _, ok := err.(*UserError); !ok { //"--" is not allowed; FIXME?
  1034. t.Error(err)
  1035. }
  1036. }
  1037. func TestDocopt(t *testing.T) {
  1038. doc := `Usage: prog [-v] A
  1039. Options: -v Be verbose.`
  1040. if v, err := testParser.ParseArgs(doc, []string{"arg"}, ""); reflect.DeepEqual(v, Opts{"-v": false, "A": "arg"}) != true {
  1041. t.Error(err)
  1042. }
  1043. if v, err := testParser.ParseArgs(doc, []string{"-v", "arg"}, ""); reflect.DeepEqual(v, Opts{"-v": true, "A": "arg"}) != true {
  1044. t.Error(err)
  1045. }
  1046. doc = `Usage: prog [-vqr] [FILE]
  1047. prog INPUT OUTPUT
  1048. prog --help
  1049. Options:
  1050. -v print status messages
  1051. -q report only file names
  1052. -r show all occurrences of the same error
  1053. --help
  1054. `
  1055. if v, err := testParser.ParseArgs(doc, []string{"-v", "file.py"}, ""); reflect.DeepEqual(v, Opts{"-v": true, "-q": false, "-r": false, "--help": false, "FILE": "file.py", "INPUT": nil, "OUTPUT": nil}) != true {
  1056. t.Error(err)
  1057. }
  1058. if v, err := testParser.ParseArgs(doc, []string{"-v"}, ""); reflect.DeepEqual(v, Opts{"-v": true, "-q": false, "-r": false, "--help": false, "FILE": nil, "INPUT": nil, "OUTPUT": nil}) != true {
  1059. t.Error(err)
  1060. }
  1061. _, err := testParser.ParseArgs(doc, []string{"-v", "input.py", "output.py"}, "") // does not match
  1062. if _, ok := err.(*UserError); !ok {
  1063. t.Error(err)
  1064. }
  1065. _, err = testParser.ParseArgs(doc, []string{"--fake"}, "")
  1066. if _, ok := err.(*UserError); !ok {
  1067. t.Error(err)
  1068. }
  1069. _, output, err := parseOutput(doc, []string{"--hel"}, true, "", false)
  1070. if err != nil || len(output) == 0 {
  1071. t.Error(err)
  1072. }
  1073. }
  1074. func TestLanguageErrors(t *testing.T) {
  1075. _, err := testParser.ParseArgs("no usage with colon here", []string{}, "")
  1076. if _, ok := err.(*LanguageError); !ok {
  1077. t.Error(err)
  1078. }
  1079. _, err = testParser.ParseArgs("usage: here \n\n and again usage: here", []string{}, "")
  1080. if _, ok := err.(*LanguageError); !ok {
  1081. t.Error(err)
  1082. }
  1083. }
  1084. func TestIssue40(t *testing.T) {
  1085. _, output, err := parseOutput("usage: prog --help-commands | --help", []string{"--help"}, true, "", false)
  1086. if err != nil || len(output) == 0 {
  1087. t.Error(err)
  1088. }
  1089. if v, err := testParser.ParseArgs("usage: prog --aabb | --aa", []string{"--aa"}, ""); reflect.DeepEqual(v, Opts{"--aabb": false, "--aa": true}) != true {
  1090. t.Error(err)
  1091. }
  1092. }
  1093. func TestIssue34UnicodeStrings(t *testing.T) {
  1094. // TODO: see if applicable
  1095. }
  1096. func TestCountMultipleFlags(t *testing.T) {
  1097. if v, err := testParser.ParseArgs("usage: prog [-v]", []string{"-v"}, ""); reflect.DeepEqual(v, Opts{"-v": true}) != true {
  1098. t.Error(err)
  1099. }
  1100. if v, err := testParser.ParseArgs("usage: prog [-vv]", []string{}, ""); reflect.DeepEqual(v, Opts{"-v": 0}) != true {
  1101. t.Error(err)
  1102. }
  1103. if v, err := testParser.ParseArgs("usage: prog [-vv]", []string{"-v"}, ""); reflect.DeepEqual(v, Opts{"-v": 1}) != true {
  1104. t.Error(err)
  1105. }
  1106. if v, err := testParser.ParseArgs("usage: prog [-vv]", []string{"-vv"}, ""); reflect.DeepEqual(v, Opts{"-v": 2}) != true {
  1107. t.Error(err)
  1108. }
  1109. _, err := testParser.ParseArgs("usage: prog [-vv]", []string{"-vvv"}, "")
  1110. if _, ok := err.(*UserError); !ok {
  1111. t.Error(err)
  1112. }
  1113. if v, err := testParser.ParseArgs("usage: prog [-v | -vv | -vvv]", []string{"-vvv"}, ""); reflect.DeepEqual(v, Opts{"-v": 3}) != true {
  1114. t.Error(err)
  1115. }
  1116. if v, err := testParser.ParseArgs("usage: prog [-v...]", []string{"-vvvvvv"}, ""); reflect.DeepEqual(v, Opts{"-v": 6}) != true {
  1117. t.Error(err)
  1118. }
  1119. if v, err := testParser.ParseArgs("usage: prog [--ver --ver]", []string{"--ver", "--ver"}, ""); reflect.DeepEqual(v, Opts{"--ver": 2}) != true {
  1120. t.Error(err)
  1121. }
  1122. }
  1123. func TestAnyOptionsParameter(t *testing.T) {
  1124. _, err := testParser.ParseArgs("usage: prog [options]", []string{"-foo", "--bar", "--spam=eggs"}, "")
  1125. if _, ok := err.(*UserError); !ok {
  1126. t.Fail()
  1127. }
  1128. _, err = testParser.ParseArgs("usage: prog [options]", []string{"--foo", "--bar", "--bar"}, "")
  1129. if _, ok := err.(*UserError); !ok {
  1130. t.Fail()
  1131. }
  1132. _, err = testParser.ParseArgs("usage: prog [options]", []string{"--bar", "--bar", "--bar", "-ffff"}, "")
  1133. if _, ok := err.(*UserError); !ok {
  1134. t.Fail()
  1135. }
  1136. _, err = testParser.ParseArgs("usage: prog [options]", []string{"--long=arg", "--long=another"}, "")
  1137. if _, ok := err.(*UserError); !ok {
  1138. t.Fail()
  1139. }
  1140. }
  1141. func TestDefaultValueForPositionalArguments(t *testing.T) {
  1142. doc := "Usage: prog [--data=<data>...]\nOptions:\n\t-d --data=<arg> Input data [default: x]"
  1143. if v, err := testParser.ParseArgs(doc, []string{}, ""); reflect.DeepEqual(v, Opts{"--data": []string{"x"}}) != true {
  1144. t.Error(err)
  1145. }
  1146. doc = "Usage: prog [--data=<data>...]\nOptions:\n\t-d --data=<arg> Input data [default: x y]"
  1147. if v, err := testParser.ParseArgs(doc, []string{}, ""); reflect.DeepEqual(v, Opts{"--data": []string{"x", "y"}}) != true {
  1148. t.Error(err)
  1149. }
  1150. doc = "Usage: prog [--data=<data>...]\nOptions:\n\t-d --data=<arg> Input data [default: x y]"
  1151. if v, err := testParser.ParseArgs(doc, []string{"--data=this"}, ""); reflect.DeepEqual(v, Opts{"--data": []string{"this"}}) != true {
  1152. t.Error(err)
  1153. }
  1154. }
  1155. func TestIssue59(t *testing.T) {
  1156. if v, err := testParser.ParseArgs("usage: prog --long=<a>", []string{"--long="}, ""); reflect.DeepEqual(v, Opts{"--long": ""}) != true {
  1157. t.Error(err)
  1158. }
  1159. if v, err := testParser.ParseArgs("usage: prog -l <a>\noptions: -l <a>", []string{"-l", ""}, ""); reflect.DeepEqual(v, Opts{"-l": ""}) != true {
  1160. t.Error(err)
  1161. }
  1162. }
  1163. func TestOptionsFirst(t *testing.T) {
  1164. if v, err := testParser.ParseArgs("usage: prog [--opt] [<args>...]", []string{"--opt", "this", "that"}, ""); reflect.DeepEqual(v, Opts{"--opt": true, "<args>": []string{"this", "that"}}) != true {
  1165. t.Error(err)
  1166. }
  1167. if v, err := testParser.ParseArgs("usage: prog [--opt] [<args>...]", []string{"this", "that", "--opt"}, ""); reflect.DeepEqual(v, Opts{"--opt": true, "<args>": []string{"this", "that"}}) != true {
  1168. t.Error(err)
  1169. }
  1170. optFirstParser := &Parser{HelpHandler: PrintHelpOnly, OptionsFirst: true}
  1171. if v, err := optFirstParser.ParseArgs("usage: prog [--opt] [<args>...]", []string{"this", "that", "--opt"}, ""); reflect.DeepEqual(v, Opts{"--opt": false, "<args>": []string{"this", "that", "--opt"}}) != true {
  1172. t.Error(err)
  1173. }
  1174. }
  1175. func TestIssue68OptionsShortcutDoesNotIncludeOptionsInUsagePattern(t *testing.T) {
  1176. args, err := testParser.ParseArgs("usage: prog [-ab] [options]\noptions: -x\n -y", []string{"-ax"}, "")
  1177. if args["-a"] != true {
  1178. t.Error(err)
  1179. }
  1180. if args["-b"] != false {
  1181. t.Error(err)
  1182. }
  1183. if args["-x"] != true {
  1184. t.Error(err)
  1185. }
  1186. if args["-y"] != false {
  1187. t.Error(err)
  1188. }
  1189. }
  1190. func TestIssue65EvaluateArgvWhenCalledNotWhenImported(t *testing.T) {
  1191. os.Args = strings.Fields("prog -a")
  1192. v, err := testParser.ParseArgs("usage: prog [-ab]", nil, "")
  1193. w := Opts{"-a": true, "-b": false}
  1194. if reflect.DeepEqual(v, w) != true {
  1195. t.Error(err)
  1196. }
  1197. os.Args = strings.Fields("prog -b")
  1198. v, err = testParser.ParseArgs("usage: prog [-ab]", nil, "")
  1199. w = Opts{"-a": false, "-b": true}
  1200. if reflect.DeepEqual(v, w) != true {
  1201. t.Error(err)
  1202. }
  1203. }
  1204. func TestIssue71DoubleDashIsNotAValidOptionArgument(t *testing.T) {
  1205. _, err := testParser.ParseArgs("usage: prog [--log=LEVEL] [--] <args>...", []string{"--log", "--", "1", "2"}, "")
  1206. if _, ok := err.(*UserError); !ok {
  1207. t.Fail()
  1208. }
  1209. _, err = testParser.ParseArgs(`usage: prog [-l LEVEL] [--] <args>...
  1210. options: -l LEVEL`, []string{"-l", "--", "1", "2"}, "")
  1211. if _, ok := err.(*UserError); !ok {
  1212. t.Fail()
  1213. }
  1214. }
  1215. func TestParseSection(t *testing.T) {
  1216. v := parseSection("usage:", "foo bar fizz buzz")
  1217. w := []string{}
  1218. if reflect.DeepEqual(v, w) != true {
  1219. t.Fail()
  1220. }
  1221. v = parseSection("usage:", "usage: prog")
  1222. w = []string{"usage: prog"}
  1223. if reflect.DeepEqual(v, w) != true {
  1224. t.Fail()
  1225. }
  1226. v = parseSection("usage:", "usage: -x\n -y")
  1227. w = []string{"usage: -x\n -y"}
  1228. if reflect.DeepEqual(v, w) != true {
  1229. t.Fail()
  1230. }
  1231. usage := `usage: this
  1232. usage:hai
  1233. usage: this that
  1234. usage: foo
  1235. bar
  1236. PROGRAM USAGE:
  1237. foo
  1238. bar
  1239. usage:
  1240. ` + "\t" + `too
  1241. ` + "\t" + `tar
  1242. Usage: eggs spam
  1243. BAZZ
  1244. usage: pit stop`
  1245. v = parseSection("usage:", usage)
  1246. w = []string{"usage: this",
  1247. "usage:hai",
  1248. "usage: this that",
  1249. "usage: foo\n bar",
  1250. "PROGRAM USAGE:\n foo\n bar",
  1251. "usage:\n\ttoo\n\ttar",
  1252. "Usage: eggs spam",
  1253. "usage: pit stop",
  1254. }
  1255. if reflect.DeepEqual(v, w) != true {
  1256. t.Fail()
  1257. }
  1258. }
  1259. func TestIssue126DefaultsNotParsedCorrectlyWhenTabs(t *testing.T) {
  1260. section := "Options:\n\t--foo=<arg> [default: bar]"
  1261. v := patternList{newOption("", "--foo", 1, "bar")}
  1262. if reflect.DeepEqual(parseDefaults(section), v) != true {
  1263. t.Fail()
  1264. }
  1265. }
  1266. // conf file based test cases
  1267. func TestFileTestcases(t *testing.T) {
  1268. filenames := []string{"testcases.docopt", "test_golang.docopt"}
  1269. for _, filename := range filenames {
  1270. raw, err := ioutil.ReadFile(filename)
  1271. if err != nil {
  1272. t.Fatal(err)
  1273. }
  1274. tests, err := parseTest(raw)
  1275. if err != nil {
  1276. t.Fatal(err)
  1277. }
  1278. for _, c := range tests {
  1279. result, err := testParser.ParseArgs(c.doc, c.argv, "")
  1280. if _, ok := err.(*UserError); c.userError && !ok {
  1281. // expected a user-error
  1282. t.Error("testcase:", c.id, "result:", result)
  1283. } else if _, ok := err.(*UserError); !c.userError && ok {
  1284. // unexpected user-error
  1285. t.Error("testcase:", c.id, "error:", err, "result:", result)
  1286. } else if reflect.DeepEqual(c.expect, result) != true {
  1287. t.Error("testcase:", c.id, "result:", result, "expect:", c.expect)
  1288. }
  1289. }
  1290. }
  1291. }
  1292. type testcase struct {
  1293. id int
  1294. doc string
  1295. prog string
  1296. argv []string
  1297. expect Opts
  1298. userError bool
  1299. }
  1300. func parseTest(raw []byte) ([]testcase, error) {
  1301. var res []testcase
  1302. commentPattern := regexp.MustCompile("#.*")
  1303. raw = commentPattern.ReplaceAll(raw, []byte(""))
  1304. raw = bytes.TrimSpace(raw)
  1305. if bytes.HasPrefix(raw, []byte(`"""`)) {
  1306. raw = raw[3:]
  1307. }
  1308. id := 0
  1309. for _, fixture := range bytes.Split(raw, []byte(`r"""`)) {
  1310. doc, _, body := stringPartition(string(fixture), `"""`)
  1311. for _, cas := range strings.Split(body, "$")[1:] {
  1312. argvString, _, expectString := stringPartition(strings.TrimSpace(cas), "\n")
  1313. prog, _, argvString := stringPartition(strings.TrimSpace(argvString), " ")
  1314. argv := []string{}
  1315. if len(argvString) > 0 {
  1316. argv = strings.Fields(argvString)
  1317. }
  1318. var expectUntyped interface{}
  1319. err := json.Unmarshal([]byte(expectString), &expectUntyped)
  1320. if err != nil {
  1321. return nil, err
  1322. }
  1323. switch expect := expectUntyped.(type) {
  1324. case string: // user-error
  1325. res = append(res, testcase{id, doc, prog, argv, nil, true})
  1326. case map[string]interface{}:
  1327. // convert []interface{} values to []string
  1328. // convert float64 values to int
  1329. for k, vUntyped := range expect {
  1330. switch v := vUntyped.(type) {
  1331. case []interface{}:
  1332. itemList := make([]string, len(v))
  1333. for i, itemUntyped := range v {
  1334. if item, ok := itemUntyped.(string); ok {
  1335. itemList[i] = item
  1336. }
  1337. }
  1338. expect[k] = itemList
  1339. case float64:
  1340. expect[k] = int(v)
  1341. }
  1342. }
  1343. res = append(res, testcase{id, doc, prog, argv, expect, false})
  1344. default:
  1345. return nil, fmt.Errorf("unhandled json data type")
  1346. }
  1347. id++
  1348. }
  1349. }
  1350. return res, nil
  1351. }
  1352. // parseOutput uses a custom parser which also returns the output
  1353. func parseOutput(doc string, argv []string, help bool, version string, optionsFirst bool) (Opts, string, error) {
  1354. var output string
  1355. p := &Parser{
  1356. HelpHandler: func(err error, usage string) { output = usage },
  1357. OptionsFirst: optionsFirst,
  1358. SkipHelpFlags: !help,
  1359. }
  1360. args, err := p.ParseArgs(doc, argv, version)
  1361. return args, output, err
  1362. }
  1363. var debugEnabled = false
  1364. func debugOn(l ...interface{}) {
  1365. debugEnabled = true
  1366. debug(l...)
  1367. }
  1368. func debugOff(l ...interface{}) {
  1369. debug(l...)
  1370. debugEnabled = false
  1371. }
  1372. func debug(l ...interface{}) {
  1373. if debugEnabled {
  1374. fmt.Println(l...)
  1375. }
  1376. }