test command validation
This commit is contained in:
parent
2d93474cb1
commit
e348cce3d2
2
Makefile
2
Makefile
@ -1,4 +1,4 @@
|
|||||||
SOURCES = $(shell find . -name "*.go" | grep -v iniparser.gen.go | grep -v docreflect.gen.go)
|
SOURCES = $(shell find . -name "*.go" | grep -v iniparser.gen.go | grep -v docreflect.gen.go | grep -v docreflect_test.go)
|
||||||
|
|
||||||
default: build
|
default: build
|
||||||
|
|
||||||
|
|||||||
60
command.go
60
command.go
@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var commandNameExpression = regexp.MustCompile("^[a-zA-Z_][a-zA-Z_0-9]*$")
|
var commandNameExpression = regexp.MustCompile("^[a-zA-Z_][a-zA-Z_0-9-]*$")
|
||||||
|
|
||||||
func wrap(impl any) Cmd {
|
func wrap(impl any) Cmd {
|
||||||
cmd, ok := impl.(Cmd)
|
cmd, ok := impl.(Cmd)
|
||||||
@ -120,10 +120,6 @@ func validateImpl(cmd Cmd, conf Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validateCommandTree(cmd Cmd, conf Config) error {
|
func validateCommandTree(cmd Cmd, conf Config) error {
|
||||||
if cmd.helpFor != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if cmd.version != "" {
|
if cmd.version != "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -171,7 +167,7 @@ func validateCommandTree(cmd Cmd, conf Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := validateCommandTree(s, conf); err != nil {
|
if err := validateCommandTree(s, conf); err != nil {
|
||||||
return fmt.Errorf("%s: %w", s.name, err)
|
return fmt.Errorf("%s: %w", cmd.name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,10 +223,6 @@ func validateShortFormsTree(cmd Cmd) (map[string]string, map[string]string, erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(cmd.shortForms)%2 != 0 {
|
|
||||||
return nil, nil, fmt.Errorf("unassigned short form: %s", cmd.shortForms[len(cmd.shortForms)-1])
|
|
||||||
}
|
|
||||||
|
|
||||||
mf := mapFields(cmd.impl)
|
mf := mapFields(cmd.impl)
|
||||||
_, helpDefined := mf["help"]
|
_, helpDefined := mf["help"]
|
||||||
for i := 0; i < len(cmd.shortForms); i += 2 {
|
for i := 0; i < len(cmd.shortForms); i += 2 {
|
||||||
@ -304,26 +296,6 @@ func validateCommand(cmd Cmd, conf Config) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func insertHelpOption(names []string) []string {
|
|
||||||
for _, n := range names {
|
|
||||||
if n == "help" {
|
|
||||||
return names
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(names, "help")
|
|
||||||
}
|
|
||||||
|
|
||||||
func insertHelpShortForm(shortForms []string) []string {
|
|
||||||
for _, sf := range shortForms {
|
|
||||||
if sf == "h" {
|
|
||||||
return shortForms
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(shortForms, "h")
|
|
||||||
}
|
|
||||||
|
|
||||||
func boolOptions(cmd Cmd) []string {
|
func boolOptions(cmd Cmd) []string {
|
||||||
f := fields(cmd.impl)
|
f := fields(cmd.impl)
|
||||||
b := boolFields(f)
|
b := boolFields(f)
|
||||||
@ -333,7 +305,18 @@ func boolOptions(cmd Cmd) []string {
|
|||||||
n = append(n, fi.Name())
|
n = append(n, fi.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
n = insertHelpOption(n)
|
var hasHelp bool
|
||||||
|
for _, fi := range f {
|
||||||
|
if fi.Name() == "help" {
|
||||||
|
hasHelp = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !hasHelp {
|
||||||
|
n = append(n, "help")
|
||||||
|
}
|
||||||
|
|
||||||
sfm := make(map[string][]string)
|
sfm := make(map[string][]string)
|
||||||
for i := 0; i < len(cmd.shortForms); i += 2 {
|
for i := 0; i < len(cmd.shortForms); i += 2 {
|
||||||
s, l := cmd.shortForms[i], cmd.shortForms[i+1]
|
s, l := cmd.shortForms[i], cmd.shortForms[i+1]
|
||||||
@ -342,11 +325,20 @@ func boolOptions(cmd Cmd) []string {
|
|||||||
|
|
||||||
var sf []string
|
var sf []string
|
||||||
for _, ni := range n {
|
for _, ni := range n {
|
||||||
if sn, ok := sfm[ni]; ok {
|
sf = append(sf, sfm[ni]...)
|
||||||
sf = append(sf, sn...)
|
}
|
||||||
|
|
||||||
|
var hasHelpShortForm bool
|
||||||
|
for i := 0; i < len(cmd.shortForms); i += 2 {
|
||||||
|
if cmd.shortForms[i] == "h" {
|
||||||
|
hasHelpShortForm = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sf = insertHelpShortForm(sf)
|
if !hasHelp && !hasHelpShortForm {
|
||||||
|
sf = append(sf, "h")
|
||||||
|
}
|
||||||
|
|
||||||
return append(n, sf...)
|
return append(n, sf...)
|
||||||
}
|
}
|
||||||
|
|||||||
347
command_test.go
Normal file
347
command_test.go
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
package wand
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCommand(t *testing.T) {
|
||||||
|
t.Run("fields", func(t *testing.T) {
|
||||||
|
type s0 struct {
|
||||||
|
FooBar int
|
||||||
|
Foo struct{ Bar bool }
|
||||||
|
}
|
||||||
|
|
||||||
|
type s1 struct {
|
||||||
|
Config string
|
||||||
|
}
|
||||||
|
|
||||||
|
f0 := func(a s0) int { return a.FooBar }
|
||||||
|
t.Run(
|
||||||
|
"incompatible field types",
|
||||||
|
testExec(testCase{impl: f0, command: "foo"}, "duplicate fields with different types", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
f1 := func(a s1) string { return a.Config }
|
||||||
|
t.Run(
|
||||||
|
"config option shadowed",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: f1, mergeConfTyped: []Config{ConfigFromOption()}, command: "foo"},
|
||||||
|
"option reserved for config",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("positional", func(t *testing.T) {
|
||||||
|
f := func(a, b, c int) int { return a + b + c }
|
||||||
|
t.Run("ok", testExec(testCase{impl: Args(Command("foo", f), 3, 3), command: "foo 1 2 3"}, "", "6"))
|
||||||
|
t.Run(
|
||||||
|
"min less than fixed",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: Args(Command("foo", f), 2, 3), command: "foo 1 2 3"},
|
||||||
|
"minimum positional",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"min more than fixed",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: Args(Command("foo", f), 4, 4), command: "foo 1 2 3"},
|
||||||
|
"minimum positional",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"max less than fixed",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: Args(Command("foo", f), 0, 2), command: "foo 1 2 3"},
|
||||||
|
"maximum positional",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fv := func(a, b int, c ...int) int { return a + b + len(c) }
|
||||||
|
t.Run("ok variadic", testExec(testCase{impl: Args(Command("foo", fv), 3, 5), command: "foo 1 2 3 4 5"}, "", "6"))
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"min less than fixed variadic",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: Args(Command("foo", fv), 1, 5), command: "foo 1 2 3"},
|
||||||
|
"minimum positional",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"max less than fixed variadic",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: Args(Command("foo", fv), 0, 1), command: "foo 1 2 3"},
|
||||||
|
"maximum positional",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"min more than max variadic",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: Args(Command("foo", fv), 4, 3), command: "foo 1 2 3 4 5"},
|
||||||
|
"minimum positional",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fvio := func(a int, in io.Reader, out io.Writer, b int, c ...int) int { return a + b + len(c) }
|
||||||
|
t.Run("ok io", testExec(testCase{impl: Args(Command("foo", fvio), 3, 5), command: "foo 1 2 3 4 5"}, "", "6"))
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"min less than fixed io",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: Args(Command("foo", fvio), 1, 5), command: "foo 1 2 3"},
|
||||||
|
"minimum positional",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"max less than fixed io",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: Args(Command("foo", fvio), 0, 1), command: "foo 1 2 3"},
|
||||||
|
"maximum positional",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"min more than max io",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: Args(Command("foo", fvio), 4, 3), command: "foo 1 2 3 4 5"},
|
||||||
|
"minimum positional",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fio := func(a, b io.Reader) {}
|
||||||
|
t.Run(
|
||||||
|
"max one io of a kind",
|
||||||
|
testExec(testCase{impl: fio, command: "foo"}, "only zero or one reader", ""),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("impl", func(t *testing.T) {
|
||||||
|
t.Run(
|
||||||
|
"must be func",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: []func(){func() {}}, command: "foo"},
|
||||||
|
"implementation must be a function",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"paramters must be bindable",
|
||||||
|
testExec(testCase{impl: func(chan int) {}, command: "foo"}, "unsupported parameter type", ""),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("command tree", func(t *testing.T) {
|
||||||
|
f := func(a, b int) int { return a + b }
|
||||||
|
cmd := Command("foo", f)
|
||||||
|
cmd = Version(cmd, "v42")
|
||||||
|
t.Run("version pass", testExec(testCase{impl: cmd, command: "foo 1 2"}, "", "3"))
|
||||||
|
cmd = Command("foo", nil)
|
||||||
|
t.Run(
|
||||||
|
"no impl and not group",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo"}, "command does not have an implementation", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = Group("foo")
|
||||||
|
t.Run(
|
||||||
|
"no impl and no subcommands",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo"}, "empty command category", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = Group("foo", Command("bar-baz", func() {}), Command("qux quux", func() {}))
|
||||||
|
t.Run(
|
||||||
|
"invalid subcommand name",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo bar-baz"}, "command name is not a valid", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = Group("foo", Command("bar", func() {}), Command("bar", func() {}))
|
||||||
|
t.Run(
|
||||||
|
"duplicate subcommand name",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo bar"}, "subcommand name conflict", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = Command("foo", func() {}, Default(Command("bar", func() {})), Command("bar", func() {}))
|
||||||
|
t.Run(
|
||||||
|
"implementation conflict",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: cmd, command: "foo bar"},
|
||||||
|
"default subcommand defined for a command that has an explicit implementation",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = Group("foo", Default(Command("bar", func() {})), Default(Command("baz", func() {})))
|
||||||
|
t.Run(
|
||||||
|
"multiple defaults",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: cmd, command: "foo bar"},
|
||||||
|
"multiple default subcommands",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = Command("foo", func() {}, Command("bar", func() {}), Command("baz", func(chan int) {}))
|
||||||
|
t.Run(
|
||||||
|
"invalid subcommand",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: cmd, command: "foo bar"},
|
||||||
|
"foo:",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("short forms", func(t *testing.T) {
|
||||||
|
type (
|
||||||
|
s0 struct {
|
||||||
|
Foo int
|
||||||
|
Qux int
|
||||||
|
}
|
||||||
|
s1 struct{ Bar int }
|
||||||
|
s2 struct{ Baz int }
|
||||||
|
)
|
||||||
|
|
||||||
|
f0 := func(a s0) int { return a.Foo }
|
||||||
|
f1 := func(a s1) int { return a.Bar }
|
||||||
|
f2 := func(a s2) int { return a.Baz }
|
||||||
|
cmd := ShortForm(Command("foo", f0, ShortForm(Command("bar", f1), "a", "bar")), "a", "foo")
|
||||||
|
t.Run(
|
||||||
|
"same short form for different options",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo"}, "same short form for different options", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(Command("foo", f0), "a", "foo", "a", "qux")
|
||||||
|
t.Run(
|
||||||
|
"same short form for different options on the same command",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo"}, "same short form for different options", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(Command("foo", f0, Command("bar", f1)), "a", "foo", "a", "qux")
|
||||||
|
t.Run(
|
||||||
|
"same short form for different options on the same command with subcommand",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo"}, "same short form for different options", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = Command(
|
||||||
|
"foo",
|
||||||
|
f0,
|
||||||
|
ShortForm(Command("bar", f1), "a", "bar"),
|
||||||
|
ShortForm(Command("baz", f2), "a", "baz"),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"same short form for different options on different branches in the tree",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo"}, "same short form for different options", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(Command("foo", f0, ShortForm(Command("bar", f1), "b", "baz")), "a", "foo")
|
||||||
|
t.Run(
|
||||||
|
"unmapped short form",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo"}, "unmapped short forms", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(
|
||||||
|
Command(
|
||||||
|
"foo",
|
||||||
|
f0,
|
||||||
|
ShortForm(Command("bar", f1), "b", "baz"),
|
||||||
|
ShortForm(Command("qux", f1), "b", "qux"),
|
||||||
|
),
|
||||||
|
"a",
|
||||||
|
"foo",
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"conflicting unmapped",
|
||||||
|
testExec(
|
||||||
|
testCase{impl: cmd, command: "foo"},
|
||||||
|
"using the same short form for different options",
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(Command("foo", f0), "ab", "foo")
|
||||||
|
t.Run(
|
||||||
|
"short form not a single character",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo"}, "invalid short form", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(Command("foo", f0), "6", "foo")
|
||||||
|
t.Run(
|
||||||
|
"short form not a single character",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo"}, "invalid short form", ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(Group("foo", Command("bar", f1)), "b", "bar")
|
||||||
|
t.Run(
|
||||||
|
"short form with command category",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo bar"}, "", "0"),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("bool options", func(t *testing.T) {
|
||||||
|
type s0 struct {
|
||||||
|
Foo int
|
||||||
|
Bar bool
|
||||||
|
Baz bool
|
||||||
|
}
|
||||||
|
type s1 struct {
|
||||||
|
Foo int
|
||||||
|
Bar bool
|
||||||
|
Baz bool
|
||||||
|
Help bool
|
||||||
|
}
|
||||||
|
f0 := func(a s0, b, c string) string {
|
||||||
|
return fmt.Sprint(a.Foo) + fmt.Sprint(a.Bar) + fmt.Sprint(a.Baz) + b + c
|
||||||
|
}
|
||||||
|
|
||||||
|
f1 := func(a s1, b, c string) string {
|
||||||
|
return fmt.Sprint(a.Foo) + fmt.Sprint(a.Bar) + fmt.Sprint(a.Baz) + fmt.Sprint(a.Help) + b + c
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := ShortForm(Command("foo", f0), "b", "bar")
|
||||||
|
t.Run(
|
||||||
|
"no help in fields and no help in short forms",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo --foo 42 -b qux --baz quux"}, "", "42truetruequxquux"),
|
||||||
|
)
|
||||||
|
|
||||||
|
t.Run(
|
||||||
|
"no help in fields and no help in short forms help",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo --help", contains: true}, "", "Synopsis"),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(Command("foo", f0), "h", "help")
|
||||||
|
t.Run(
|
||||||
|
"help from short forms",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo -h", contains: true}, "", "Synopsis"),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(Command("foo", f1), "b", "bar")
|
||||||
|
t.Run(
|
||||||
|
"help taken by a field",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo --help qux quux"}, "", "0falsefalsetruequxquux"),
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd = ShortForm(Command("foo", f1), "h", "bar")
|
||||||
|
t.Run(
|
||||||
|
"help taken by a field and help short form used for another field",
|
||||||
|
testExec(testCase{impl: cmd, command: "foo --help qux -h quux"}, "", "0truefalsetruequxquux"),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCommand(t *testing.T) {
|
func TestCommandLine(t *testing.T) {
|
||||||
type f struct {
|
type f struct {
|
||||||
One string
|
One string
|
||||||
SecondField int
|
SecondField int
|
||||||
@ -93,7 +93,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"bool last",
|
"bool last",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three"),
|
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three"),
|
||||||
command: "foo -abc true",
|
command: "foo -abc true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -105,7 +105,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"string last",
|
"string last",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fm), "a", "one", "b", "two", "c", "three"),
|
impl: ShortForm(Command("foo", fm), "a", "one", "b", "two", "c", "three"),
|
||||||
command: "foo -abc bar",
|
command: "foo -abc bar",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -119,7 +119,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"bools, short",
|
"bools, short",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fl), "a", "one"),
|
impl: ShortForm(Command("foo", fl), "a", "one"),
|
||||||
command: "foo -a -a -a",
|
command: "foo -a -a -a",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -131,7 +131,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"bools, short, combined",
|
"bools, short, combined",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fl), "a", "one"),
|
impl: ShortForm(Command("foo", fl), "a", "one"),
|
||||||
command: "foo -aaa",
|
command: "foo -aaa",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -143,7 +143,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"bools, short, explicit",
|
"bools, short, explicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fl), "a", "one"),
|
impl: ShortForm(Command("foo", fl), "a", "one"),
|
||||||
command: "foo -a true -a true -a true",
|
command: "foo -a true -a true -a true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -155,7 +155,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"bools, short, combined, last explicit",
|
"bools, short, combined, last explicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fl), "a", "one"),
|
impl: ShortForm(Command("foo", fl), "a", "one"),
|
||||||
command: "foo -aaa true",
|
command: "foo -aaa true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -167,7 +167,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"bools, long",
|
"bools, long",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fl,
|
impl: fl,
|
||||||
command: "foo --one --one --one",
|
command: "foo --one --one --one",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -179,18 +179,18 @@ func TestCommand(t *testing.T) {
|
|||||||
"bools, long, explicit",
|
"bools, long, explicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fl,
|
impl: fl,
|
||||||
command: "foo --one true --one true --one true",
|
command: "foo --one true --one true --one true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
"true,true,true;"),
|
"true,true,true;"),
|
||||||
)
|
)
|
||||||
|
|
||||||
t.Run(
|
t.Run(
|
||||||
"mixd, short",
|
"mixd, short",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fl), "a", "one", "b", "two"),
|
impl: ShortForm(Command("foo", fl), "a", "one", "b", "two"),
|
||||||
command: "foo -a -b bar",
|
command: "foo -a -b bar",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -202,7 +202,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"mixed, short, combined",
|
"mixed, short, combined",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fl), "a", "one", "b", "two"),
|
impl: ShortForm(Command("foo", fl), "a", "one", "b", "two"),
|
||||||
command: "foo -ab bar",
|
command: "foo -ab bar",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -214,7 +214,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"mixed, long",
|
"mixed, long",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fl,
|
impl: fl,
|
||||||
command: "foo --one --two bar",
|
command: "foo --one --two bar",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -226,7 +226,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"mixed, long, explicit",
|
"mixed, long, explicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fl,
|
impl: fl,
|
||||||
command: "foo --one true --two bar",
|
command: "foo --one true --two bar",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -240,7 +240,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short",
|
"short",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one"),
|
impl: ShortForm(Command("foo", fb), "a", "one"),
|
||||||
command: "foo -a",
|
command: "foo -a",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -252,7 +252,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, multiple",
|
"short, multiple",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three"),
|
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three"),
|
||||||
command: "foo -a -b -c",
|
command: "foo -a -b -c",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -264,7 +264,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, combined",
|
"short, combined",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three"),
|
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three"),
|
||||||
command: "foo -abc",
|
command: "foo -abc",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -276,7 +276,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, combined, multiple",
|
"short, combined, multiple",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three", "d", "four"),
|
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three", "d", "four"),
|
||||||
command: "foo -ab -cd",
|
command: "foo -ab -cd",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -288,7 +288,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, multiple values",
|
"short, multiple values",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", flb), "a", "one", "b", "two", "c", "three"),
|
impl: ShortForm(Command("foo", flb), "a", "one", "b", "two", "c", "three"),
|
||||||
command: "foo -aba -cab",
|
command: "foo -aba -cab",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -300,7 +300,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long",
|
"long",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fb,
|
impl: fb,
|
||||||
command: "foo --one",
|
command: "foo --one",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -312,7 +312,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long, multiple",
|
"long, multiple",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fb,
|
impl: fb,
|
||||||
command: "foo --one --two --three",
|
command: "foo --one --two --three",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -324,7 +324,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long, multiple values",
|
"long, multiple values",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: flb,
|
impl: flb,
|
||||||
command: "foo --one --two --one",
|
command: "foo --one --two --one",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -338,7 +338,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, true",
|
"short, true",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one"),
|
impl: ShortForm(Command("foo", fb), "a", "one"),
|
||||||
command: "foo -a true",
|
command: "foo -a true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -350,7 +350,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, false",
|
"short, false",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one"),
|
impl: ShortForm(Command("foo", fb), "a", "one"),
|
||||||
command: "foo -a false",
|
command: "foo -a false",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -362,7 +362,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, with eq",
|
"short, with eq",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one"),
|
impl: ShortForm(Command("foo", fb), "a", "one"),
|
||||||
command: "foo -a=true",
|
command: "foo -a=true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -374,7 +374,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, true variant, capital",
|
"short, true variant, capital",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a","one"),
|
impl: ShortForm(Command("foo", fb), "a", "one"),
|
||||||
command: "foo -a True",
|
command: "foo -a True",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -386,7 +386,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, true variant, 1",
|
"short, true variant, 1",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one"),
|
impl: ShortForm(Command("foo", fb), "a", "one"),
|
||||||
command: "foo -a 1",
|
command: "foo -a 1",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -398,7 +398,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, false variant, 0",
|
"short, false variant, 0",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one"),
|
impl: ShortForm(Command("foo", fb), "a", "one"),
|
||||||
command: "foo -a 0",
|
command: "foo -a 0",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -410,7 +410,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, combined",
|
"short, combined",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two"),
|
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two"),
|
||||||
command: "foo -ab true",
|
command: "foo -ab true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -422,7 +422,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, combined, multiple",
|
"short, combined, multiple",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three", "d", "four"),
|
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two", "c", "three", "d", "four"),
|
||||||
command: "foo -ab true -cd true",
|
command: "foo -ab true -cd true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -434,7 +434,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long",
|
"long",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fb,
|
impl: fb,
|
||||||
command: "foo --one true",
|
command: "foo --one true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -446,7 +446,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long, false",
|
"long, false",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fb,
|
impl: fb,
|
||||||
command: "foo --one false",
|
command: "foo --one false",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -458,7 +458,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"logn, with eq",
|
"logn, with eq",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fb,
|
impl: fb,
|
||||||
command: "foo --one=true",
|
command: "foo --one=true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -469,7 +469,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long, mixed, first",
|
"long, mixed, first",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fb,
|
impl: fb,
|
||||||
command: "foo --one false --two",
|
command: "foo --one false --two",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -481,7 +481,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long, mixed, last",
|
"long, mixed, last",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fb,
|
impl: fb,
|
||||||
command: "foo --one --two false",
|
command: "foo --one --two false",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -495,7 +495,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, implicit",
|
"short, implicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one"),
|
impl: ShortForm(Command("foo", fb), "a", "one"),
|
||||||
command: "foo -a",
|
command: "foo -a",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -506,7 +506,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, explicit",
|
"short, explicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a", "one"),
|
impl: ShortForm(Command("foo", fb), "a", "one"),
|
||||||
command: "foo -a true",
|
command: "foo -a true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -518,7 +518,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, automatic positional",
|
"short, automatic positional",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fbp), "a", "one"),
|
impl: ShortForm(Command("foo", fbp), "a", "one"),
|
||||||
command: "foo -a bar",
|
command: "foo -a bar",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -530,7 +530,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, combined",
|
"short, combined",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fb), "a","one", "b", "two"),
|
impl: ShortForm(Command("foo", fb), "a", "one", "b", "two"),
|
||||||
command: "foo -ab true",
|
command: "foo -ab true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -542,7 +542,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short, combined, automatic positional",
|
"short, combined, automatic positional",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fbp), "a", "one", "b", "two"),
|
impl: ShortForm(Command("foo", fbp), "a", "one", "b", "two"),
|
||||||
command: "foo -ab bar",
|
command: "foo -ab bar",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -553,7 +553,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long, implicit",
|
"long, implicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fb,
|
impl: fb,
|
||||||
command: "foo --one",
|
command: "foo --one",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -565,7 +565,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long, explicit",
|
"long, explicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fb,
|
impl: fb,
|
||||||
command: "foo --one true",
|
command: "foo --one true",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -577,7 +577,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"long, automatic positional",
|
"long, automatic positional",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fbp,
|
impl: fbp,
|
||||||
command: "foo --one bar",
|
command: "foo --one bar",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -591,7 +591,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"basic",
|
"basic",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fp,
|
impl: fp,
|
||||||
command: "foo bar baz",
|
command: "foo bar baz",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -603,7 +603,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"explicit",
|
"explicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fp,
|
impl: fp,
|
||||||
command: "foo -- bar baz",
|
command: "foo -- bar baz",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -615,7 +615,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"mixed",
|
"mixed",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fp,
|
impl: fp,
|
||||||
command: "foo bar -- baz",
|
command: "foo bar -- baz",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -627,7 +627,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"with option",
|
"with option",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fp,
|
impl: fp,
|
||||||
command: "foo bar --second-field 42 baz",
|
command: "foo bar --second-field 42 baz",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -639,7 +639,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"with bool option at the end",
|
"with bool option at the end",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fbp,
|
impl: fbp,
|
||||||
command: "foo bar baz --one",
|
command: "foo bar baz --one",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -651,7 +651,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"with expected bool, implicit",
|
"with expected bool, implicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fbp,
|
impl: fbp,
|
||||||
command: "foo bar --one baz",
|
command: "foo bar --one baz",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -663,7 +663,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"with expected bool, explicit",
|
"with expected bool, explicit",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fbp,
|
impl: fbp,
|
||||||
command: "foo bar --one true baz",
|
command: "foo bar --one true baz",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -675,7 +675,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"option format",
|
"option format",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fbp,
|
impl: fbp,
|
||||||
command: "foo -- --one",
|
command: "foo -- --one",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -705,7 +705,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"full",
|
"full",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fs), "a", "foo", "b", "bar"),
|
impl: ShortForm(Command("foo", fs), "a", "foo", "b", "bar"),
|
||||||
command: "foo -ab --bar baz -b --qux --quux corge -- grault",
|
command: "foo -ab --bar baz -b --qux --quux corge -- grault",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -719,7 +719,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"capital letters",
|
"capital letters",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fp,
|
impl: fp,
|
||||||
command: "foo --One bar",
|
command: "foo --One bar",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -731,7 +731,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"digit in option name",
|
"digit in option name",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fd,
|
impl: fd,
|
||||||
command: "foo --one-2",
|
command: "foo --one-2",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -743,7 +743,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"dash in option name",
|
"dash in option name",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ff,
|
impl: ff,
|
||||||
command: "foo --second-field 42",
|
command: "foo --second-field 42",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -755,7 +755,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"unpexpected character",
|
"unpexpected character",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fp,
|
impl: fp,
|
||||||
command: "foo --one#",
|
command: "foo --one#",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -767,7 +767,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"invalid short option set",
|
"invalid short option set",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fp), "a", "one", "b", "one", "c", "second-field"),
|
impl: ShortForm(Command("foo", fp), "a", "one", "b", "one", "c", "second-field"),
|
||||||
command: "foo -aBc",
|
command: "foo -aBc",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -779,7 +779,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"positional separator, no value",
|
"positional separator, no value",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fp,
|
impl: fp,
|
||||||
command: "foo --one bar --",
|
command: "foo --one bar --",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -791,7 +791,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"positional separator, expecting value",
|
"positional separator, expecting value",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fp,
|
impl: fp,
|
||||||
command: "foo --one --",
|
command: "foo --one --",
|
||||||
},
|
},
|
||||||
"--one",
|
"--one",
|
||||||
@ -803,7 +803,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"shot flag set, expecting value",
|
"shot flag set, expecting value",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fp), "b", "second-field"),
|
impl: ShortForm(Command("foo", fp), "b", "second-field"),
|
||||||
command: "foo --one -b",
|
command: "foo --one -b",
|
||||||
},
|
},
|
||||||
"--one",
|
"--one",
|
||||||
@ -817,7 +817,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"bools",
|
"bools",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fl,
|
impl: fl,
|
||||||
command: "foo --one --one false --one",
|
command: "foo --one --one false --one",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -829,7 +829,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"strings",
|
"strings",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fl,
|
impl: fl,
|
||||||
command: "foo --two 1 --two 2 --two 3",
|
command: "foo --two 1 --two 2 --two 3",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -843,7 +843,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"named",
|
"named",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: Group("foo", Command("bar", ff), Command("baz", ff)),
|
impl: Group("foo", Command("bar", ff), Command("baz", ff)),
|
||||||
command: "foo baz",
|
command: "foo baz",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -855,7 +855,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"default",
|
"default",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: Group("foo", Command("bar", ff), Default(Command("baz", ff))),
|
impl: Group("foo", Command("bar", ff), Default(Command("baz", ff))),
|
||||||
command: "foo",
|
command: "foo",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -869,7 +869,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short form not defined",
|
"short form not defined",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fm,
|
impl: fm,
|
||||||
command: "foo -h",
|
command: "foo -h",
|
||||||
},
|
},
|
||||||
"foo help",
|
"foo help",
|
||||||
@ -881,7 +881,7 @@ func TestCommand(t *testing.T) {
|
|||||||
"short form not help",
|
"short form not help",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fm), "h", "one"),
|
impl: ShortForm(Command("foo", fm), "h", "one"),
|
||||||
command: "foo -h",
|
command: "foo -h",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -893,8 +893,8 @@ func TestCommand(t *testing.T) {
|
|||||||
"short form",
|
"short form",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: ShortForm(Command("foo", fm), "h", "help"),
|
impl: ShortForm(Command("foo", fm), "h", "help"),
|
||||||
command: "foo -h",
|
command: "foo -h",
|
||||||
contains: true,
|
contains: true,
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
@ -906,8 +906,8 @@ func TestCommand(t *testing.T) {
|
|||||||
"long form",
|
"long form",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fm,
|
impl: fm,
|
||||||
command: "foo --help",
|
command: "foo --help",
|
||||||
contains: true,
|
contains: true,
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
|
|||||||
@ -104,9 +104,9 @@ func TestConfig(t *testing.T) {
|
|||||||
"discard in previous doc",
|
"discard in previous doc",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fm,
|
impl: fm,
|
||||||
mergeConf: []string{"one=bar\nsecond-var=baz", "one\nsecond-var=qux"},
|
mergeConf: []string{"one=bar\nsecond-var=baz", "one\nsecond-var=qux"},
|
||||||
command: "foo",
|
command: "foo",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
";qux",
|
";qux",
|
||||||
@ -117,9 +117,9 @@ func TestConfig(t *testing.T) {
|
|||||||
"discard in previous same doc",
|
"discard in previous same doc",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fm,
|
impl: fm,
|
||||||
mergeConf: []string{"one=bar\nsecond-var=baz", "one\nsecond-var=qux\nsecond-var"},
|
mergeConf: []string{"one=bar\nsecond-var=baz", "one\nsecond-var=qux\nsecond-var"},
|
||||||
command: "foo",
|
command: "foo",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
";",
|
";",
|
||||||
@ -138,8 +138,8 @@ func TestConfig(t *testing.T) {
|
|||||||
"comments",
|
"comments",
|
||||||
testExec(
|
testExec(
|
||||||
testCase{
|
testCase{
|
||||||
impl: fm,
|
impl: fm,
|
||||||
conf: "# comment on a line\none=bar # comment after an entry",
|
conf: "# comment on a line\none=bar # comment after an entry",
|
||||||
command: "foo",
|
command: "foo",
|
||||||
},
|
},
|
||||||
"",
|
"",
|
||||||
|
|||||||
8
debug.go
8
debug.go
@ -11,5 +11,13 @@ func debug(a ...any) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notation.Fprintln(os.Stderr, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func debugw(a ...any) {
|
||||||
|
if !testing.Testing() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
notation.Fprintlnw(os.Stderr, a...)
|
notation.Fprintlnw(os.Stderr, a...)
|
||||||
}
|
}
|
||||||
|
|||||||
3
exec.go
3
exec.go
@ -10,7 +10,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func exec(stdin io.Reader, stdout, stderr io.Writer, exit func(int), cmd Cmd, conf Config, env, args []string) {
|
func exec(stdin io.Reader, stdout, stderr io.Writer, exit func(int), cmd Cmd, conf Config, env, args []string) {
|
||||||
cmd = insertHelp(cmd)
|
|
||||||
_, cmd.name = filepath.Split(args[0])
|
_, cmd.name = filepath.Split(args[0])
|
||||||
if err := validateCommand(cmd, conf); err != nil {
|
if err := validateCommand(cmd, conf); err != nil {
|
||||||
fmt.Fprintf(stderr, "program error: %v\n", err)
|
fmt.Fprintf(stderr, "program error: %v\n", err)
|
||||||
@ -37,6 +36,8 @@ func exec(stdin io.Reader, stdout, stderr io.Writer, exit func(int), cmd Cmd, co
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd = insertHelp(cmd)
|
||||||
|
|
||||||
// will need root command for the config and the env:
|
// will need root command for the config and the env:
|
||||||
rootCmd := cmd
|
rootCmd := cmd
|
||||||
cmd, fullCmd, args := selectCommand(cmd, args[1:])
|
cmd, fullCmd, args := selectCommand(cmd, args[1:])
|
||||||
|
|||||||
52
exec_test.go
52
exec_test.go
@ -9,13 +9,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
impl any
|
impl any
|
||||||
stdin string
|
stdin string
|
||||||
conf string
|
conf string
|
||||||
mergeConf []string
|
mergeConfTyped []Config
|
||||||
env string
|
mergeConf []string
|
||||||
command string
|
env string
|
||||||
contains bool
|
command string
|
||||||
|
contains bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func testExec(test testCase, err string, expect ...string) func(*testing.T) {
|
func testExec(test testCase, err string, expect ...string) func(*testing.T) {
|
||||||
@ -23,9 +24,11 @@ func testExec(test testCase, err string, expect ...string) func(*testing.T) {
|
|||||||
var exitCode int
|
var exitCode int
|
||||||
exit := func(code int) { exitCode = code }
|
exit := func(code int) { exitCode = code }
|
||||||
|
|
||||||
var stdinr io.Reader
|
var stdin io.Reader
|
||||||
if test.stdin != "" {
|
if test.stdin == "" {
|
||||||
stdinr = bytes.NewBuffer([]byte(test.stdin))
|
stdin = bytes.NewBuffer(nil)
|
||||||
|
} else {
|
||||||
|
stdin = bytes.NewBufferString(test.stdin)
|
||||||
}
|
}
|
||||||
|
|
||||||
stdout := bytes.NewBuffer(nil)
|
stdout := bytes.NewBuffer(nil)
|
||||||
@ -33,11 +36,28 @@ func testExec(test testCase, err string, expect ...string) func(*testing.T) {
|
|||||||
cmd := wrap(test.impl)
|
cmd := wrap(test.impl)
|
||||||
e := strings.Split(test.env, ";")
|
e := strings.Split(test.env, ";")
|
||||||
a := strings.Split(test.command, " ")
|
a := strings.Split(test.command, " ")
|
||||||
|
|
||||||
var conf Config
|
zeroOrOne := func(b ...bool) bool {
|
||||||
if test.conf != "" && len(test.mergeConf) > 0 {
|
var one bool
|
||||||
|
for _, bi := range b {
|
||||||
|
if bi && one {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if bi {
|
||||||
|
one = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !zeroOrOne(test.conf != "", len(test.mergeConf) > 0, len(test.mergeConfTyped) > 0) {
|
||||||
t.Fatal("test error: conflicting test config")
|
t.Fatal("test error: conflicting test config")
|
||||||
} else if test.conf != "" {
|
}
|
||||||
|
|
||||||
|
var conf Config
|
||||||
|
if test.conf != "" {
|
||||||
conf = Config{test: test.conf}
|
conf = Config{test: test.conf}
|
||||||
} else if len(test.mergeConf) > 0 {
|
} else if len(test.mergeConf) > 0 {
|
||||||
var c []Config
|
var c []Config
|
||||||
@ -46,9 +66,11 @@ func testExec(test testCase, err string, expect ...string) func(*testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conf = MergeConfig(c...)
|
conf = MergeConfig(c...)
|
||||||
|
} else if len(test.mergeConfTyped) > 0 {
|
||||||
|
conf = MergeConfig(test.mergeConfTyped...)
|
||||||
}
|
}
|
||||||
|
|
||||||
exec(stdinr, stdout, stderr, exit, cmd, conf, e, a)
|
exec(stdin, stdout, stderr, exit, cmd, conf, e, a)
|
||||||
if exitCode != 0 && err == "" {
|
if exitCode != 0 && err == "" {
|
||||||
t.Fatal("non-zero exit code:", stderr.String())
|
t.Fatal("non-zero exit code:", stderr.String())
|
||||||
}
|
}
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module code.squareroundforest.org/arpio/wand
|
|||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.squareroundforest.org/arpio/bind v0.0.0-20250903234821-f3e17035cd36
|
code.squareroundforest.org/arpio/bind v0.0.0-20250905213330-4591a086be1e
|
||||||
code.squareroundforest.org/arpio/docreflect v0.0.0-20250904132730-afd27063724e
|
code.squareroundforest.org/arpio/docreflect v0.0.0-20250904132730-afd27063724e
|
||||||
code.squareroundforest.org/arpio/notation v0.0.0-20250826181910-5140794b16b2
|
code.squareroundforest.org/arpio/notation v0.0.0-20250826181910-5140794b16b2
|
||||||
code.squareroundforest.org/arpio/treerack v0.0.0-20250820014405-1d956dcc6610
|
code.squareroundforest.org/arpio/treerack v0.0.0-20250820014405-1d956dcc6610
|
||||||
|
|||||||
10
go.sum
10
go.sum
@ -1,11 +1,5 @@
|
|||||||
code.squareroundforest.org/arpio/bind v0.0.0-20250901011104-bcadfd8b71fc h1:nu5YXVLDrRzN9Ea5agXmhxFILyVAPyoED25ksTYC9ws=
|
code.squareroundforest.org/arpio/bind v0.0.0-20250905213330-4591a086be1e h1:DkOYkD12OWMAczreQESVQF7b1KsyBQq4G700oGxNy08=
|
||||||
code.squareroundforest.org/arpio/bind v0.0.0-20250901011104-bcadfd8b71fc/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI=
|
code.squareroundforest.org/arpio/bind v0.0.0-20250905213330-4591a086be1e/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI=
|
||||||
code.squareroundforest.org/arpio/bind v0.0.0-20250903223305-8683d8ba4074 h1:OTzn0dMou+6m2rw70g7fIylQLHUTu75noAX3lbCYMqw=
|
|
||||||
code.squareroundforest.org/arpio/bind v0.0.0-20250903223305-8683d8ba4074/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI=
|
|
||||||
code.squareroundforest.org/arpio/bind v0.0.0-20250903234821-f3e17035cd36 h1:8TB3ABJVV0eEdnWl+dJ3Hg4lGe+BlgNPgcW5p9yZnrQ=
|
|
||||||
code.squareroundforest.org/arpio/bind v0.0.0-20250903234821-f3e17035cd36/go.mod h1:tTCmCwFABKNm3PO0Dclsp4zWhNQFTfg9+uSrgoarZFI=
|
|
||||||
code.squareroundforest.org/arpio/docreflect v0.0.0-20250831183400-d26ecc663a30 h1:QUCgxUEA5/ng7GwRnzb/WezmFQXSHXl48GdLJc0KC5k=
|
|
||||||
code.squareroundforest.org/arpio/docreflect v0.0.0-20250831183400-d26ecc663a30/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA=
|
|
||||||
code.squareroundforest.org/arpio/docreflect v0.0.0-20250904132730-afd27063724e h1:f7wtGAmuTYH/VTn92sBTtKhs463q+DTtW2yKgst2kl8=
|
code.squareroundforest.org/arpio/docreflect v0.0.0-20250904132730-afd27063724e h1:f7wtGAmuTYH/VTn92sBTtKhs463q+DTtW2yKgst2kl8=
|
||||||
code.squareroundforest.org/arpio/docreflect v0.0.0-20250904132730-afd27063724e/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA=
|
code.squareroundforest.org/arpio/docreflect v0.0.0-20250904132730-afd27063724e/go.mod h1:/3xQI36oJG8qLBxT2fSS61P5/+i1T64fTX9GHRh8XhA=
|
||||||
code.squareroundforest.org/arpio/notation v0.0.0-20250826181910-5140794b16b2 h1:S4mjQHL70CuzFg1AGkr0o0d+4M+ZWM0sbnlYq6f0b3I=
|
code.squareroundforest.org/arpio/notation v0.0.0-20250826181910-5140794b16b2 h1:S4mjQHL70CuzFg1AGkr0o0d+4M+ZWM0sbnlYq6f0b3I=
|
||||||
|
|||||||
361
iniparser.gen.go
361
iniparser.gen.go
File diff suppressed because one or more lines are too long
@ -1,3 +1,6 @@
|
|||||||
|
use a type cache
|
||||||
|
support unix timestamps in bind and in reflect
|
||||||
|
verify that duration can be parsed from integer strings
|
||||||
test:
|
test:
|
||||||
- nil return values
|
- nil return values
|
||||||
- options in variadic
|
- options in variadic
|
||||||
|
|||||||
24
reflect.go
24
reflect.go
@ -145,10 +145,30 @@ func compatibleTypes(t ...bind.FieldType) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch t[0] {
|
switch t[0] {
|
||||||
case bind.Any:
|
case bind.String, bind.Any:
|
||||||
return compatibleTypes(t[1:]...)
|
return compatibleTypes(t[1:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t[1] {
|
||||||
|
case bind.String, bind.Any:
|
||||||
|
return compatibleTypes(t[1:]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t[0] {
|
||||||
|
case bind.Bool:
|
||||||
|
switch t[1] {
|
||||||
|
case bind.Bool:
|
||||||
|
return compatibleTypes(t[1:]...)
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t[1] {
|
||||||
|
case bind.Bool:
|
||||||
|
return false
|
||||||
default:
|
default:
|
||||||
return t[0] == t[1] && compatibleTypes(t[1:]...)
|
return compatibleTypes(t[1:]...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package wand
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.squareroundforest.org/arpio/wand/internal/tests/testlib"
|
"code.squareroundforest.org/arpio/wand/internal/tests/testlib"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -96,22 +97,94 @@ func TestReflect(t *testing.T) {
|
|||||||
t.Run("compatible types", func(t *testing.T) {
|
t.Run("compatible types", func(t *testing.T) {
|
||||||
type s0 struct {
|
type s0 struct {
|
||||||
FooBar int
|
FooBar int
|
||||||
Foo struct{ Bar string }
|
Foo struct{ Bar bool }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type s0a struct {
|
||||||
|
FooBar bool
|
||||||
|
Foo struct{ Bar int }
|
||||||
|
}
|
||||||
|
|
||||||
type s1 struct {
|
type s1 struct {
|
||||||
FooBar int
|
FooBar int
|
||||||
Foo struct{ Bar int }
|
Foo struct{ Bar int }
|
||||||
}
|
}
|
||||||
f := func(a s0) int { return a.FooBar + len(a.Foo.Bar) }
|
|
||||||
|
f := func(a s0) string { return fmt.Sprint(a.FooBar) + fmt.Sprint(a.Foo.Bar) }
|
||||||
|
fa := func(a s0a) string { return fmt.Sprint(a.FooBar) + fmt.Sprint(a.Foo.Bar) }
|
||||||
g := func(a s1) int { return a.FooBar + a.Foo.Bar }
|
g := func(a s1) int { return a.FooBar + a.Foo.Bar }
|
||||||
t.Run("incompatible", testExec(testCase{impl: f, command: "foo --foo-bar 42"}, "duplicate fields with different types", ""))
|
t.Run("incompatible", testExec(testCase{impl: f, command: "foo --foo-bar 42"}, "duplicate fields with different types", ""))
|
||||||
|
t.Run("incompatible", testExec(testCase{impl: fa, command: "foo --foo-bar 42"}, "duplicate fields with different types", ""))
|
||||||
t.Run("compatible", testExec(testCase{impl: g, command: "foo --foo-bar 42"}, "", "84"))
|
t.Run("compatible", testExec(testCase{impl: g, command: "foo --foo-bar 42"}, "", "84"))
|
||||||
|
|
||||||
type s2 struct {
|
type s2 struct {
|
||||||
FooBar any
|
FooBar any
|
||||||
Foo struct{ Bar int }
|
Foo struct{ Bar int }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type s2a struct {
|
||||||
|
FooBar int
|
||||||
|
Foo struct{ Bar any }
|
||||||
|
}
|
||||||
|
|
||||||
h := func(a s2) int { return len(a.FooBar.(string)) + a.Foo.Bar }
|
h := func(a s2) int { return len(a.FooBar.(string)) + a.Foo.Bar }
|
||||||
t.Run("any interface", testExec(testCase{impl: h, command: "foo --foo-bar 42"}, "", "44"))
|
t.Run("any interface", testExec(testCase{impl: h, command: "foo --foo-bar 42"}, "", "44"))
|
||||||
|
ha := func(a s2a) int { return a.FooBar + len(a.Foo.Bar.(string)) }
|
||||||
|
t.Run("any interface", testExec(testCase{impl: ha, command: "foo --foo-bar 42"}, "", "44"))
|
||||||
|
|
||||||
|
type s3 struct {
|
||||||
|
FooBar string
|
||||||
|
Foo struct{ Bar int }
|
||||||
|
}
|
||||||
|
|
||||||
|
i := func(a s2) string { return fmt.Sprint(a.FooBar) + fmt.Sprint(a.Foo.Bar) }
|
||||||
|
t.Run("string", testExec(testCase{impl: i, command: "foo --foo-bar 42"}, "", "4242"))
|
||||||
|
|
||||||
|
type s4 struct {
|
||||||
|
FooBar bool
|
||||||
|
Foo struct{ Bar bool }
|
||||||
|
}
|
||||||
|
|
||||||
|
j := func(a s4) string { return fmt.Sprint(a.FooBar) + fmt.Sprint(a.Foo.Bar) }
|
||||||
|
t.Run("bool", testExec(testCase{impl: j, command: "foo --foo-bar"}, "", "truetrue"))
|
||||||
|
|
||||||
|
type s5 struct {
|
||||||
|
FooBar time.Duration
|
||||||
|
Foo struct{ Bar time.Duration }
|
||||||
|
}
|
||||||
|
|
||||||
|
k := func(a s5) string { return fmt.Sprint(a.FooBar) + fmt.Sprint(a.Foo.Bar) }
|
||||||
|
t.Run("duration and duration", testExec(testCase{impl: k, command: "foo --foo-bar 9s"}, "", "9s9s"))
|
||||||
|
|
||||||
|
type s6 struct {
|
||||||
|
FooBar time.Duration
|
||||||
|
Foo struct{ Bar int }
|
||||||
|
}
|
||||||
|
|
||||||
|
l := func(a s6) string { return fmt.Sprint(a.FooBar) + fmt.Sprint(a.Foo.Bar) }
|
||||||
|
t.Run(
|
||||||
|
"duration and numeric",
|
||||||
|
testExec(testCase{impl: l, command: "foo --foo-bar 9000000000"}, "", "9s9000000000"),
|
||||||
|
)
|
||||||
|
|
||||||
|
type s7 struct {
|
||||||
|
FooBar time.Time
|
||||||
|
Foo struct{ Bar time.Time }
|
||||||
|
}
|
||||||
|
|
||||||
|
m := func(a s7) string { return fmt.Sprint(a.FooBar.Unix()) + fmt.Sprint(a.Foo.Bar.Unix()) }
|
||||||
|
t.Run("time and time", testExec(testCase{impl: m, command: "foo --foo-bar 1757097011"}, "", "17570970111757097011"))
|
||||||
|
|
||||||
|
type s8 struct {
|
||||||
|
FooBar time.Time
|
||||||
|
Foo struct{ Bar int }
|
||||||
|
}
|
||||||
|
|
||||||
|
n := func(a s8) string { return fmt.Sprint(a.FooBar.Unix()) + fmt.Sprint(a.Foo.Bar) }
|
||||||
|
t.Run(
|
||||||
|
"time and numeric",
|
||||||
|
testExec(testCase{impl: n, command: "foo --foo-bar 1757097011"}, "", "17570970111757097011"),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("bind failure", func(t *testing.T) {
|
t.Run("bind failure", func(t *testing.T) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user