package wand import ( "bytes" "io" "testing" ) func TestReflect(t *testing.T) { t.Run("pack and unpack", func(t *testing.T) { f := func(a int) int { return a } t.Run("no need to pack", testExec(testCase{impl: f, command: "foo 42"}, "", "42")) g := func(a *int) int { return *a } t.Run("pointer", testExec(testCase{impl: g, command: "foo 42"}, "", "42")) h := func(a []int) int { return a[0] } t.Run("slice", testExec(testCase{impl: h, command: "foo 42"}, "", "42")) i := func(a *[]*[]int) int { return (*((*a)[0]))[0] } t.Run("pointer and slice", testExec(testCase{impl: i, command: "foo 42"}, "", "42")) }) t.Run("io params", func(t *testing.T) { f := func(in io.Reader) string { b, _ := io.ReadAll(in); return string(b) } t.Run("in", testExec(testCase{impl: f, stdin: "foo", command: "bar"}, "", "foo")) g := func(a string) io.Reader { return bytes.NewBufferString(a) } t.Run("out", testExec(testCase{impl: g, command: "foo bar"}, "", "bar")) h := func(out io.Writer, a string) { out.Write([]byte(a)) } t.Run("stdout param", testExec(testCase{impl: h, command: "foo bar"}, "", "bar")) }) t.Run("struct param", func(t *testing.T) { f := func(s struct{ Bar int }) int { return s.Bar } t.Run("basic", testExec(testCase{impl: f, command: "foo --bar 42"}, "", "42")) }) t.Run("basic types", func(t *testing.T) { t.Run("signed int", func(t *testing.T) { f := func(a int) int { return a } t.Run("decimal", testExec(testCase{impl: f, command: "foo 42"}, "", "42")) t.Run("hexa", testExec(testCase{impl: f, command: "foo 0x2a"}, "", "42")) t.Run("octal", testExec(testCase{impl: f, command: "foo 052"}, "", "42")) t.Run("binary", testExec(testCase{impl: f, command: "foo 0b101010"}, "", "42")) t.Run("fail", testExec(testCase{impl: f, command: "foo bar"}, "expecting int", "")) g := func(a int32) int32 { return a } t.Run("sized", testExec(testCase{impl: g, command: "foo 42"}, "", "42")) }) t.Run("unsigned int", func(t *testing.T) { f := func(a uint) uint { return a } t.Run("decimal", testExec(testCase{impl: f, command: "foo 42"}, "", "42")) t.Run("hexa", testExec(testCase{impl: f, command: "foo 0x2a"}, "", "42")) t.Run("octal", testExec(testCase{impl: f, command: "foo 052"}, "", "42")) t.Run("binary", testExec(testCase{impl: f, command: "foo 0b101010"}, "", "42")) t.Run("fail", testExec(testCase{impl: f, command: "foo bar"}, "expecting uint", "")) g := func(a uint32) uint32 { return a } t.Run("sized", testExec(testCase{impl: g, command: "foo 42"}, "", "42")) }) t.Run("bool", func(t *testing.T) { f := func(a bool) bool { return a } t.Run("true", testExec(testCase{impl: f, command: "foo true"}, "", "true")) t.Run("false", testExec(testCase{impl: f, command: "foo false"}, "", "false")) t.Run("fail", testExec(testCase{impl: f, command: "foo yes"}, "expecting bool", "")) }) t.Run("float", func(t *testing.T) { f := func(a float64) float64 { return a } t.Run("accept", testExec(testCase{impl: f, command: "foo 3.14"}, "", "3.14")) t.Run("fail", testExec(testCase{impl: f, command: "foo bar"}, "expecting float", "")) }) t.Run("string", func(t *testing.T) { f := func(a string) string { return a } t.Run("accept", testExec(testCase{impl: f, command: "foo bar"}, "", "bar")) }) t.Run("interface", func(t *testing.T) { f := func(a any) any { return a } t.Run("any", testExec(testCase{impl: f, command: "foo bar"}, "", "bar")) type i interface{ Foo() } g := func(a i) any { return a } t.Run("unscannable", testExec(testCase{impl: g, command: "foo bar"}, "non-empty interface", "")) }) }) }