package wand import ( "errors" "io" "testing" ) func TestApply(t *testing.T) { t.Run("input", func(t *testing.T) { type s0 struct { Foo string Bar string } type s2 struct { Foo bool Bar bool } f0 := func(a s0) string { return a.Foo + a.Bar } f0a := func(a ...s0) int { return len(a) } f0b := func(a *s0) string { return a.Foo + a.Bar } f0c := func(a []s0) int { return len(a) } f0d := func(a *[]**s0) int { return len(*a) } f0io := func(out io.Writer, a s0, in io.Reader) { io.Copy(out, in); out.Write([]byte(a.Foo + a.Bar)) } f1 := func(a, b, c int) int { return a + b + c } f1a := func(a, b int, c ...int) int { return a + b + len(c) } f1b := func(a, b, c **int) int { return **a + **b + **c } f1c := func(a, b, c []int) int { return a[0] + b[0] + c[0] } f1d := func(a, b, c **[]*int) int { return *(**a)[0] + *(**b)[0] + *(**c)[0] } f2 := func(a s2) bool { return a.Foo != a.Bar } t.Run("config", testExec(testCase{impl: f0, command: "foo", conf: "foo=bar"}, "", "bar")) t.Run("env", testExec(testCase{impl: f0, command: "foo", env: "foo_foo=bar"}, "", "bar")) t.Run("options", testExec(testCase{impl: f0, command: "foo --foo bar"}, "", "bar")) t.Run( "env overrides config", testExec( testCase{impl: f0, command: "foo", conf: "foo=bar\nbar=baz", env: "foo_foo=qux"}, "", "quxbaz", ), ) t.Run( "options override env and config", testExec( testCase{impl: f0, command: "foo --bar quux", conf: "foo=bar\nbar=baz", env: "foo_foo=qux"}, "", "quxquux", ), ) t.Run("variadic structure not set", testExec(testCase{impl: f0a, command: "foo"}, "", "0")) t.Run( "variadic structure from env", testExec(testCase{impl: f0a, command: "foo", env: "foo_foo=bar"}, "", "1"), ) t.Run( "variadic structure from options", testExec(testCase{impl: f0a, command: "foo --foo bar"}, "", "1"), ) t.Run( "variadic with multiple entries not allowed", testExec(testCase{impl: f0a, command: "foo --foo bar --foo baz"}, "expected only one value", ""), ) t.Run( "pointer", testExec(testCase{impl: f0b, command: "foo --foo bar"}, "", "bar"), ) t.Run( "list", testExec(testCase{impl: f0c, command: "foo --foo bar"}, "", "1"), ) t.Run( "list with multiple entries not allowed", testExec(testCase{impl: f0c, command: "foo --foo bar --foo baz"}, "expected only one value", ""), ) t.Run( "variadic list pointer", testExec(testCase{impl: f0d, command: "foo --foo bar"}, "", "1"), ) t.Run( "reader and writer set", testExec( testCase{impl: f0io, stdin: "foobar", command: "foo --foo baz --bar qux"}, "", "foobarbazqux", ), ) t.Run("positional", testExec(testCase{impl: f1, command: "foo 1 2 3"}, "", "6")) t.Run( "variadic positional", testExec(testCase{impl: f1a, command: "foo 1 2 3 4 5"}, "", "6"), ) t.Run("boolean options", testExec(testCase{impl: f2, command: "foo --foo --bar"}, "", "false")) t.Run( "short form options", testExec( testCase{impl: ShortForm(Command("foo", f0), "f", "foo"), command: "foo -f bar"}, "", "bar", ), ) t.Run("positional in pointer", testExec(testCase{impl: f1b, command: "foo 1 2 3"}, "", "6")) t.Run("positional in pointer", testExec(testCase{impl: f1c, command: "foo 1 2 3"}, "", "6")) t.Run("positional in pointer", testExec(testCase{impl: f1d, command: "foo 1 2 3"}, "", "6")) }) t.Run("output", func(t *testing.T) { f0 := func() {} f1 := func() int { return 42 } f2 := func() (int, int, int) { return 21, 42, 84 } f3 := func() error { return nil } f4 := func() error { return errors.New("test error") } f5 := func() (int, int, error) { return 42, 84, nil } f6 := func() (int, int, error) { return 42, 84, errors.New("test error") } t.Run("no output", testExec(testCase{impl: f0, command: "foo"}, "", "")) t.Run("non-error output", testExec(testCase{impl: f1, command: "foo"}, "", "42")) t.Run("multiple outputs", testExec(testCase{impl: f2, command: "foo"}, "", "21\n42\n84")) t.Run("error output no error", testExec(testCase{impl: f3, command: "foo"}, "", "")) t.Run("error output error", testExec(testCase{impl: f4, command: "foo"}, "test error", "")) t.Run("mixed output no error", testExec(testCase{impl: f5, command: "foo"}, "", "42\n84")) t.Run("mixed output error", testExec(testCase{impl: f6, command: "foo"}, "test error", "")) }) }