240 lines
9.5 KiB
Go
240 lines
9.5 KiB
Go
package wand
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestCommand(t *testing.T) {
|
|
type f struct {
|
|
One string
|
|
SecondField int
|
|
}
|
|
ff := func(f f) string {
|
|
return f.One + fmt.Sprint(f.SecondField)
|
|
}
|
|
|
|
type b struct{ One, Two, Three, Four bool }
|
|
fb := func(b b) string {
|
|
return fmt.Sprintf("%t;%t;%t;%t", b.One, b.Two, b.Three, b.Four)
|
|
}
|
|
|
|
fbp := func(b b, p ...string) string {
|
|
o := fb(b)
|
|
if len(p) == 0 {
|
|
return o
|
|
}
|
|
|
|
s := []string{o}
|
|
for _, pi := range p {
|
|
s = append(s, pi)
|
|
}
|
|
|
|
return strings.Join(s, ";")
|
|
}
|
|
|
|
type m struct {
|
|
One, Two bool
|
|
Three string
|
|
}
|
|
fm := func(m m) string {
|
|
return fmt.Sprintf("%t;%t;%s", m.One, m.Two, m.Three)
|
|
}
|
|
|
|
type l struct {
|
|
One []bool
|
|
Two []string
|
|
}
|
|
fl := func(l l) string {
|
|
var sb []string
|
|
for _, b := range l.One {
|
|
sb = append(sb, fmt.Sprint(b))
|
|
}
|
|
|
|
return strings.Join([]string{strings.Join(sb, ","), strings.Join(l.Two, ",")}, ";")
|
|
}
|
|
|
|
type lb struct{ One, Two, Three []bool }
|
|
flb := func(lb lb) string {
|
|
var s []string
|
|
for _, b := range [][]bool{lb.One, lb.Two, lb.Three} {
|
|
var sb []string
|
|
for _, bi := range b {
|
|
sb = append(sb, fmt.Sprint(bi))
|
|
}
|
|
|
|
s = append(s, strings.Join(sb, ","))
|
|
}
|
|
|
|
return strings.Join(s, ";")
|
|
}
|
|
|
|
fp := func(f f, a ...string) string {
|
|
o := ff(f)
|
|
return fmt.Sprintf("%s;%s", o, strings.Join(a, ","))
|
|
}
|
|
|
|
type d struct{ One2 bool }
|
|
fd := func(d d) string {
|
|
return fmt.Sprint(d.One2)
|
|
}
|
|
|
|
t.Run("no args", testExec(t, ff, "", "foo", "", "0"))
|
|
t.Run("basic options", func(t *testing.T) {
|
|
t.Run("space", testExec(t, ff, "", "foo --one baz --second-field 42", "", "baz42"))
|
|
t.Run("eq", testExec(t, ff, "", "foo --one=baz --second-field=42", "", "baz42"))
|
|
})
|
|
|
|
t.Run("short options combined, explicit last", func(t *testing.T) {
|
|
t.Run("bool last", testExec(t, ShortForm(fb, "one", "a", "two", "b", "three", "c"), "", "foo -abc true", "", "true;true;true;false"))
|
|
t.Run("string last", testExec(t, ShortForm(fm, "one", "a", "two", "b", "three", "c"), "", "foo -abc bar", "", "true;true;bar"))
|
|
})
|
|
|
|
t.Run("multiple values", func(t *testing.T) {
|
|
t.Run("bools, short", testExec(t, ShortForm(fl, "one", "a"), "", "foo -a -a -a", "", "true,true,true;"))
|
|
t.Run("bools, short, combined", testExec(t, ShortForm(fl, "one", "a"), "", "foo -aaa", "", "true,true,true;"))
|
|
t.Run("bools, short, explicit", testExec(t, ShortForm(fl, "one", "a"), "", "foo -a true -a true -a true", "", "true,true,true;"))
|
|
t.Run("bools, short, combined, last explicit", testExec(t, ShortForm(fl, "one", "a"), "", "foo -aaa true", "", "true,true,true;"))
|
|
t.Run("bools, long", testExec(t, fl, "", "foo --one --one --one", "", "true,true,true;"))
|
|
t.Run("bools, long, explicit", testExec(t, fl, "", "foo --one true --one true --one true", "", "true,true,true;"))
|
|
t.Run("mixd, short", testExec(t, ShortForm(fl, "one", "a", "two", "b"), "", "foo -a -b bar", "", "true;bar"))
|
|
t.Run("mixed, short, combined", testExec(t, ShortForm(fl, "one", "a", "two", "b"), "", "foo -ab bar", "", "true;bar"))
|
|
t.Run("mixed, long", testExec(t, fl, "", "foo --one --two bar", "", "true;bar"))
|
|
t.Run("mixed, long, explicit", testExec(t, fl, "", "foo --one true --two bar", "", "true;bar"))
|
|
})
|
|
|
|
t.Run("implicit bool option", func(t *testing.T) {
|
|
t.Run("short", testExec(t, ShortForm(fb, "one", "a"), "", "foo -a", "", "true;false;false;false"))
|
|
t.Run(
|
|
"short, multiple",
|
|
testExec(t, ShortForm(fb, "one", "a", "two", "b", "three", "c"), "", "foo -a -b -c", "", "true;true;true;false"),
|
|
)
|
|
|
|
t.Run(
|
|
"short, combined",
|
|
testExec(t, ShortForm(fb, "one", "a", "two", "b", "three", "c"), "", "foo -abc", "", "true;true;true;false"),
|
|
)
|
|
|
|
t.Run(
|
|
"short, combined, multiple",
|
|
testExec(t, ShortForm(fb, "one", "a", "two", "b", "three", "c", "four", "d"), "", "foo -ab -cd", "", "true;true;true;true"),
|
|
)
|
|
|
|
t.Run(
|
|
"short, multiple values",
|
|
testExec(t, ShortForm(flb, "one", "a", "two", "b", "three", "c"), "", "foo -aba -cab", "", "true,true,true;true,true;true"),
|
|
)
|
|
|
|
t.Run("long", testExec(t, fb, "", "foo --one", "", "true;false;false;false"))
|
|
t.Run("long, multiple", testExec(t, fb, "", "foo --one --two --three", "", "true;true;true;false"))
|
|
t.Run("long, multiple values", testExec(t, flb, "", "foo --one --two --one", "", "true,true;true;"))
|
|
})
|
|
|
|
t.Run("explicit bool option", func(t *testing.T) {
|
|
t.Run("short, true", testExec(t, ShortForm(fb, "one", "a"), "", "foo -a true", "", "true;false;false;false"))
|
|
t.Run("short, false", testExec(t, ShortForm(fb, "one", "a"), "", "foo -a false", "", "false;false;false;false"))
|
|
t.Run("short, with eq", testExec(t, ShortForm(fb, "one", "a"), "", "foo -a=true", "", "true;false;false;false"))
|
|
t.Run("short, true variant, capital", testExec(t, ShortForm(fb, "one", "a"), "", "foo -a True", "", "true;false;false;false"))
|
|
t.Run("short, true variant, 1", testExec(t, ShortForm(fb, "one", "a"), "", "foo -a 1", "", "true;false;false;false"))
|
|
t.Run("short, false variant, 0", testExec(t, ShortForm(fb, "one", "a"), "", "foo -a 0", "", "false;false;false;false"))
|
|
t.Run("short, combined", testExec(t, ShortForm(fb, "one", "a", "two", "b"), "", "foo -ab true", "", "true;true;false;false"))
|
|
t.Run(
|
|
"short, combined, multiple",
|
|
testExec(
|
|
t,
|
|
ShortForm(fb, "one", "a", "two", "b", "three", "c", "four", "d"),
|
|
"", "foo -ab true -cd true",
|
|
"", "true;true;true;true",
|
|
),
|
|
)
|
|
|
|
t.Run("long", testExec(t, fb, "", "foo --one true", "", "true;false;false;false"))
|
|
t.Run("long, false", testExec(t, fb, "", "foo --one false", "", "false;false;false;false"))
|
|
t.Run("logn, with eq", testExec(t, fb, "", "foo --one=true", "", "true;false;false;false"))
|
|
t.Run("long, mixed, first", testExec(t, fb, "", "foo --one false --two", "", "false;true;false;false"))
|
|
t.Run("long, mixed, last", testExec(t, fb, "", "foo --one --two false", "", "true;false;false;false"))
|
|
})
|
|
|
|
t.Run("expected bool option", func(t *testing.T) {
|
|
t.Run("short, implicit", testExec(t, ShortForm(fb, "one", "a"), "", "foo -a", "", "true;false;false;false"))
|
|
t.Run("short, explicit", testExec(t, ShortForm(fb, "one", "a"), "", "foo -a true", "", "true;false;false;false"))
|
|
t.Run("short, automatic positional", testExec(t, ShortForm(fbp, "one", "a"), "", "foo -a bar", "", "true;false;false;false;bar"))
|
|
t.Run("short, combined", testExec(t, ShortForm(fb, "one", "a", "two", "b"), "", "foo -ab true", "", "true;true;false;false"))
|
|
t.Run(
|
|
"short, combined, automatic positional",
|
|
testExec(t, ShortForm(fbp, "one", "a", "two", "b"), "", "foo -ab bar", "", "true;true;false;false;bar"),
|
|
)
|
|
|
|
t.Run("long, implicit", testExec(t, fb, "", "foo --one", "", "true;false;false;false"))
|
|
t.Run("long, explicit", testExec(t, fb, "", "foo --one true", "", "true;false;false;false"))
|
|
t.Run("long, automatic positional", testExec(t, fbp, "", "foo --one bar", "", "true;false;false;false;bar"))
|
|
})
|
|
|
|
t.Run("positional", func(t *testing.T) {
|
|
t.Run("basic", testExec(t, fp, "", "foo bar baz", "", "0;bar,baz"))
|
|
t.Run("explicit", testExec(t, fp, "", "foo -- bar baz", "", "0;bar,baz"))
|
|
t.Run("mixed", testExec(t, fp, "", "foo bar -- baz", "", "0;bar,baz"))
|
|
t.Run("with option", testExec(t, fp, "", "foo bar --second-field 42 baz", "", "42;bar,baz"))
|
|
t.Run("with bool option at the end", testExec(t, fbp, "", "foo bar baz --one", "", "true;false;false;false;bar;baz"))
|
|
t.Run("with expected bool, implicit", testExec(t, fbp, "", "foo bar --one baz", "", "true;false;false;false;bar;baz"))
|
|
t.Run("with expected bool, explicit", testExec(t, fbp, "", "foo bar --one true baz", "", "true;false;false;false;bar;baz"))
|
|
t.Run("option format", testExec(t, fbp, "", "foo -- --one", "", "false;false;false;false;--one"))
|
|
})
|
|
|
|
t.Run("example", func(t *testing.T) {
|
|
type s struct {
|
|
Foo bool
|
|
Bar []bool
|
|
Qux bool
|
|
Quux string
|
|
}
|
|
|
|
fs := func(s s, a1, a2 string) string {
|
|
var sbar []string
|
|
for _, b := range s.Bar {
|
|
sbar = append(sbar, fmt.Sprint(b))
|
|
}
|
|
|
|
return fmt.Sprintf("%t;%s;%t;%s;%s;%s", s.Foo, strings.Join(sbar, ","), s.Qux, s.Quux, a1, a2)
|
|
}
|
|
|
|
t.Run(
|
|
"full",
|
|
testExec(
|
|
t,
|
|
ShortForm(fs, "foo", "a", "bar", "b"),
|
|
"",
|
|
"foo -ab --bar baz -b --qux --quux corge -- grault",
|
|
"",
|
|
"true;true,true,true;true;corge;baz;grault",
|
|
),
|
|
)
|
|
})
|
|
|
|
t.Run("expected or unexpected", func(t *testing.T) {
|
|
t.Run("capital letters", testExec(t, fp, "", "foo --One bar", "", "0;--One,bar"))
|
|
t.Run("digit in option name", testExec(t, fd, "", "foo --one-2", "", "true"))
|
|
t.Run("dash in option name", testExec(t, ff, "", "foo --second-field 42", "", "42"))
|
|
t.Run("unpexpected character", testExec(t, fp, "", "foo --one#", "", "0;--one#"))
|
|
t.Run(
|
|
"invalid short option set",
|
|
testExec(t, ShortForm(fp, "one", "a", "one", "b", "second-field", "c"), "", "foo -aBc", "", "0;-aBc"),
|
|
)
|
|
|
|
t.Run("positional separator, no value", testExec(t, fp, "", "foo --one bar --", "", "bar0;"))
|
|
t.Run("positional separator, expecting value", testExec(t, fp, "", "foo --one --", "--one", ""))
|
|
t.Run("shot flag set, expecting value", testExec(t, ShortForm(fp, "second-field", "b"), "", "foo --one -b", "--one", ""))
|
|
})
|
|
|
|
t.Run("preserve order", func(t *testing.T) {
|
|
t.Run("bools", testExec(t, fl, "", "foo --one --one false --one", "", "true,false,true;"))
|
|
t.Run("strings", testExec(t, fl, "", "foo --two 1 --two 2 --two 3", "", ";1,2,3"))
|
|
})
|
|
|
|
t.Run("select subcommand", func(t *testing.T) {
|
|
t.Run("named", testExec(t, Command("", nil, Command("bar", ff), Command("baz", ff)), "", "foo baz", "", "0"))
|
|
t.Run("default", testExec(t, Command("", nil, Command("bar", ff), Default(Command("baz", ff))), "", "foo", "", "0"))
|
|
})
|
|
}
|