| /* |
| Based of off docopt.py: https://github.com/docopt/docopt |
| |
| Licensed under terms of MIT license (see LICENSE-MIT) |
| Copyright (c) 2013 Keith Batten, kbatten@gmail.com |
| */ |
| |
| package docopt |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "fmt" |
| "io" |
| "io/ioutil" |
| "os" |
| "reflect" |
| "regexp" |
| "strings" |
| "testing" |
| ) |
| |
| func TestPatternFlat(t *testing.T) { |
| q := patternList{ |
| newArgument("N", nil), |
| newOption("-a", "", 0, false), |
| newArgument("M", nil)} |
| p, err := newRequired( |
| newOneOrMore(newArgument("N", nil)), |
| newOption("-a", "", 0, false), |
| newArgument("M", nil)).flat(patternDefault) |
| if reflect.DeepEqual(p, q) != true { |
| t.Error(err) |
| } |
| |
| q = patternList{newOptionsShortcut()} |
| p, err = newRequired( |
| newOptional(newOptionsShortcut()), |
| newOptional(newOption("-a", "", 0, false))).flat(patternOptionSSHORTCUT) |
| if reflect.DeepEqual(p, q) != true { |
| t.Error(err) |
| } |
| return |
| } |
| |
| func TestOption(t *testing.T) { |
| if !parseOption("-h").eq(newOption("-h", "", 0, false)) { |
| t.Error() |
| } |
| if !parseOption("--help").eq(newOption("", "--help", 0, false)) { |
| t.Error() |
| } |
| if !parseOption("-h --help").eq(newOption("-h", "--help", 0, false)) { |
| t.Error() |
| } |
| if !parseOption("-h, --help").eq(newOption("-h", "--help", 0, false)) { |
| t.Error() |
| } |
| |
| if !parseOption("-h TOPIC").eq(newOption("-h", "", 1, false)) { |
| t.Error() |
| } |
| if !parseOption("--help TOPIC").eq(newOption("", "--help", 1, false)) { |
| t.Error() |
| } |
| if !parseOption("-h TOPIC --help TOPIC").eq(newOption("-h", "--help", 1, false)) { |
| t.Error() |
| } |
| if !parseOption("-h TOPIC, --help TOPIC").eq(newOption("-h", "--help", 1, false)) { |
| t.Error() |
| } |
| if !parseOption("-h TOPIC, --help=TOPIC").eq(newOption("-h", "--help", 1, false)) { |
| t.Error() |
| } |
| |
| if !parseOption("-h Description...").eq(newOption("-h", "", 0, false)) { |
| t.Error() |
| } |
| if !parseOption("-h --help Description...").eq(newOption("-h", "--help", 0, false)) { |
| t.Error() |
| } |
| if !parseOption("-h TOPIC Description...").eq(newOption("-h", "", 1, false)) { |
| t.Error() |
| } |
| |
| if !parseOption(" -h").eq(newOption("-h", "", 0, false)) { |
| t.Error() |
| } |
| |
| if !parseOption("-h TOPIC Description... [default: 2]").eq(newOption("-h", "", 1, "2")) { |
| t.Error() |
| } |
| if !parseOption("-h TOPIC Descripton... [default: topic-1]").eq(newOption("-h", "", 1, "topic-1")) { |
| t.Error() |
| } |
| if !parseOption("--help=TOPIC ... [default: 3.14]").eq(newOption("", "--help", 1, "3.14")) { |
| t.Error() |
| } |
| if !parseOption("-h, --help=DIR ... [default: ./]").eq(newOption("-h", "--help", 1, "./")) { |
| t.Error() |
| } |
| if !parseOption("-h TOPIC Descripton... [dEfAuLt: 2]").eq(newOption("-h", "", 1, "2")) { |
| t.Error() |
| } |
| return |
| } |
| |
| func TestOptionName(t *testing.T) { |
| if newOption("-h", "", 0, false).name != "-h" { |
| t.Error() |
| } |
| if newOption("-h", "--help", 0, false).name != "--help" { |
| t.Error() |
| } |
| if newOption("", "--help", 0, false).name != "--help" { |
| t.Error() |
| } |
| return |
| } |
| |
| func TestCommands(t *testing.T) { |
| if v, err := Parse("Usage: prog add", []string{"add"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"add": true}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("Usage: prog [add]", []string{}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"add": false}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("Usage: prog [add]", []string{"add"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"add": true}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("Usage: prog (add|rm)", []string{"add"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"add": true, "rm": false}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("Usage: prog (add|rm)", []string{"rm"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"add": false, "rm": true}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("Usage: prog a b", []string{"a", "b"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"a": true, "b": true}) != true { |
| t.Error(err) |
| } |
| _, err := Parse("Usage: prog a b", []string{"b", "a"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error(err) |
| } |
| return |
| } |
| |
| func TestFormalUsage(t *testing.T) { |
| doc := ` |
| Usage: prog [-hv] ARG |
| prog N M |
| |
| prog is a program` |
| usage := parseSection("usage:", doc)[0] |
| if usage != "Usage: prog [-hv] ARG\n prog N M" { |
| t.Fatal() |
| } |
| formal, err := formalUsage(usage) |
| if err != nil { |
| t.Fatal(err) |
| } |
| if formal != "( [-hv] ARG ) | ( N M )" { |
| t.Error() |
| } |
| return |
| } |
| |
| func TestParseArgv(t *testing.T) { |
| o := patternList{ |
| newOption("-h", "", 0, false), |
| newOption("-v", "--verbose", 0, false), |
| newOption("-f", "--file", 1, false), |
| } |
| |
| p, err := parseArgv(tokenListFromString(""), &o, false) |
| q := patternList{} |
| if reflect.DeepEqual(p, q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parseArgv(tokenListFromString("-h"), &o, false) |
| q = patternList{newOption("-h", "", 0, true)} |
| if reflect.DeepEqual(p, q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parseArgv(tokenListFromString("-h --verbose"), &o, false) |
| q = patternList{ |
| newOption("-h", "", 0, true), |
| newOption("-v", "--verbose", 0, true), |
| } |
| if reflect.DeepEqual(p, q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parseArgv(tokenListFromString("-h --file f.txt"), &o, false) |
| q = patternList{ |
| newOption("-h", "", 0, true), |
| newOption("-f", "--file", 1, "f.txt"), |
| } |
| if reflect.DeepEqual(p, q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parseArgv(tokenListFromString("-h --file f.txt arg"), &o, false) |
| q = patternList{ |
| newOption("-h", "", 0, true), |
| newOption("-f", "--file", 1, "f.txt"), |
| newArgument("", "arg"), |
| } |
| if reflect.DeepEqual(p, q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parseArgv(tokenListFromString("-h --file f.txt arg arg2"), &o, false) |
| q = patternList{ |
| newOption("-h", "", 0, true), |
| newOption("-f", "--file", 1, "f.txt"), |
| newArgument("", "arg"), |
| newArgument("", "arg2"), |
| } |
| if reflect.DeepEqual(p, q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parseArgv(tokenListFromString("-h arg -- -v"), &o, false) |
| q = patternList{ |
| newOption("-h", "", 0, true), |
| newArgument("", "arg"), |
| newArgument("", "--"), |
| newArgument("", "-v"), |
| } |
| if reflect.DeepEqual(p, q) != true { |
| t.Error(err) |
| } |
| } |
| |
| func TestParsePattern(t *testing.T) { |
| o := patternList{ |
| newOption("-h", "", 0, false), |
| newOption("-v", "--verbose", 0, false), |
| newOption("-f", "--file", 1, false), |
| } |
| |
| p, err := parsePattern("[ -h ]", &o) |
| q := newRequired(newOptional(newOption("-h", "", 0, false))) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("[ ARG ... ]", &o) |
| q = newRequired(newOptional( |
| newOneOrMore( |
| newArgument("ARG", nil)))) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("[ -h | -v ]", &o) |
| q = newRequired( |
| newOptional( |
| newEither( |
| newOption("-h", "", 0, false), |
| newOption("-v", "--verbose", 0, false)))) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("( -h | -v [ --file <f> ] )", &o) |
| q = newRequired( |
| newRequired( |
| newEither( |
| newOption("-h", "", 0, false), |
| newRequired( |
| newOption("-v", "--verbose", 0, false), |
| newOptional( |
| newOption("-f", "--file", 1, nil)))))) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("(-h|-v[--file=<f>]N...)", &o) |
| q = newRequired( |
| newRequired( |
| newEither( |
| newOption("-h", "", 0, false), |
| newRequired( |
| newOption("-v", "--verbose", 0, false), |
| newOptional( |
| newOption("-f", "--file", 1, nil)), |
| newOneOrMore( |
| newArgument("N", nil)))))) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("(N [M | (K | L)] | O P)", &o) |
| q = newRequired( |
| newRequired( |
| newEither( |
| newRequired( |
| newArgument("N", nil), |
| newOptional( |
| newEither( |
| newArgument("M", nil), |
| newRequired( |
| newEither( |
| newArgument("K", nil), |
| newArgument("L", nil)))))), |
| newRequired( |
| newArgument("O", nil), |
| newArgument("P", nil))))) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("[ -h ] [N]", &o) |
| q = newRequired( |
| newOptional( |
| newOption("-h", "", 0, false)), |
| newOptional( |
| newArgument("N", nil))) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("[options]", &o) |
| q = newRequired( |
| newOptional( |
| newOptionsShortcut())) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("[options] A", &o) |
| q = newRequired( |
| newOptional( |
| newOptionsShortcut()), |
| newArgument("A", nil)) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("-v [options]", &o) |
| q = newRequired( |
| newOption("-v", "--verbose", 0, false), |
| newOptional( |
| newOptionsShortcut())) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("ADD", &o) |
| q = newRequired(newArgument("ADD", nil)) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("<add>", &o) |
| q = newRequired(newArgument("<add>", nil)) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| |
| p, err = parsePattern("add", &o) |
| q = newRequired(newCommand("add", false)) |
| if p.eq(q) != true { |
| t.Error(err) |
| } |
| } |
| |
| func TestOptionMatch(t *testing.T) { |
| v, w, x := newOption("-a", "", 0, false).match( |
| &patternList{newOption("-a", "", 0, true)}, nil) |
| y := patternList{newOption("-a", "", 0, true)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOption("-a", "", 0, false).match( |
| &patternList{newOption("-x", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOption("-a", "", 0, false).match( |
| &patternList{newOption("-x", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| v, w, x = newOption("-a", "", 0, false).match( |
| &patternList{newArgument("N", nil)}, nil) |
| y = patternList{newArgument("N", nil)} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOption("-a", "", 0, false).match( |
| &patternList{ |
| newOption("-x", "", 0, false), |
| newOption("-a", "", 0, false), |
| newArgument("N", nil)}, nil) |
| y = patternList{ |
| newOption("-x", "", 0, false), |
| newArgument("N", nil)} |
| z := patternList{newOption("-a", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOption("-a", "", 0, false).match( |
| &patternList{ |
| newOption("-a", "", 0, true), |
| newOption("-a", "", 0, false)}, nil) |
| y = patternList{newOption("-a", "", 0, false)} |
| z = patternList{newOption("-a", "", 0, true)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| } |
| |
| func TestArgumentMatch(t *testing.T) { |
| v, w, x := newArgument("N", nil).match( |
| &patternList{newArgument("N", 9)}, nil) |
| y := patternList{newArgument("N", 9)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newArgument("N", nil).match( |
| &patternList{newOption("-x", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| |
| v, w, x = newArgument("N", nil).match( |
| &patternList{newOption("-x", "", 0, false), |
| newOption("-a", "", 0, false), |
| newArgument("", 5)}, nil) |
| y = patternList{newOption("-x", "", 0, false), |
| newOption("-a", "", 0, false)} |
| z := patternList{newArgument("N", 5)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newArgument("N", nil).match( |
| &patternList{newArgument("", 9), |
| newArgument("", 0)}, nil) |
| y = patternList{newArgument("", 0)} |
| z = patternList{newArgument("N", 9)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| } |
| |
| func TestCommandMatch(t *testing.T) { |
| v, w, x := newCommand("c", false).match( |
| &patternList{newArgument("", "c")}, nil) |
| y := patternList{newCommand("c", true)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newCommand("c", false).match( |
| &patternList{newOption("-x", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| |
| v, w, x = newCommand("c", false).match( |
| &patternList{ |
| newOption("-x", "", 0, false), |
| newOption("-a", "", 0, false), |
| newArgument("", "c")}, nil) |
| y = patternList{newOption("-x", "", 0, false), |
| newOption("-a", "", 0, false)} |
| z := patternList{newCommand("c", true)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newEither( |
| newCommand("add", false), |
| newCommand("rm", false)).match( |
| &patternList{newArgument("", "rm")}, nil) |
| y = patternList{newCommand("rm", true)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| } |
| |
| func TestOptionalMatch(t *testing.T) { |
| v, w, x := newOptional(newOption("-a", "", 0, false)).match( |
| &patternList{newOption("-a", "", 0, false)}, nil) |
| y := patternList{newOption("-a", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOptional(newOption("-a", "", 0, false)).match( |
| &patternList{}, nil) |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOptional(newOption("-a", "", 0, false)).match( |
| &patternList{newOption("-x", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOptional(newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)).match( |
| &patternList{newOption("-a", "", 0, false)}, nil) |
| y = patternList{newOption("-a", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOptional(newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)).match( |
| &patternList{newOption("-b", "", 0, false)}, nil) |
| y = patternList{newOption("-b", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOptional(newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)).match( |
| &patternList{newOption("-x", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOptional(newArgument("N", nil)).match( |
| &patternList{newArgument("", 9)}, nil) |
| y = patternList{newArgument("N", 9)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOptional(newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)).match( |
| &patternList{newOption("-b", "", 0, false), |
| newOption("-x", "", 0, false), |
| newOption("-a", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| z := patternList{newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| } |
| |
| func TestRequiredMatch(t *testing.T) { |
| v, w, x := newRequired(newOption("-a", "", 0, false)).match( |
| &patternList{newOption("-a", "", 0, false)}, nil) |
| y := patternList{newOption("-a", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newRequired(newOption("-a", "", 0, false)).match(&patternList{}, nil) |
| if v != false || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| |
| v, w, x = newRequired(newOption("-a", "", 0, false)).match( |
| &patternList{newOption("-x", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| v, w, x = newRequired(newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)).match( |
| &patternList{newOption("-a", "", 0, false)}, nil) |
| y = patternList{newOption("-a", "", 0, false)} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, patternList{}) != true { |
| t.Error() |
| } |
| } |
| |
| func TestEitherMatch(t *testing.T) { |
| v, w, x := newEither( |
| newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)).match( |
| &patternList{newOption("-a", "", 0, false)}, nil) |
| y := patternList{newOption("-a", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newEither( |
| newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)).match(&patternList{ |
| newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)}, nil) |
| y = patternList{newOption("-b", "", 0, false)} |
| z := patternList{newOption("-a", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newEither( |
| newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)).match(&patternList{ |
| newOption("-x", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| z = patternList{} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newEither( |
| newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false), |
| newOption("-c", "", 0, false)).match(&patternList{ |
| newOption("-x", "", 0, false), |
| newOption("-b", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| z = patternList{newOption("-b", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| v, w, x = newEither( |
| newArgument("M", nil), |
| newRequired(newArgument("N", nil), |
| newArgument("M", nil))).match(&patternList{ |
| newArgument("", 1), |
| newArgument("", 2)}, nil) |
| y = patternList{} |
| z = patternList{newArgument("N", 1), newArgument("M", 2)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| } |
| |
| func TestOneOrMoreMatch(t *testing.T) { |
| v, w, x := newOneOrMore(newArgument("N", nil)).match( |
| &patternList{newArgument("", 9)}, nil) |
| y := patternList{newArgument("N", 9)} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOneOrMore(newArgument("N", nil)).match( |
| &patternList{}, nil) |
| y = patternList{} |
| z := patternList{} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOneOrMore(newArgument("N", nil)).match( |
| &patternList{newOption("-x", "", 0, false)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| z = patternList{} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOneOrMore(newArgument("N", nil)).match( |
| &patternList{newArgument("", 9), newArgument("", 8)}, nil) |
| y = patternList{} |
| z = patternList{newArgument("N", 9), newArgument("N", 8)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOneOrMore(newArgument("N", nil)).match(&patternList{ |
| newArgument("", 9), |
| newOption("-x", "", 0, false), |
| newArgument("", 8)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| z = patternList{newArgument("N", 9), newArgument("N", 8)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOneOrMore(newOption("-a", "", 0, false)).match(&patternList{ |
| newOption("-a", "", 0, false), |
| newArgument("", 8), |
| newOption("-a", "", 0, false)}, nil) |
| y = patternList{newArgument("", 8)} |
| z = patternList{newOption("-a", "", 0, false), newOption("-a", "", 0, false)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOneOrMore(newOption("-a", "", 0, false)).match(&patternList{ |
| newArgument("", 8), |
| newOption("-x", "", 0, false)}, nil) |
| y = patternList{newArgument("", 8), newOption("-x", "", 0, false)} |
| z = patternList{} |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOneOrMore(newRequired(newOption("-a", "", 0, false), |
| newArgument("N", nil))).match(&patternList{ |
| newOption("-a", "", 0, false), |
| newArgument("", 1), |
| newOption("-x", "", 0, false), |
| newOption("-a", "", 0, false), |
| newArgument("", 2)}, nil) |
| y = patternList{newOption("-x", "", 0, false)} |
| z = patternList{newOption("-a", "", 0, false), |
| newArgument("N", 1), |
| newOption("-a", "", 0, false), |
| newArgument("N", 2)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| v, w, x = newOneOrMore(newOptional(newArgument("N", nil))).match( |
| &patternList{newArgument("", 9)}, nil) |
| y = patternList{} |
| z = patternList{newArgument("N", 9)} |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| } |
| |
| func TestListArgumentMatch(t *testing.T) { |
| p := newRequired( |
| newArgument("N", nil), |
| newArgument("N", nil)) |
| p.fix() |
| v, w, x := p.match(&patternList{newArgument("", "1"), |
| newArgument("", "2")}, nil) |
| y := patternList{newArgument("N", []string{"1", "2"})} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| p = newOneOrMore(newArgument("N", nil)) |
| p.fix() |
| v, w, x = p.match(&patternList{newArgument("", "1"), |
| newArgument("", "2"), newArgument("", "3")}, nil) |
| y = patternList{newArgument("N", []string{"1", "2", "3"})} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| p = newRequired(newArgument("N", nil), |
| newOneOrMore(newArgument("N", nil))) |
| p.fix() |
| v, w, x = p.match(&patternList{ |
| newArgument("", "1"), |
| newArgument("", "2"), |
| newArgument("", "3")}, nil) |
| y = patternList{newArgument("N", []string{"1", "2", "3"})} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| p = newRequired(newArgument("N", nil), |
| newRequired(newArgument("N", nil))) |
| p.fix() |
| v, w, x = p.match(&patternList{ |
| newArgument("", "1"), |
| newArgument("", "2")}, nil) |
| y = patternList{newArgument("N", []string{"1", "2"})} |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| } |
| |
| func TestBasicPatternMatching(t *testing.T) { |
| // ( -a N [ -x Z ] ) |
| p := newRequired( |
| newOption("-a", "", 0, false), |
| newArgument("N", nil), |
| newOptional( |
| newOption("-x", "", 0, false), |
| newArgument("Z", nil))) |
| |
| // -a N |
| q := patternList{newOption("-a", "", 0, false), newArgument("", 9)} |
| y := patternList{newOption("-a", "", 0, false), newArgument("N", 9)} |
| v, w, x := p.match(&q, nil) |
| if v != true || |
| reflect.DeepEqual(*w, patternList{}) != true || |
| reflect.DeepEqual(*x, y) != true { |
| t.Error() |
| } |
| |
| // -a -x N Z |
| q = patternList{newOption("-a", "", 0, false), |
| newOption("-x", "", 0, false), |
| newArgument("", 9), newArgument("", 5)} |
| y = patternList{} |
| z := patternList{newOption("-a", "", 0, false), newArgument("N", 9), |
| newOption("-x", "", 0, false), newArgument("Z", 5)} |
| v, w, x = p.match(&q, nil) |
| if v != true || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| |
| // -x N Z # BZZ! |
| q = patternList{newOption("-x", "", 0, false), |
| newArgument("", 9), newArgument("", 5)} |
| y = patternList{newOption("-x", "", 0, false), |
| newArgument("", 9), newArgument("", 5)} |
| z = patternList{} |
| v, w, x = p.match(&q, nil) |
| if v != false || |
| reflect.DeepEqual(*w, y) != true || |
| reflect.DeepEqual(*x, z) != true { |
| t.Error() |
| } |
| } |
| |
| func TestPatternEither(t *testing.T) { |
| p := newOption("-a", "", 0, false).transform() |
| q := newEither(newRequired( |
| newOption("-a", "", 0, false))) |
| if p.eq(q) != true { |
| t.Error() |
| } |
| |
| p = newArgument("A", nil).transform() |
| q = newEither(newRequired( |
| newArgument("A", nil))) |
| if p.eq(q) != true { |
| t.Error() |
| } |
| |
| p = newRequired( |
| newEither( |
| newOption("-a", "", 0, false), |
| newOption("-b", "", 0, false)), |
| newOption("-c", "", 0, false)).transform() |
| q = newEither( |
| newRequired( |
| newOption("-a", "", 0, false), |
| newOption("-c", "", 0, false)), |
| newRequired( |
| newOption("-b", "", 0, false), |
| newOption("-c", "", 0, false))) |
| if p.eq(q) != true { |
| t.Error() |
| } |
| |
| p = newOptional(newOption("-a", "", 0, false), |
| newEither(newOption("-b", "", 0, false), |
| newOption("-c", "", 0, false))).transform() |
| q = newEither( |
| newRequired( |
| newOption("-b", "", 0, false), newOption("-a", "", 0, false)), |
| newRequired( |
| newOption("-c", "", 0, false), newOption("-a", "", 0, false))) |
| if p.eq(q) != true { |
| t.Error() |
| } |
| |
| p = newEither(newOption("-x", "", 0, false), |
| newEither(newOption("-y", "", 0, false), |
| newOption("-z", "", 0, false))).transform() |
| q = newEither( |
| newRequired(newOption("-x", "", 0, false)), |
| newRequired(newOption("-y", "", 0, false)), |
| newRequired(newOption("-z", "", 0, false))) |
| if p.eq(q) != true { |
| t.Error() |
| } |
| |
| p = newOneOrMore(newArgument("N", nil), |
| newArgument("M", nil)).transform() |
| q = newEither( |
| newRequired(newArgument("N", nil), newArgument("M", nil), |
| newArgument("N", nil), newArgument("M", nil))) |
| if p.eq(q) != true { |
| t.Error() |
| } |
| } |
| |
| func TestPatternFixRepeatingArguments(t *testing.T) { |
| p := newOption("-a", "", 0, false) |
| p.fixRepeatingArguments() |
| if p.eq(newOption("-a", "", 0, false)) != true { |
| t.Error() |
| } |
| |
| p = newArgument("N", nil) |
| p.fixRepeatingArguments() |
| if p.eq(newArgument("N", nil)) != true { |
| t.Error() |
| } |
| |
| p = newRequired( |
| newArgument("N", nil), |
| newArgument("N", nil)) |
| q := newRequired( |
| newArgument("N", []string{}), |
| newArgument("N", []string{})) |
| p.fixRepeatingArguments() |
| if p.eq(q) != true { |
| t.Error() |
| } |
| |
| p = newEither( |
| newArgument("N", nil), |
| newOneOrMore(newArgument("N", nil))) |
| q = newEither( |
| newArgument("N", []string{}), |
| newOneOrMore(newArgument("N", []string{}))) |
| p.fix() |
| if p.eq(q) != true { |
| t.Error() |
| } |
| } |
| |
| func TestSet(t *testing.T) { |
| p := newArgument("N", nil) |
| q := newArgument("N", nil) |
| if reflect.DeepEqual(p, q) != true { |
| t.Error() |
| } |
| pl := patternList{newArgument("N", nil), newArgument("N", nil)} |
| ql := patternList{newArgument("N", nil)} |
| if reflect.DeepEqual(pl.unique(), ql.unique()) != true { |
| t.Error() |
| } |
| } |
| |
| func TestPatternFixIdentities1(t *testing.T) { |
| p := newRequired( |
| newArgument("N", nil), |
| newArgument("N", nil)) |
| if len(p.children) < 2 { |
| t.Fatal() |
| } |
| if p.children[0].eq(p.children[1]) != true { |
| t.Error() |
| } |
| if p.children[0] == p.children[1] { |
| t.Error() |
| } |
| p.fixIdentities(nil) |
| if p.children[0] != p.children[1] { |
| t.Error() |
| } |
| } |
| |
| func TestPatternFixIdentities2(t *testing.T) { |
| p := newRequired( |
| newOptional( |
| newArgument("X", nil), |
| newArgument("N", nil)), |
| newArgument("N", nil)) |
| if len(p.children) < 2 { |
| t.Fatal() |
| } |
| if len(p.children[0].children) < 2 { |
| t.Fatal() |
| } |
| if p.children[0].children[1].eq(p.children[1]) != true { |
| t.Error() |
| } |
| if p.children[0].children[1] == p.children[1] { |
| t.Error() |
| } |
| p.fixIdentities(nil) |
| if p.children[0].children[1] != p.children[1] { |
| t.Error() |
| } |
| } |
| |
| func TestLongOptionsErrorHandling(t *testing.T) { |
| _, err := Parse("Usage: prog", []string{"--non-existent"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error(fmt.Sprintf("(%s) %s", reflect.TypeOf(err), err)) |
| } |
| _, err = Parse("Usage: prog [--version --verbose]\nOptions: --version\n --verbose", |
| []string{"--ver"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error(err) |
| } |
| _, err = Parse("Usage: prog --long\nOptions: --long ARG", []string{}, true, "", false, false) |
| if _, ok := err.(*LanguageError); !ok { |
| t.Error(err) |
| } |
| _, err = Parse("Usage: prog --long ARG\nOptions: --long ARG", |
| []string{"--long"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error(fmt.Sprintf("(%s) %s", reflect.TypeOf(err), err)) |
| } |
| _, err = Parse("Usage: prog --long=ARG\nOptions: --long", []string{}, true, "", false, false) |
| if _, ok := err.(*LanguageError); !ok { |
| t.Error(err) |
| } |
| _, err = Parse("Usage: prog --long\nOptions: --long", |
| []string{}, true, "--long=ARG", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error(err) |
| } |
| } |
| |
| func TestShortOptionsErrorHandling(t *testing.T) { |
| _, err := Parse("Usage: prog -x\nOptions: -x this\n -x that", []string{}, true, "", false, false) |
| if _, ok := err.(*LanguageError); !ok { |
| t.Error(fmt.Sprintf("(%s) %s", reflect.TypeOf(err), err)) |
| } |
| _, err = Parse("Usage: prog", []string{"-x"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error(err) |
| } |
| _, err = Parse("Usage: prog -o\nOptions: -o ARG", []string{}, true, "", false, false) |
| if _, ok := err.(*LanguageError); !ok { |
| t.Error(err) |
| } |
| _, err = Parse("Usage: prog -o ARG\nOptions: -o ARG", []string{"-o"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error(err) |
| } |
| } |
| |
| func TestMatchingParen(t *testing.T) { |
| _, err := Parse("Usage: prog [a [b]", []string{}, true, "", false, false) |
| if _, ok := err.(*LanguageError); !ok { |
| t.Error(err) |
| } |
| _, err = Parse("Usage: prog [a [b] ] c )", []string{}, true, "", false, false) |
| if _, ok := err.(*LanguageError); !ok { |
| t.Error(err) |
| } |
| } |
| |
| func TestAllowDoubleDash(t *testing.T) { |
| if v, err := Parse("usage: prog [-o] [--] <arg>\noptions: -o", []string{"--", "-o"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-o": false, "<arg>": "-o", "--": true}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("usage: prog [-o] [--] <arg>\noptions: -o", []string{"-o", "1"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-o": true, "<arg>": "1", "--": false}) != true { |
| t.Error(err) |
| } |
| _, err := Parse("usage: prog [-o] <arg>\noptions:-o", []string{"-o"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { //"--" is not allowed; FIXME? |
| t.Error(err) |
| } |
| } |
| |
| func TestDocopt(t *testing.T) { |
| doc := `Usage: prog [-v] A |
| |
| Options: -v Be verbose.` |
| if v, err := Parse(doc, []string{"arg"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": false, "A": "arg"}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse(doc, []string{"-v", "arg"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": true, "A": "arg"}) != true { |
| t.Error(err) |
| } |
| |
| doc = `Usage: prog [-vqr] [FILE] |
| prog INPUT OUTPUT |
| prog --help |
| |
| Options: |
| -v print status messages |
| -q report only file names |
| -r show all occurrences of the same error |
| --help |
| |
| ` |
| if v, err := Parse(doc, []string{"-v", "file.py"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": true, "-q": false, "-r": false, "--help": false, "FILE": "file.py", "INPUT": nil, "OUTPUT": nil}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse(doc, []string{"-v"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": true, "-q": false, "-r": false, "--help": false, "FILE": nil, "INPUT": nil, "OUTPUT": nil}) != true { |
| t.Error(err) |
| } |
| |
| _, err := Parse(doc, []string{"-v", "input.py", "output.py"}, true, "", false, false) // does not match |
| if _, ok := err.(*UserError); !ok { |
| t.Error(err) |
| } |
| _, err = Parse(doc, []string{"--fake"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error(err) |
| } |
| _, output, err := parseOutput(doc, []string{"--hel"}, true, "", false) |
| if err != nil || len(output) == 0 { |
| t.Error(err) |
| } |
| } |
| |
| func TestLanguageErrors(t *testing.T) { |
| _, err := Parse("no usage with colon here", []string{}, true, "", false, false) |
| if _, ok := err.(*LanguageError); !ok { |
| t.Error(err) |
| } |
| _, err = Parse("usage: here \n\n and again usage: here", []string{}, true, "", false, false) |
| if _, ok := err.(*LanguageError); !ok { |
| t.Error(err) |
| } |
| } |
| |
| func TestIssue40(t *testing.T) { |
| _, output, err := parseOutput("usage: prog --help-commands | --help", []string{"--help"}, true, "", false) |
| if err != nil || len(output) == 0 { |
| t.Error(err) |
| } |
| if v, err := Parse("usage: prog --aabb | --aa", []string{"--aa"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"--aabb": false, "--aa": true}) != true { |
| t.Error(err) |
| } |
| } |
| |
| func TestIssue34UnicodeStrings(t *testing.T) { |
| // TODO: see if applicable |
| } |
| |
| func TestCountMultipleFlags(t *testing.T) { |
| if v, err := Parse("usage: prog [-v]", []string{"-v"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": true}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("usage: prog [-vv]", []string{}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": 0}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("usage: prog [-vv]", []string{"-v"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": 1}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("usage: prog [-vv]", []string{"-vv"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": 2}) != true { |
| t.Error(err) |
| } |
| _, err := Parse("usage: prog [-vv]", []string{"-vvv"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error(err) |
| } |
| if v, err := Parse("usage: prog [-v | -vv | -vvv]", []string{"-vvv"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": 3}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("usage: prog [-v...]", []string{"-vvvvvv"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-v": 6}) != true { |
| t.Error(err) |
| } |
| if v, err := Parse("usage: prog [--ver --ver]", []string{"--ver", "--ver"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"--ver": 2}) != true { |
| t.Error(err) |
| } |
| } |
| |
| func TestAnyOptionsParameter(t *testing.T) { |
| _, err := Parse("usage: prog [options]", |
| []string{"-foo", "--bar", "--spam=eggs"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error() |
| } |
| |
| _, err = Parse("usage: prog [options]", |
| []string{"--foo", "--bar", "--bar"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error() |
| } |
| _, err = Parse("usage: prog [options]", |
| []string{"--bar", "--bar", "--bar", "-ffff"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error() |
| } |
| _, err = Parse("usage: prog [options]", |
| []string{"--long=arg", "--long=another"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error() |
| } |
| } |
| |
| func TestDefaultValueForPositionalArguments(t *testing.T) { |
| doc := "Usage: prog [--data=<data>...]\nOptions:\n\t-d --data=<arg> Input data [default: x]" |
| if v, err := Parse(doc, []string{}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"--data": []string{"x"}}) != true { |
| t.Error(err) |
| } |
| |
| doc = "Usage: prog [--data=<data>...]\nOptions:\n\t-d --data=<arg> Input data [default: x y]" |
| if v, err := Parse(doc, []string{}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"--data": []string{"x", "y"}}) != true { |
| t.Error(err) |
| } |
| |
| doc = "Usage: prog [--data=<data>...]\nOptions:\n\t-d --data=<arg> Input data [default: x y]" |
| if v, err := Parse(doc, []string{"--data=this"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"--data": []string{"this"}}) != true { |
| t.Error(err) |
| } |
| } |
| |
| func TestIssue59(t *testing.T) { |
| if v, err := Parse("usage: prog --long=<a>", []string{"--long="}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"--long": ""}) != true { |
| t.Error(err) |
| } |
| |
| if v, err := Parse("usage: prog -l <a>\noptions: -l <a>", []string{"-l", ""}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"-l": ""}) != true { |
| t.Error(err) |
| } |
| } |
| |
| func TestOptionsFirst(t *testing.T) { |
| if v, err := Parse("usage: prog [--opt] [<args>...]", []string{"--opt", "this", "that"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"--opt": true, "<args>": []string{"this", "that"}}) != true { |
| t.Error(err) |
| } |
| |
| if v, err := Parse("usage: prog [--opt] [<args>...]", []string{"this", "that", "--opt"}, true, "", false, false); reflect.DeepEqual(v, map[string]interface{}{"--opt": true, "<args>": []string{"this", "that"}}) != true { |
| t.Error(err) |
| } |
| |
| if v, err := Parse("usage: prog [--opt] [<args>...]", []string{"this", "that", "--opt"}, true, "", true, false); reflect.DeepEqual(v, map[string]interface{}{"--opt": false, "<args>": []string{"this", "that", "--opt"}}) != true { |
| t.Error(err) |
| } |
| } |
| |
| func TestIssue68OptionsShortcutDoesNotIncludeOptionsInUsagePattern(t *testing.T) { |
| args, err := Parse("usage: prog [-ab] [options]\noptions: -x\n -y", []string{"-ax"}, true, "", false, false) |
| |
| if args["-a"] != true { |
| t.Error(err) |
| } |
| if args["-b"] != false { |
| t.Error(err) |
| } |
| if args["-x"] != true { |
| t.Error(err) |
| } |
| if args["-y"] != false { |
| t.Error(err) |
| } |
| } |
| |
| func TestIssue65EvaluateArgvWhenCalledNotWhenImported(t *testing.T) { |
| os.Args = strings.Fields("prog -a") |
| v, err := Parse("usage: prog [-ab]", nil, true, "", false, false) |
| w := map[string]interface{}{"-a": true, "-b": false} |
| if reflect.DeepEqual(v, w) != true { |
| t.Error(err) |
| } |
| |
| os.Args = strings.Fields("prog -b") |
| v, err = Parse("usage: prog [-ab]", nil, true, "", false, false) |
| w = map[string]interface{}{"-a": false, "-b": true} |
| if reflect.DeepEqual(v, w) != true { |
| t.Error(err) |
| } |
| } |
| |
| func TestIssue71DoubleDashIsNotAValidOptionArgument(t *testing.T) { |
| _, err := Parse("usage: prog [--log=LEVEL] [--] <args>...", |
| []string{"--log", "--", "1", "2"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error() |
| } |
| |
| _, err = Parse(`usage: prog [-l LEVEL] [--] <args>... |
| options: -l LEVEL`, []string{"-l", "--", "1", "2"}, true, "", false, false) |
| if _, ok := err.(*UserError); !ok { |
| t.Error() |
| } |
| } |
| |
| func TestParseSection(t *testing.T) { |
| v := parseSection("usage:", "foo bar fizz buzz") |
| w := []string{} |
| if reflect.DeepEqual(v, w) != true { |
| t.Error() |
| } |
| |
| v = parseSection("usage:", "usage: prog") |
| w = []string{"usage: prog"} |
| if reflect.DeepEqual(v, w) != true { |
| t.Error() |
| } |
| |
| v = parseSection("usage:", "usage: -x\n -y") |
| w = []string{"usage: -x\n -y"} |
| if reflect.DeepEqual(v, w) != true { |
| t.Error() |
| } |
| |
| usage := `usage: this |
| |
| usage:hai |
| usage: this that |
| |
| usage: foo |
| bar |
| |
| PROGRAM USAGE: |
| foo |
| bar |
| usage: |
| ` + "\t" + `too |
| ` + "\t" + `tar |
| Usage: eggs spam |
| BAZZ |
| usage: pit stop` |
| |
| v = parseSection("usage:", usage) |
| w = []string{"usage: this", |
| "usage:hai", |
| "usage: this that", |
| "usage: foo\n bar", |
| "PROGRAM USAGE:\n foo\n bar", |
| "usage:\n\ttoo\n\ttar", |
| "Usage: eggs spam", |
| "usage: pit stop", |
| } |
| if reflect.DeepEqual(v, w) != true { |
| t.Error() |
| } |
| } |
| |
| func TestIssue126DefaultsNotParsedCorrectlyWhenTabs(t *testing.T) { |
| section := "Options:\n\t--foo=<arg> [default: bar]" |
| v := patternList{newOption("", "--foo", 1, "bar")} |
| if reflect.DeepEqual(parseDefaults(section), v) != true { |
| t.Error() |
| } |
| } |
| |
| // conf file based test cases |
| func TestFileTestcases(t *testing.T) { |
| filenames := []string{"testcases.docopt", "test_golang.docopt"} |
| for _, filename := range filenames { |
| raw, err := ioutil.ReadFile(filename) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| tests, err := parseTest(raw) |
| if err != nil { |
| t.Fatal(err) |
| } |
| for _, c := range tests { |
| result, err := Parse(c.doc, c.argv, true, "", false, false) |
| if _, ok := err.(*UserError); c.userError && !ok { |
| // expected a user-error |
| t.Error("testcase:", c.id, "result:", result) |
| } else if _, ok := err.(*UserError); !c.userError && ok { |
| // unexpected user-error |
| t.Error("testcase:", c.id, "error:", err, "result:", result) |
| } else if reflect.DeepEqual(c.expect, result) != true { |
| t.Error("testcase:", c.id, "result:", result, "expect:", c.expect) |
| } |
| } |
| } |
| } |
| |
| type testcase struct { |
| id int |
| doc string |
| prog string |
| argv []string |
| expect map[string]interface{} |
| userError bool |
| } |
| |
| func parseTest(raw []byte) ([]testcase, error) { |
| var res []testcase |
| commentPattern := regexp.MustCompile("#.*") |
| raw = commentPattern.ReplaceAll(raw, []byte("")) |
| raw = bytes.TrimSpace(raw) |
| if bytes.HasPrefix(raw, []byte(`"""`)) { |
| raw = raw[3:] |
| } |
| |
| id := 0 |
| for _, fixture := range bytes.Split(raw, []byte(`r"""`)) { |
| doc, _, body := stringPartition(string(fixture), `"""`) |
| for _, cas := range strings.Split(body, "$")[1:] { |
| argvString, _, expectString := stringPartition(strings.TrimSpace(cas), "\n") |
| prog, _, argvString := stringPartition(strings.TrimSpace(argvString), " ") |
| argv := []string{} |
| if len(argvString) > 0 { |
| argv = strings.Fields(argvString) |
| } |
| var expectUntyped interface{} |
| err := json.Unmarshal([]byte(expectString), &expectUntyped) |
| if err != nil { |
| return nil, err |
| } |
| switch expect := expectUntyped.(type) { |
| case string: // user-error |
| res = append(res, testcase{id, doc, prog, argv, nil, true}) |
| case map[string]interface{}: |
| // convert []interface{} values to []string |
| // convert float64 values to int |
| for k, vUntyped := range expect { |
| switch v := vUntyped.(type) { |
| case []interface{}: |
| itemList := make([]string, len(v)) |
| for i, itemUntyped := range v { |
| if item, ok := itemUntyped.(string); ok { |
| itemList[i] = item |
| } |
| } |
| expect[k] = itemList |
| case float64: |
| expect[k] = int(v) |
| } |
| } |
| res = append(res, testcase{id, doc, prog, argv, expect, false}) |
| default: |
| return nil, fmt.Errorf("unhandled json data type") |
| } |
| id++ |
| } |
| } |
| return res, nil |
| } |
| |
| // parseOutput wraps the Parse() function to also return stdout |
| func parseOutput(doc string, argv []string, help bool, version string, |
| optionsFirst bool) (map[string]interface{}, string, error) { |
| stdout := os.Stdout |
| r, w, _ := os.Pipe() |
| os.Stdout = w |
| |
| args, err := Parse(doc, argv, help, version, optionsFirst, false) |
| |
| outChan := make(chan string) |
| go func() { |
| var buf bytes.Buffer |
| io.Copy(&buf, r) |
| outChan <- buf.String() |
| }() |
| |
| w.Close() |
| os.Stdout = stdout |
| output := <-outChan |
| |
| return args, output, err |
| } |
| |
| var debugEnabled = false |
| |
| func debugOn(l ...interface{}) { |
| debugEnabled = true |
| debug(l...) |
| } |
| func debugOff(l ...interface{}) { |
| debug(l...) |
| debugEnabled = false |
| } |
| |
| func debug(l ...interface{}) { |
| if debugEnabled { |
| fmt.Println(l...) |
| } |
| } |