package tools import ( "bytes" "code.squareroundforest.org/arpio/notation" "fmt" "os" "path/filepath" "testing" ) func TestExec(t *testing.T) { wd, err := os.Getwd() if err != nil { t.Fatal(err) } cacheDir := filepath.Join(wd, "../internal/tests/tmpdir") selfReplace := filepath.Join(wd, "..") baseOpt := ExecOptions{ ClearCache: true, CacheDir: cacheDir, ReplaceModule: []string{fmt.Sprintf("%s=%s", selfPkg, selfReplace)}, } t.Run("stdin", func(t *testing.T) { var stdout, stderr bytes.Buffer in := bytes.NewBufferString("strings.Split 1,2,3 ,") o := baseOpt o.Import = []string{"strings"} if err := execInput(o, in, &stdout, &stderr); err != nil { t.Fatal(err) } if stderr.String() != "" { t.Fatal(stderr.String()) } if stdout.String() != "1\n2\n3\n" { t.Fatal(stdout.String()) } }) t.Run("stdin multiple lines", func(t *testing.T) { var stdout, stderr bytes.Buffer in := bytes.NewBufferString("strings.Split 1,2,3 ,\nstrings.Split 4,5,6 ,") o := baseOpt o.Import = []string{"strings"} if err := execInput(o, in, &stdout, &stderr); err != nil { t.Fatal(err) } if stderr.String() != "" { t.Fatal(stderr.String()) } if stdout.String() != "1\n2\n3\n4\n5\n6\n" { t.Fatal(stdout.String()) } }) t.Run("args", func(t *testing.T) { var stdin, stdout, stderr bytes.Buffer o := baseOpt o.Import = []string{"strings"} if err := execInput(o, &stdin, &stdout, &stderr, "strings.Split", "1,2,3", ","); err != nil { t.Fatal(err) } if stderr.String() != "" { t.Fatal(stderr.String()) } if stdout.String() != "1\n2\n3\n" { t.Fatal(stdout.String()) } }) t.Run("inline import", func(t *testing.T) { var stdin, stdout, stderr bytes.Buffer o := baseOpt o.Import = []string{".=strings"} if err := execInput(o, &stdin, &stdout, &stderr, "Split", "1,2,3", ","); err != nil { t.Fatal(err) } if stderr.String() != "" { t.Fatal(stderr.String()) } if stdout.String() != "1\n2\n3\n" { t.Fatal(stdout.String()) } }) t.Run("named import", func(t *testing.T) { var stdin, stdout, stderr bytes.Buffer o := baseOpt o.Import = []string{"str=strings"} if err := execInput(o, &stdin, &stdout, &stderr, "str.Split", "1,2,3", ","); err != nil { t.Fatal(err) } if stderr.String() != "" { t.Fatal(stderr.String()) } if stdout.String() != "1\n2\n3\n" { t.Fatal(stdout.String()) } }) t.Run("io args", func(t *testing.T) { var stdout, stderr bytes.Buffer in := bytes.NewBuffer([]byte{0, 1, 2}) o := baseOpt o.Import = []string{"io", "bytes"} expr := `func(in io.Reader) (out io.Reader) { out = bytes.NewBuffer(nil) buf := make([]byte, 1) for { n, err := in.Read(buf) if n == 1 { buf[0] = buf[0] * 2 out.(io.Writer).Write(buf) } if err != nil { return out } } return out }` if err := execInput(o, in, &stdout, &stderr, expr); err != nil { t.Log(stderr.String()) t.Fatal(err) } if stderr.String() != "" { t.Fatal(stderr.String()) } if stdout.Len() != 3 || stdout.Bytes()[0] != 0 || stdout.Bytes()[1] != 2 || stdout.Bytes()[2] != 4 { t.Fatal(notation.Sprint(stdout.Bytes())) } }) t.Run("escape", func(t *testing.T) { t.Run("full", func(t *testing.T) { var stdout, stderr bytes.Buffer in := bytes.NewBufferString("'func(a string) { println(a) }' 'foo'") if err := execInput(baseOpt, in, &stdout, &stderr); err != nil { t.Log(stderr.String()) t.Fatal(err) } if stderr.String() != "foo\n" { t.Fatal(stderr.String()) } if stdout.String() != "" { t.Fatal(stdout.String()) } }) t.Run("one", func(t *testing.T) { var stdout, stderr bytes.Buffer in := bytes.NewBufferString("'func(a string) { println(a) }' foo\\ bar") if err := execInput(baseOpt, in, &stdout, &stderr); err != nil { t.Log(stderr.String()) t.Fatal(err) } if stderr.String() != "foo bar\n" { t.Fatal(stderr.String()) } if stdout.String() != "" { t.Fatal(stdout.String()) } }) t.Run("one and partial", func(t *testing.T) { var stdout, stderr bytes.Buffer in := bytes.NewBufferString("'func(a string) { println(a) }' \"\\'foo\\'\"") if err := execInput(baseOpt, in, &stdout, &stderr); err != nil { t.Log(stderr.String()) t.Fatal(err) } if stderr.String() != "'foo'\n" { t.Fatal(stderr.String()) } if stdout.String() != "" { t.Fatal(stdout.String()) } }) }) }