github.com/traefik/yaegi@v0.15.1/interp/interp_eval_test.go (about)

     1  package interp_test
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"context"
     7  	"fmt"
     8  	"go/build"
     9  	"go/parser"
    10  	"io"
    11  	"log"
    12  	"net/http"
    13  	"os"
    14  	"path/filepath"
    15  	"reflect"
    16  	"runtime"
    17  	"strconv"
    18  	"strings"
    19  	"sync"
    20  	"testing"
    21  	"time"
    22  
    23  	"github.com/traefik/yaegi/interp"
    24  	"github.com/traefik/yaegi/stdlib"
    25  )
    26  
    27  func init() { log.SetFlags(log.Lshortfile) }
    28  
    29  // testCase represents an interpreter test case.
    30  // Care must be taken when defining multiple test cases within the same interpreter
    31  // context, as all declarations occur in the global scope and are therefore
    32  // shared between multiple test cases.
    33  // Hint: use different variables or package names in testcases to keep them uncoupled.
    34  type testCase struct {
    35  	desc, src, res, err string
    36  	skip                string // if not empty, skip this test case (used in case of known error)
    37  	pre                 func() // functions to execute prior eval src, or nil
    38  }
    39  
    40  func TestEvalArithmetic(t *testing.T) {
    41  	i := interp.New(interp.Options{})
    42  	runTests(t, i, []testCase{
    43  		{desc: "add_II", src: "2 + 3", res: "5"},
    44  		{desc: "add_FI", src: "2.3 + 3", res: "5.3"},
    45  		{desc: "add_IF", src: "2 + 3.3", res: "5.3"},
    46  		{desc: "add_SS", src: `"foo" + "bar"`, res: "foobar"},
    47  		{desc: "add_SI", src: `"foo" + 1`, err: "1:28: invalid operation: mismatched types untyped string and untyped int"},
    48  		{desc: "sub_SS", src: `"foo" - "bar"`, err: "1:28: invalid operation: operator - not defined on untyped string"},
    49  		{desc: "sub_II", src: "7 - 3", res: "4"},
    50  		{desc: "sub_FI", src: "7.2 - 3", res: "4.2"},
    51  		{desc: "sub_IF", src: "7 - 3.2", res: "3.8"},
    52  		{desc: "mul_II", src: "2 * 3", res: "6"},
    53  		{desc: "mul_FI", src: "2.2 * 3", res: "6.6"},
    54  		{desc: "mul_IF", src: "3 * 2.2", res: "6.6"},
    55  		{desc: "quo_Z", src: "3 / 0", err: "1:28: invalid operation: division by zero"},
    56  		{desc: "rem_FI", src: "8.2 % 4", err: "1:28: invalid operation: operator % not defined on untyped float"},
    57  		{desc: "rem_Z", src: "8 % 0", err: "1:28: invalid operation: division by zero"},
    58  		{desc: "shl_II", src: "1 << 8", res: "256"},
    59  		{desc: "shl_IN", src: "1 << -1", err: "1:28: invalid operation: shift count type untyped int, must be integer"},
    60  		{desc: "shl_IF", src: "1 << 1.0", res: "2"},
    61  		{desc: "shl_IF1", src: "1 << 1.1", err: "1:28: invalid operation: shift count type untyped float, must be integer"},
    62  		{desc: "shl_IF2", src: "1.0 << 1", res: "2"},
    63  		{desc: "shr_II", src: "1 >> 8", res: "0"},
    64  		{desc: "shr_IN", src: "1 >> -1", err: "1:28: invalid operation: shift count type untyped int, must be integer"},
    65  		{desc: "shr_IF", src: "1 >> 1.0", res: "0"},
    66  		{desc: "shr_IF1", src: "1 >> 1.1", err: "1:28: invalid operation: shift count type untyped float, must be integer"},
    67  		{desc: "neg_I", src: "-2", res: "-2"},
    68  		{desc: "pos_I", src: "+2", res: "2"},
    69  		{desc: "bitnot_I", src: "^2", res: "-3"},
    70  		{desc: "bitnot_F", src: "^0.2", err: "1:28: invalid operation: operator ^ not defined on untyped float"},
    71  		{desc: "not_B", src: "!false", res: "true"},
    72  		{desc: "not_I", src: "!0", err: "1:28: invalid operation: operator ! not defined on untyped int"},
    73  	})
    74  }
    75  
    76  func TestEvalShift(t *testing.T) {
    77  	i := interp.New(interp.Options{})
    78  	runTests(t, i, []testCase{
    79  		{src: "a, b, m := uint32(1), uint32(2), uint32(0); m = a + (1 << b)", res: "5"},
    80  		{src: "c := uint(1); d := uint64(+(-(1 << c)))", res: "18446744073709551614"},
    81  		{src: "e, f := uint32(0), uint32(0); f = 1 << -(e * 2)", res: "1"},
    82  		{src: "p := uint(0xdead); byte((1 << (p & 7)) - 1)", res: "31"},
    83  		{pre: func() { eval(t, i, "const k uint = 1 << 17") }, src: "int(k)", res: "131072"},
    84  	})
    85  }
    86  
    87  func TestOpVarConst(t *testing.T) {
    88  	i := interp.New(interp.Options{})
    89  	runTests(t, i, []testCase{
    90  		{pre: func() { eval(t, i, "const a uint = 8 + 2") }, src: "a", res: "10"},
    91  		{src: "b := uint(5); a+b", res: "15"},
    92  		{src: "b := uint(5); b+a", res: "15"},
    93  		{src: "b := uint(5); b>a", res: "false"},
    94  		{src: "const maxlen = cap(aa); var aa = []int{1,2}", err: "1:20: constant definition loop"},
    95  	})
    96  }
    97  
    98  func TestEvalStar(t *testing.T) {
    99  	i := interp.New(interp.Options{})
   100  	runTests(t, i, []testCase{
   101  		{src: `a := &struct{A int}{1}; b := *a`, res: "{1}"},
   102  		{src: `a := struct{A int}{1}; b := *a`, err: "1:57: invalid operation: cannot indirect \"a\""},
   103  	})
   104  }
   105  
   106  func TestEvalAssign(t *testing.T) {
   107  	i := interp.New(interp.Options{})
   108  	if err := i.Use(interp.Exports{
   109  		"testpkg/testpkg": {
   110  			"val": reflect.ValueOf(int64(11)),
   111  		},
   112  	}); err != nil {
   113  		t.Fatal(err)
   114  	}
   115  
   116  	_, e := i.Eval(`import "testpkg"`)
   117  	if e != nil {
   118  		t.Fatal(e)
   119  	}
   120  
   121  	runTests(t, i, []testCase{
   122  		{src: `a := "Hello"; a += " world"`, res: "Hello world"},
   123  		{src: `b := "Hello"; b += 1`, err: "1:42: invalid operation: mismatched types string and untyped int"},
   124  		{src: `c := "Hello"; c -= " world"`, err: "1:42: invalid operation: operator -= not defined on string"},
   125  		{src: "e := 64.4; e %= 64", err: "1:39: invalid operation: operator %= not defined on float64"},
   126  		{src: "f := int64(3.2)", err: "1:39: cannot convert expression of type untyped float to type int64"},
   127  		{src: "g := 1; g <<= 8", res: "256"},
   128  		{src: "h := 1; h >>= 8", res: "0"},
   129  		{src: "i := 1; j := &i; (*j) = 2", res: "2"},
   130  		{src: "i64 := testpkg.val; i64 == 11", res: "true"},
   131  		{pre: func() { eval(t, i, "k := 1") }, src: `k := "Hello world"`, res: "Hello world"}, // allow reassignment in subsequent evaluations
   132  		{src: "_ = _", err: "1:28: cannot use _ as value"},
   133  		{src: "j := true || _", err: "1:33: cannot use _ as value"},
   134  		{src: "j := true && _", err: "1:33: cannot use _ as value"},
   135  		{src: "j := interface{}(int(1)); j.(_)", err: "1:54: cannot use _ as value"},
   136  		{src: "ff := func() (a, b, c int) {return 1, 2, 3}; x, y, x := ff()", err: "1:73: x repeated on left side of :="},
   137  		{src: "xx := 1; xx, _ := 2, 3", err: "1:37: no new variables on left side of :="},
   138  		{src: "1 = 2", err: "1:28: cannot assign to 1 (untyped int constant)"},
   139  	})
   140  }
   141  
   142  func TestEvalBuiltin(t *testing.T) {
   143  	i := interp.New(interp.Options{})
   144  	runTests(t, i, []testCase{
   145  		{src: `a := []int{}; a = append(a, 1); a`, res: "[1]"},
   146  		{src: `b := []int{1}; b = append(a, 2, 3); b`, res: "[1 2 3]"},
   147  		{src: `c := []int{1}; d := []int{2, 3}; c = append(c, d...); c`, res: "[1 2 3]"},
   148  		{src: `string(append([]byte("hello "), "world"...))`, res: "hello world"},
   149  		{src: `e := "world"; string(append([]byte("hello "), e...))`, res: "hello world"},
   150  		{src: `b := []int{1}; b = append(1, 2, 3); b`, err: "1:54: first argument to append must be slice; have untyped int"},
   151  		{src: `a1 := []int{0,1,2}; append(a1)`, res: "[0 1 2]"},
   152  		{src: `append(nil)`, err: "first argument to append must be slice; have nil"},
   153  		{src: `g := len(a)`, res: "1"},
   154  		{src: `g := cap(a)`, res: "1"},
   155  		{src: `g := len("test")`, res: "4"},
   156  		{src: `g := len(map[string]string{"a": "b"})`, res: "1"},
   157  		{src: `n := len()`, err: "not enough arguments in call to len"},
   158  		{src: `n := len([]int, 0)`, err: "too many arguments for len"},
   159  		{src: `g := cap("test")`, err: "1:37: invalid argument for cap"},
   160  		{src: `g := cap(map[string]string{"a": "b"})`, err: "1:37: invalid argument for cap"},
   161  		{src: `h := make(chan int, 1); close(h); len(h)`, res: "0"},
   162  		{src: `close(a)`, err: "1:34: invalid operation: non-chan type []int"},
   163  		{src: `h := make(chan int, 1); var i <-chan int = h; close(i)`, err: "1:80: invalid operation: cannot close receive-only channel"},
   164  		{src: `j := make([]int, 2)`, res: "[0 0]"},
   165  		{src: `j := make([]int, 2, 3)`, res: "[0 0]"},
   166  		{src: `j := make(int)`, err: "1:38: cannot make int; type must be slice, map, or channel"},
   167  		{src: `j := make([]int)`, err: "1:33: not enough arguments in call to make"},
   168  		{src: `j := make([]int, 0, 1, 2)`, err: "1:33: too many arguments for make"},
   169  		{src: `j := make([]int, 2, 1)`, err: "1:33: len larger than cap in make"},
   170  		{src: `j := make([]int, "test")`, err: "1:45: cannot convert \"test\" to int"},
   171  		{src: `k := []int{3, 4}; copy(k, []int{1,2}); k`, res: "[1 2]"},
   172  		{src: `f := []byte("Hello"); copy(f, "world"); string(f)`, res: "world"},
   173  		{src: `copy(g, g)`, err: "1:28: copy expects slice arguments"},
   174  		{src: `copy(a, "world")`, err: "1:28: arguments to copy have different element types []int and untyped string"},
   175  		{src: `l := map[string]int{"a": 1, "b": 2}; delete(l, "a"); l`, res: "map[b:2]"},
   176  		{src: `delete(a, 1)`, err: "1:35: first argument to delete must be map; have []int"},
   177  		{src: `l := map[string]int{"a": 1, "b": 2}; delete(l, 1)`, err: "1:75: cannot use untyped int as type string in delete"},
   178  		{src: `a := []int{1,2}; println(a...)`, err: "invalid use of ... with builtin println"},
   179  		{src: `m := complex(3, 2); real(m)`, res: "3"},
   180  		{src: `m := complex(3, 2); imag(m)`, res: "2"},
   181  		{src: `m := complex("test", 2)`, err: "1:33: invalid types string and int"},
   182  		{src: `imag("test")`, err: "1:33: cannot convert untyped string to untyped complex"},
   183  		{src: `imag(a)`, err: "1:33: invalid argument type []int for imag"},
   184  		{src: `real(a)`, err: "1:33: invalid argument type []int for real"},
   185  		{src: `t := map[int]int{}; t[123]++; t`, res: "map[123:1]"},
   186  		{src: `t := map[int]int{}; t[123]--; t`, res: "map[123:-1]"},
   187  		{src: `t := map[int]int{}; t[123] += 1; t`, res: "map[123:1]"},
   188  		{src: `t := map[int]int{}; t[123] -= 1; t`, res: "map[123:-1]"},
   189  		{src: `println("hello", _)`, err: "1:28: cannot use _ as value"},
   190  		{src: `f := func() complex64 { return complex(0, 0) }()`, res: "(0+0i)"},
   191  		{src: `f := func() float32 { return real(complex(2, 1)) }()`, res: "2"},
   192  		{src: `f := func() int8 { return imag(complex(2, 1)) }()`, res: "1"},
   193  	})
   194  }
   195  
   196  func TestEvalDecl(t *testing.T) {
   197  	i := interp.New(interp.Options{})
   198  	runTests(t, i, []testCase{
   199  		{pre: func() { eval(t, i, "var i int = 2") }, src: "i", res: "2"},
   200  		{pre: func() { eval(t, i, "var j, k int = 2, 3") }, src: "j", res: "2"},
   201  		{pre: func() { eval(t, i, "var l, m int = 2, 3") }, src: "k", res: "3"},
   202  		{pre: func() { eval(t, i, "func f() int {return 4}") }, src: "f()", res: "4"},
   203  		{pre: func() { eval(t, i, `package foo; var I = 2`) }, src: "foo.I", res: "2"},
   204  		{pre: func() { eval(t, i, `package foo; func F() int {return 5}`) }, src: "foo.F()", res: "5"},
   205  	})
   206  }
   207  
   208  func TestEvalDeclWithExpr(t *testing.T) {
   209  	i := interp.New(interp.Options{})
   210  	runTests(t, i, []testCase{
   211  		{src: `a1 := ""; var a2 int; a2 = 2`, res: "2"},
   212  		{src: `b1 := ""; const b2 = 2; b2`, res: "2"},
   213  		{src: `c1 := ""; var c2, c3 [8]byte; c3[3]`, res: "0"},
   214  	})
   215  }
   216  
   217  func TestEvalTypeSpec(t *testing.T) {
   218  	i := interp.New(interp.Options{})
   219  	runTests(t, i, []testCase{
   220  		{src: `type _ struct{}`, err: "1:19: cannot use _ as value"},
   221  		{src: `a := struct{a, _ int}{32, 0}`, res: "{32 0}"},
   222  		{src: "type A int; type A = string", err: "1:31: A redeclared in this block"},
   223  		{src: "type B int; type B string", err: "1:31: B redeclared in this block"},
   224  	})
   225  }
   226  
   227  func TestEvalFunc(t *testing.T) {
   228  	i := interp.New(interp.Options{})
   229  	runTests(t, i, []testCase{
   230  		{src: `(func () string {return "ok"})()`, res: "ok"},
   231  		{src: `(func () (res string) {res = "ok"; return})()`, res: "ok"},
   232  		{src: `(func () int {f := func() (a, b int) {a, b = 3, 4; return}; x, y := f(); return x+y})()`, res: "7"},
   233  		{src: `(func () int {f := func() (a int, b, c int) {a, b, c = 3, 4, 5; return}; x, y, z := f(); return x+y+z})()`, res: "12"},
   234  		{src: `(func () int {f := func() (a, b, c int) {a, b, c = 3, 4, 5; return}; x, y, z := f(); return x+y+z})()`, res: "12"},
   235  		{src: `func f() int { return _ }`, err: "1:29: cannot use _ as value"},
   236  		{src: `(func (x int) {})(_)`, err: "1:28: cannot use _ as value"},
   237  	})
   238  }
   239  
   240  func TestEvalImport(t *testing.T) {
   241  	i := interp.New(interp.Options{})
   242  	if err := i.Use(stdlib.Symbols); err != nil {
   243  		t.Fatal(err)
   244  	}
   245  	runTests(t, i, []testCase{
   246  		{pre: func() { eval(t, i, `import "time"`) }, src: "2 * time.Second", res: "2s"},
   247  	})
   248  }
   249  
   250  func TestEvalStdout(t *testing.T) {
   251  	var out, err bytes.Buffer
   252  	i := interp.New(interp.Options{Stdout: &out, Stderr: &err})
   253  	if err := i.Use(stdlib.Symbols); err != nil {
   254  		t.Fatal(err)
   255  	}
   256  	_, e := i.Eval(`import "fmt"; func main() { fmt.Println("hello") }`)
   257  	if e != nil {
   258  		t.Fatal(e)
   259  	}
   260  	wanted := "hello\n"
   261  	if res := out.String(); res != wanted {
   262  		t.Fatalf("got %v, want %v", res, wanted)
   263  	}
   264  }
   265  
   266  func TestEvalNil(t *testing.T) {
   267  	i := interp.New(interp.Options{})
   268  	if err := i.Use(stdlib.Symbols); err != nil {
   269  		t.Fatal(err)
   270  	}
   271  	runTests(t, i, []testCase{
   272  		{desc: "assign nil", src: "a := nil", err: "1:33: use of untyped nil"},
   273  		{desc: "return nil", pre: func() { eval(t, i, "func getNil() error {return nil}") }, src: "getNil()", res: "<nil>"},
   274  		{
   275  			desc: "return func which return error",
   276  			pre: func() {
   277  				eval(t, i, `
   278  					package bar
   279  
   280  					func New() func(string) error {
   281  						return func(v string) error {
   282  							return nil
   283  						}
   284  					}
   285  				`)
   286  				v := eval(t, i, `bar.New()`)
   287  				fn, ok := v.Interface().(func(string) error)
   288  				if !ok {
   289  					t.Fatal("conversion failed")
   290  				}
   291  				if res := fn("hello"); res != nil {
   292  					t.Fatalf("got %v, want nil", res)
   293  				}
   294  			},
   295  		},
   296  		{
   297  			desc: "return nil pointer",
   298  			pre: func() {
   299  				eval(t, i, `
   300  					import "fmt"
   301  
   302  					type Foo struct{}
   303  
   304  					func Hello() *Foo {
   305  						fmt.Println("Hello")
   306  						return nil
   307  					}
   308  				`)
   309  			},
   310  			src: "Hello()",
   311  			res: "<nil>",
   312  		},
   313  		{
   314  			desc: "return nil func",
   315  			pre: func() {
   316  				eval(t, i, `func Bar() func() { return nil }`)
   317  			},
   318  			src: "Bar()",
   319  			res: "<nil>",
   320  		},
   321  	})
   322  }
   323  
   324  func TestEvalStruct0(t *testing.T) {
   325  	i := interp.New(interp.Options{})
   326  	runTests(t, i, []testCase{
   327  		{
   328  			desc: "func field in struct",
   329  			pre: func() {
   330  				eval(t, i, `
   331  					type Fromage struct {
   332  						Name string
   333  						Call func(string) string
   334  					}
   335  
   336  					func f() string {
   337  						a := Fromage{}
   338  						a.Name = "test"
   339  						a.Call = func(s string) string { return s }
   340  
   341  						return a.Call(a.Name)
   342  					}
   343  				`)
   344  			},
   345  			src: "f()",
   346  			res: "test",
   347  		},
   348  		{
   349  			desc: "literal func field in struct",
   350  			pre: func() {
   351  				eval(t, i, `
   352  					type Fromage2 struct {
   353  						Name string
   354  						Call func(string) string
   355  					}
   356  
   357  					func f2() string {
   358  						a := Fromage2{
   359  							"test",
   360  							func(s string) string { return s },
   361  						}
   362  						return a.Call(a.Name)
   363  					}
   364  				`)
   365  			},
   366  			src: "f2()",
   367  			res: "test",
   368  		},
   369  	})
   370  }
   371  
   372  func TestEvalStruct1(t *testing.T) {
   373  	i := interp.New(interp.Options{})
   374  	eval(t, i, `
   375  type Fromage struct {
   376  	Name string
   377  	Call func(string) string
   378  }
   379  
   380  func f() string {
   381  	a := Fromage{
   382  		"test",
   383  		func(s string) string { return s },
   384  	}
   385  
   386  	return a.Call(a.Name)
   387  }
   388  `)
   389  
   390  	v := eval(t, i, `f()`)
   391  	if v.Interface().(string) != "test" {
   392  		t.Fatalf("got %v, want test", v)
   393  	}
   394  }
   395  
   396  func TestEvalComposite0(t *testing.T) {
   397  	i := interp.New(interp.Options{})
   398  	eval(t, i, `
   399  type T struct {
   400  	a, b, c, d, e, f, g, h, i, j, k, l, m, n string
   401  	o map[string]int
   402  	p []string
   403  }
   404  
   405  var a = T{
   406  	o: map[string]int{"truc": 1, "machin": 2},
   407  	p: []string{"hello", "world"},
   408  }
   409  `)
   410  	v := eval(t, i, `a.p[1]`)
   411  	if v.Interface().(string) != "world" {
   412  		t.Fatalf("got %v, want word", v)
   413  	}
   414  }
   415  
   416  func TestEvalCompositeBin0(t *testing.T) {
   417  	i := interp.New(interp.Options{})
   418  	if err := i.Use(stdlib.Symbols); err != nil {
   419  		t.Fatal(err)
   420  	}
   421  	eval(t, i, `
   422  import (
   423  	"fmt"
   424  	"net/http"
   425  	"time"
   426  )
   427  
   428  func Foo() {
   429  	http.DefaultClient = &http.Client{Timeout: 2 * time.Second}
   430  }
   431  `)
   432  	http.DefaultClient = &http.Client{}
   433  	eval(t, i, `Foo()`)
   434  	if http.DefaultClient.Timeout != 2*time.Second {
   435  		t.Fatalf("got %v, want 2s", http.DefaultClient.Timeout)
   436  	}
   437  }
   438  
   439  func TestEvalComparison(t *testing.T) {
   440  	i := interp.New(interp.Options{})
   441  	runTests(t, i, []testCase{
   442  		{src: `2 > 1`, res: "true"},
   443  		{src: `1.2 > 1.1`, res: "true"},
   444  		{src: `"hhh" > "ggg"`, res: "true"},
   445  		{src: `a, b, c := 1, 1, false; if a == b { c = true }; c`, res: "true"},
   446  		{src: `a, b, c := 1, 2, false; if a != b { c = true }; c`, res: "true"},
   447  		{
   448  			desc: "mismatched types equality",
   449  			src: `
   450  				type Foo string
   451  				type Bar string
   452  
   453  				var a = Foo("test")
   454  				var b = Bar("test")
   455  				var c = a == b
   456  			`,
   457  			err: "7:13: invalid operation: mismatched types main.Foo and main.Bar",
   458  		},
   459  		{
   460  			desc: "mismatched types less than",
   461  			src: `
   462  				type Foo string
   463  				type Bar string
   464  
   465  				var a = Foo("test")
   466  				var b = Bar("test")
   467  				var c = a < b
   468  			`,
   469  			err: "7:13: invalid operation: mismatched types main.Foo and main.Bar",
   470  		},
   471  		{src: `1 > _`, err: "1:28: cannot use _ as value"},
   472  		{src: `(_) > 1`, err: "1:28: cannot use _ as value"},
   473  		{src: `v := interface{}(2); v == 2`, res: "true"},
   474  		{src: `v := interface{}(2); v > 1`, err: "1:49: invalid operation: operator > not defined on interface{}"},
   475  		{src: `v := interface{}(int64(2)); v == 2`, res: "false"},
   476  		{src: `v := interface{}(int64(2)); v != 2`, res: "true"},
   477  		{src: `v := interface{}(2.3); v == 2.3`, res: "true"},
   478  		{src: `v := interface{}(float32(2.3)); v != 2.3`, res: "true"},
   479  		{src: `v := interface{}("hello"); v == "hello"`, res: "true"},
   480  		{src: `v := interface{}("hello"); v < "hellp"`, err: "1:55: invalid operation: operator < not defined on interface{}"},
   481  	})
   482  }
   483  
   484  func TestEvalCompositeArray(t *testing.T) {
   485  	i := interp.New(interp.Options{})
   486  	eval(t, i, `const l = 10`)
   487  	runTests(t, i, []testCase{
   488  		{src: "a := []int{1, 2, 7: 20, 30}", res: "[1 2 0 0 0 0 0 20 30]"},
   489  		{src: `a := []int{1, 1.2}`, err: "1:42: 6/5 truncated to int"},
   490  		{src: `a := []int{0:1, 0:1}`, err: "1:46: duplicate index 0 in array or slice literal"},
   491  		{src: `a := []int{1.1:1, 1.2:"test"}`, err: "1:39: index untyped float must be integer constant"},
   492  		{src: `a := [2]int{1, 1.2}`, err: "1:43: 6/5 truncated to int"},
   493  		{src: `a := [1]int{1, 2}`, err: "1:43: index 1 is out of bounds (>= 1)"},
   494  		{src: `b := [l]int{1, 2}`, res: "[1 2 0 0 0 0 0 0 0 0]"},
   495  		{src: `i := 10; a := [i]int{1, 2}`, err: "1:43: non-constant array bound \"i\""},
   496  		{src: `c := [...]float64{1, 3: 3.4, 5}`, res: "[1 0 0 3.4 5]"},
   497  	})
   498  }
   499  
   500  func TestEvalCompositeMap(t *testing.T) {
   501  	i := interp.New(interp.Options{})
   502  	runTests(t, i, []testCase{
   503  		{src: `a := map[string]int{"one":1, "two":2}`, res: "map[one:1 two:2]"},
   504  		{src: `a := map[string]int{1:1, 2:2}`, err: "1:48: cannot convert 1 to string"},
   505  		{src: `a := map[string]int{"one":1, "two":2.2}`, err: "1:63: 11/5 truncated to int"},
   506  		{src: `a := map[string]int{1, "two":2}`, err: "1:48: missing key in map literal"},
   507  		{src: `a := map[string]int{"one":1, "one":2}`, err: "1:57: duplicate key one in map literal"},
   508  	})
   509  }
   510  
   511  func TestEvalCompositeStruct(t *testing.T) {
   512  	i := interp.New(interp.Options{})
   513  	runTests(t, i, []testCase{
   514  		{src: `a := struct{A,B,C int}{}`, res: "{0 0 0}"},
   515  		{src: `a := struct{A,B,C int}{1,2,3}`, res: "{1 2 3}"},
   516  		{src: `a := struct{A,B,C int}{1,2.2,3}`, err: "1:53: 11/5 truncated to int"},
   517  		{src: `a := struct{A,B,C int}{1,2}`, err: "1:53: too few values in struct literal"},
   518  		{src: `a := struct{A,B,C int}{1,2,3,4}`, err: "1:57: too many values in struct literal"},
   519  		{src: `a := struct{A,B,C int}{1,B:2,3}`, err: "1:53: mixture of field:value and value elements in struct literal"},
   520  		{src: `a := struct{A,B,C int}{A:1,B:2,C:3}`, res: "{1 2 3}"},
   521  		{src: `a := struct{A,B,C int}{B:2}`, res: "{0 2 0}"},
   522  		{src: `a := struct{A,B,C int}{A:1,D:2,C:3}`, err: "1:55: unknown field D in struct literal"},
   523  		{src: `a := struct{A,B,C int}{A:1,A:2,C:3}`, err: "1:55: duplicate field name A in struct literal"},
   524  		{src: `a := struct{A,B,C int}{A:1,B:2.2,C:3}`, err: "1:57: 11/5 truncated to int"},
   525  		{src: `a := struct{A,B,C int}{A:1,2,C:3}`, err: "1:55: mixture of field:value and value elements in struct literal"},
   526  		{src: `a := struct{A,B,C int}{1,2,_}`, err: "1:33: cannot use _ as value"},
   527  		{src: `a := struct{A,B,C int}{B: _}`, err: "1:51: cannot use _ as value"},
   528  	})
   529  }
   530  
   531  func TestEvalSliceExpression(t *testing.T) {
   532  	i := interp.New(interp.Options{})
   533  	runTests(t, i, []testCase{
   534  		{src: `a := []int{0,1,2}[1:3]`, res: "[1 2]"},
   535  		{src: `a := []int{0,1,2}[:3]`, res: "[0 1 2]"},
   536  		{src: `a := []int{0,1,2}[:]`, res: "[0 1 2]"},
   537  		{src: `a := []int{0,1,2,3}[1:3:4]`, res: "[1 2]"},
   538  		{src: `a := []int{0,1,2,3}[:3:4]`, res: "[0 1 2]"},
   539  		{src: `ar := [3]int{0,1,2}; a := ar[1:3]`, res: "[1 2]"},
   540  		{src: `a := (&[3]int{0,1,2})[1:3]`, res: "[1 2]"},
   541  		{src: `a := (&[3]int{0,1,2})[1:3]`, res: "[1 2]"},
   542  		{src: `s := "hello"[1:3]`, res: "el"},
   543  		{src: `str := "hello"; s := str[1:3]`, res: "el"},
   544  		{src: `a := int(1)[0:1]`, err: "1:33: cannot slice type int"},
   545  		{src: `a := (&[]int{0,1,2,3})[1:3]`, err: "1:33: cannot slice type *[]int"},
   546  		{src: `a := "hello"[1:3:4]`, err: "1:45: invalid operation: 3-index slice of string"},
   547  		{src: `ar := [3]int{0,1,2}; a := ar[:4]`, err: "1:58: index int is out of bounds"},
   548  		{src: `a := []int{0,1,2,3}[1::4]`, err: "index required in 3-index slice"},
   549  		{src: `a := []int{0,1,2,3}[1:3:]`, err: "index required in 3-index slice"},
   550  		{src: `a := []int{0,1,2}[3:1]`, err: "invalid index values, must be low <= high <= max"},
   551  		{pre: func() { eval(t, i, `type Str = string; var r Str = "truc"`) }, src: `r[1]`, res: "114"},
   552  		{src: `_[12]`, err: "1:28: cannot use _ as value"},
   553  		{src: `b := []int{0,1,2}[_:4]`, err: "1:33: cannot use _ as value"},
   554  	})
   555  }
   556  
   557  func TestEvalConversion(t *testing.T) {
   558  	i := interp.New(interp.Options{})
   559  	runTests(t, i, []testCase{
   560  		{src: `a := uint64(1)`, res: "1"},
   561  		{src: `i := 1.1; a := uint64(i)`, res: "1"},
   562  		{src: `b := string(49)`, res: "1"},
   563  		{src: `c := uint64(1.1)`, err: "1:40: cannot convert expression of type untyped float to type uint64"},
   564  		{src: `int(_)`, err: "1:28: cannot use _ as value"},
   565  	})
   566  }
   567  
   568  func TestEvalUnary(t *testing.T) {
   569  	i := interp.New(interp.Options{})
   570  	runTests(t, i, []testCase{
   571  		{src: "a := -1", res: "-1"},
   572  		{src: "b := +1", res: "1", skip: "BUG"},
   573  		{src: "c := !false", res: "true"},
   574  		{src: "_ = 2; _++", err: "1:35: cannot use _ as value"},
   575  		{src: "_ = false; !_ == true", err: "1:39: cannot use _ as value"},
   576  		{src: "!((((_))))", err: "1:28: cannot use _ as value"},
   577  	})
   578  }
   579  
   580  func TestEvalMethod(t *testing.T) {
   581  	i := interp.New(interp.Options{})
   582  	eval(t, i, `
   583  		type Root struct {
   584  			Name string
   585  		}
   586  
   587  		type One struct {
   588  			Root
   589  		}
   590  
   591  		type Hi interface {
   592  			Hello() string
   593  		}
   594  
   595  		type Hey interface {
   596  			Hello() string
   597  		}
   598  
   599  		func (r *Root) Hello() string { return "Hello " + r.Name }
   600  
   601  		var r = Root{"R"}
   602  		var o = One{r}
   603  		// TODO(mpl): restore empty interfaces when type assertions work (again) on them.
   604  		// var root interface{} = &Root{Name: "test1"}
   605  		// var one interface{} = &One{Root{Name: "test2"}}
   606  		var root Hey = &Root{Name: "test1"}
   607  		var one Hey = &One{Root{Name: "test2"}}
   608  	`)
   609  	runTests(t, i, []testCase{
   610  		{src: "r.Hello()", res: "Hello R"},
   611  		{src: "(&r).Hello()", res: "Hello R"},
   612  		{src: "o.Hello()", res: "Hello R"},
   613  		{src: "(&o).Hello()", res: "Hello R"},
   614  		{src: "root.(Hi).Hello()", res: "Hello test1"},
   615  		{src: "one.(Hi).Hello()", res: "Hello test2"},
   616  	})
   617  }
   618  
   619  func TestEvalChan(t *testing.T) {
   620  	i := interp.New(interp.Options{})
   621  	runTests(t, i, []testCase{
   622  		{
   623  			src: `(func () string {
   624  				messages := make(chan string)
   625  				go func() { messages <- "ping" }()
   626  				msg := <-messages
   627  				return msg
   628  			})()`, res: "ping",
   629  		},
   630  		{
   631  			src: `(func () bool {
   632  				messages := make(chan string)
   633  				go func() { messages <- "ping" }()
   634  				msg, ok := <-messages
   635  				return ok && msg == "ping"
   636  			})()`, res: "true",
   637  		},
   638  		{
   639  			src: `(func () bool {
   640  				messages := make(chan string)
   641  				go func() { messages <- "ping" }()
   642  				var msg string
   643  				var ok bool
   644  				msg, ok = <-messages
   645  				return ok && msg == "ping"
   646  			})()`, res: "true",
   647  		},
   648  		{src: `a :=5; a <- 4`, err: "cannot send to non-channel int"},
   649  		{src: `a :=5; b := <-a`, err: "cannot receive from non-channel int"},
   650  	})
   651  }
   652  
   653  func TestEvalFunctionCallWithFunctionParam(t *testing.T) {
   654  	i := interp.New(interp.Options{})
   655  	eval(t, i, `
   656  		func Bar(s string, fn func(string)string) string { return fn(s) }
   657  	`)
   658  
   659  	v := eval(t, i, "Bar")
   660  	bar := v.Interface().(func(string, func(string) string) string)
   661  
   662  	got := bar("hello ", func(s string) string {
   663  		return s + "world!"
   664  	})
   665  
   666  	want := "hello world!"
   667  	if got != want {
   668  		t.Errorf("unexpected result of function eval: got %q, want %q", got, want)
   669  	}
   670  }
   671  
   672  func TestEvalCall(t *testing.T) {
   673  	i := interp.New(interp.Options{})
   674  	runTests(t, i, []testCase{
   675  		{src: ` test := func(a int, b float64) int { return a }
   676  				a := test(1, 2.3)`, res: "1"},
   677  		{src: ` test := func(a int, b float64) int { return a }
   678  				a := test(1)`, err: "2:10: not enough arguments in call to test"},
   679  		{src: ` test := func(a int, b float64) int { return a }
   680  				s := "test"
   681  				a := test(1, s)`, err: "3:18: cannot use type string as type float64"},
   682  		{src: ` test := func(a ...int) int { return 1 }
   683  				a := test([]int{1}...)`, res: "1"},
   684  		{src: ` test := func(a ...int) int { return 1 }
   685  				a := test()`, res: "1"},
   686  		{src: ` test := func(a ...int) int { return 1 }
   687  				blah := func() []int { return []int{1,1} }
   688  				a := test(blah()...)`, res: "1"},
   689  		{src: ` test := func(a ...int) int { return 1 }
   690  				a := test([]string{"1"}...)`, err: "2:15: cannot use []string as type []int"},
   691  		{src: ` test := func(a ...int) int { return 1 }
   692  				i := 1
   693  				a := test(i...)`, err: "3:15: cannot use int as type []int"},
   694  		{src: ` test := func(a int) int { return a }
   695  				a := test([]int{1}...)`, err: "2:10: invalid use of ..., corresponding parameter is non-variadic"},
   696  		{src: ` test := func(a ...int) int { return 1 }
   697  				blah := func() (int, int) { return 1, 1 }
   698  				a := test(blah()...)`, err: "3:15: cannot use ... with 2-valued func() (int,int)"},
   699  		{src: ` test := func(a, b int) int { return a }
   700  				blah := func() (int, int) { return 1, 1 }
   701  				a := test(blah())`, res: "1"},
   702  		{src: ` test := func(a, b int) int { return a }
   703  				blah := func() int { return 1 }
   704  				a := test(blah(), blah())`, res: "1"},
   705  		{src: ` test := func(a, b, c, d int) int { return a }
   706  				blah := func() (int, int) { return 1, 1 }
   707  				a := test(blah(), blah())`, err: "3:15: cannot use func() (int,int) as type int"},
   708  		{src: ` test := func(a, b int) int { return a }
   709  				blah := func() (int, float64) { return 1, 1.1 }
   710  				a := test(blah())`, err: "3:15: cannot use func() (int,float64) as type (int,int)"},
   711  		{src: "func f()", err: "function declaration without body is unsupported"},
   712  	})
   713  }
   714  
   715  func TestEvalBinCall(t *testing.T) {
   716  	i := interp.New(interp.Options{})
   717  	if err := i.Use(stdlib.Symbols); err != nil {
   718  		t.Fatal(err)
   719  	}
   720  	if _, err := i.Eval(`import "fmt"`); err != nil {
   721  		t.Fatal(err)
   722  	}
   723  	runTests(t, i, []testCase{
   724  		{src: `a := fmt.Sprint(1, 2.3)`, res: "1 2.3"},
   725  		{src: `a := fmt.Sprintf()`, err: "1:33: not enough arguments in call to fmt.Sprintf"},
   726  		{src: `i := 1
   727  			   a := fmt.Sprintf(i)`, err: "2:24: cannot use type int as type string"},
   728  		{src: `a := fmt.Sprint()`, res: ""},
   729  	})
   730  }
   731  
   732  func TestEvalReflect(t *testing.T) {
   733  	i := interp.New(interp.Options{})
   734  	if err := i.Use(stdlib.Symbols); err != nil {
   735  		t.Fatal(err)
   736  	}
   737  	if _, err := i.Eval(`
   738  		import (
   739  			"net/url"
   740  			"reflect"
   741  		)
   742  
   743  		type Encoder interface {
   744  			EncodeValues(key string, v *url.Values) error
   745  		}
   746  	`); err != nil {
   747  		t.Fatal(err)
   748  	}
   749  
   750  	runTests(t, i, []testCase{
   751  		{src: "reflect.TypeOf(new(Encoder)).Elem()", res: "interp.valueInterface"},
   752  	})
   753  }
   754  
   755  func TestEvalMissingSymbol(t *testing.T) {
   756  	defer func() {
   757  		r := recover()
   758  		if r != nil {
   759  			t.Errorf("unexpected panic: %v", r)
   760  		}
   761  	}()
   762  
   763  	type S2 struct{}
   764  	type S1 struct {
   765  		F S2
   766  	}
   767  	i := interp.New(interp.Options{})
   768  	if err := i.Use(interp.Exports{"p/p": map[string]reflect.Value{
   769  		"S1": reflect.Zero(reflect.TypeOf(&S1{})),
   770  	}}); err != nil {
   771  		t.Fatal(err)
   772  	}
   773  	_, err := i.Eval(`import "p"`)
   774  	if err != nil {
   775  		t.Fatalf("failed to import package: %v", err)
   776  	}
   777  	_, err = i.Eval(`p.S1{F: p.S2{}}`)
   778  	if err == nil {
   779  		t.Error("unexpected nil error for expression with undefined type")
   780  	}
   781  }
   782  
   783  func TestEvalWithContext(t *testing.T) {
   784  	tests := []testCase{
   785  		{
   786  			desc: "for {}",
   787  			src: `(func() {
   788  				      for {}
   789  			      })()`,
   790  		},
   791  		{
   792  			desc: "select {}",
   793  			src: `(func() {
   794  				     select {}
   795  			     })()`,
   796  		},
   797  		{
   798  			desc: "blocked chan send",
   799  			src: `(func() {
   800  			         c := make(chan int)
   801  				     c <- 1
   802  				 })()`,
   803  		},
   804  		{
   805  			desc: "blocked chan recv",
   806  			src: `(func() {
   807  			         c := make(chan int)
   808  				     <-c
   809  			     })()`,
   810  		},
   811  		{
   812  			desc: "blocked chan recv2",
   813  			src: `(func() {
   814  			         c := make(chan int)
   815  				     _, _ = <-c
   816  			     })()`,
   817  		},
   818  		{
   819  			desc: "blocked range chan",
   820  			src: `(func() {
   821  			         c := make(chan int)
   822  				     for range c {}
   823  			     })()`,
   824  		},
   825  		{
   826  			desc: "double lock",
   827  			src: `(func() {
   828  			         var mu sync.Mutex
   829  				     mu.Lock()
   830  				     mu.Lock()
   831  			      })()`,
   832  		},
   833  	}
   834  
   835  	for _, test := range tests {
   836  		done := make(chan struct{})
   837  		src := test.src
   838  		go func() {
   839  			defer close(done)
   840  			i := interp.New(interp.Options{})
   841  			if err := i.Use(stdlib.Symbols); err != nil {
   842  				t.Error(err)
   843  			}
   844  			_, err := i.Eval(`import "sync"`)
   845  			if err != nil {
   846  				t.Errorf(`failed to import "sync": %v`, err)
   847  				return
   848  			}
   849  			ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
   850  			defer cancel()
   851  			_, err = i.EvalWithContext(ctx, src)
   852  			switch err {
   853  			case context.DeadlineExceeded:
   854  				// Successful cancellation.
   855  
   856  				// Check we can still execute an expression.
   857  				v, err := i.EvalWithContext(context.Background(), "1+1\n")
   858  				if err != nil {
   859  					t.Errorf("failed to evaluate expression after cancellation: %v", err)
   860  				}
   861  				got := v.Interface()
   862  				if got != 2 {
   863  					t.Errorf("unexpected result of eval(1+1): got %v, want 2", got)
   864  				}
   865  			case nil:
   866  				t.Errorf("unexpected success evaluating expression %q", test.desc)
   867  			default:
   868  				t.Errorf("failed to evaluate expression %q: %v", test.desc, err)
   869  			}
   870  		}()
   871  		select {
   872  		case <-time.After(time.Second):
   873  			t.Errorf("timeout failed to terminate execution of %q", test.desc)
   874  		case <-done:
   875  		}
   876  	}
   877  }
   878  
   879  func runTests(t *testing.T, i *interp.Interpreter, tests []testCase) {
   880  	t.Helper()
   881  
   882  	for _, test := range tests {
   883  		t.Run(test.desc, func(t *testing.T) {
   884  			if test.skip != "" {
   885  				t.Skip(test.skip)
   886  			}
   887  			if test.pre != nil {
   888  				test.pre()
   889  			}
   890  			if test.src != "" {
   891  				assertEval(t, i, test.src, test.err, test.res)
   892  			}
   893  		})
   894  	}
   895  }
   896  
   897  func eval(t *testing.T, i *interp.Interpreter, src string) reflect.Value {
   898  	t.Helper()
   899  	res, err := i.Eval(src)
   900  	if err != nil {
   901  		t.Logf("Error: %v", err)
   902  		if e, ok := err.(interp.Panic); ok {
   903  			t.Logf(string(e.Stack))
   904  		}
   905  		t.FailNow()
   906  	}
   907  	return res
   908  }
   909  
   910  func assertEval(t *testing.T, i *interp.Interpreter, src, expectedError, expectedRes string) {
   911  	t.Helper()
   912  
   913  	res, err := i.Eval(src)
   914  
   915  	if expectedError != "" {
   916  		if err == nil || !strings.Contains(err.Error(), expectedError) {
   917  			t.Fatalf("got %v, want %s", err, expectedError)
   918  		}
   919  		return
   920  	}
   921  
   922  	if err != nil {
   923  		t.Logf("got an error: %v", err)
   924  		if e, ok := err.(interp.Panic); ok {
   925  			t.Logf(string(e.Stack))
   926  		}
   927  		t.FailNow()
   928  	}
   929  
   930  	if fmt.Sprintf("%v", res) != expectedRes {
   931  		t.Fatalf("got %v, want %s", res, expectedRes)
   932  	}
   933  }
   934  
   935  func TestMultiEval(t *testing.T) {
   936  	t.Skip("fail in CI only ?")
   937  	// catch stdout
   938  	backupStdout := os.Stdout
   939  	defer func() {
   940  		os.Stdout = backupStdout
   941  	}()
   942  	r, w, _ := os.Pipe()
   943  	os.Stdout = w
   944  
   945  	i := interp.New(interp.Options{})
   946  	if err := i.Use(stdlib.Symbols); err != nil {
   947  		t.Fatal(err)
   948  	}
   949  
   950  	f, err := os.Open(filepath.Join("testdata", "multi", "731"))
   951  	if err != nil {
   952  		t.Fatal(err)
   953  	}
   954  	names, err := f.Readdirnames(-1)
   955  	if err != nil {
   956  		t.Fatal(err)
   957  	}
   958  	for _, v := range names {
   959  		if _, err := i.EvalPath(filepath.Join(f.Name(), v)); err != nil {
   960  			t.Fatal(err)
   961  		}
   962  	}
   963  
   964  	// read stdout
   965  	if err = w.Close(); err != nil {
   966  		t.Fatal(err)
   967  	}
   968  	outInterp, err := io.ReadAll(r)
   969  	if err != nil {
   970  		t.Fatal(err)
   971  	}
   972  
   973  	// restore Stdout
   974  	os.Stdout = backupStdout
   975  
   976  	want := "A\nB\n"
   977  	got := string(outInterp)
   978  	if got != want {
   979  		t.Fatalf("unexpected output: got %v, wanted %v", got, want)
   980  	}
   981  }
   982  
   983  func TestMultiEvalNoName(t *testing.T) {
   984  	t.Skip("fail in CI only ?")
   985  	i := interp.New(interp.Options{})
   986  	if err := i.Use(stdlib.Symbols); err != nil {
   987  		t.Fatal(err)
   988  	}
   989  
   990  	f, err := os.Open(filepath.Join("testdata", "multi", "731"))
   991  	if err != nil {
   992  		t.Fatal(err)
   993  	}
   994  	names, err := f.Readdirnames(-1)
   995  	if err != nil {
   996  		t.Fatal(err)
   997  	}
   998  	for k, v := range names {
   999  		data, err := os.ReadFile(filepath.Join(f.Name(), v))
  1000  		if err != nil {
  1001  			t.Fatal(err)
  1002  		}
  1003  		_, err = i.Eval(string(data))
  1004  		if k == 1 {
  1005  			expectedErr := fmt.Errorf("3:8: fmt/%s redeclared in this block", interp.DefaultSourceName)
  1006  			if err == nil || err.Error() != expectedErr.Error() {
  1007  				t.Fatalf("unexpected result; wanted error %v, got %v", expectedErr, err)
  1008  			}
  1009  			return
  1010  		}
  1011  		if err != nil {
  1012  			t.Fatal(err)
  1013  		}
  1014  	}
  1015  }
  1016  
  1017  const goMinorVersionTest = 16
  1018  
  1019  func TestHasIOFS(t *testing.T) {
  1020  	code := `
  1021  // +build go1.18
  1022  
  1023  package main
  1024  
  1025  import (
  1026  	"errors"
  1027  	"io/fs"
  1028  )
  1029  
  1030  func main() {
  1031  	pe := fs.PathError{}
  1032  	pe.Op = "nothing"
  1033  	pe.Path = "/nowhere"
  1034  	pe.Err = errors.New("an error")
  1035  	println(pe.Error())
  1036  }
  1037  
  1038  // Output:
  1039  // nothing /nowhere: an error
  1040  `
  1041  
  1042  	var buf bytes.Buffer
  1043  	i := interp.New(interp.Options{Stdout: &buf})
  1044  	if err := i.Use(interp.Symbols); err != nil {
  1045  		t.Fatal(err)
  1046  	}
  1047  	if err := i.Use(stdlib.Symbols); err != nil {
  1048  		t.Fatal(err)
  1049  	}
  1050  
  1051  	if _, err := i.Eval(code); err != nil {
  1052  		t.Fatal(err)
  1053  	}
  1054  
  1055  	var expectedOutput string
  1056  	var minor int
  1057  	var err error
  1058  	version := runtime.Version()
  1059  	version = strings.Replace(version, "beta", ".", 1)
  1060  	version = strings.Replace(version, "rc", ".", 1)
  1061  	fields := strings.Fields(version)
  1062  	// Go stable
  1063  	if len(fields) == 1 {
  1064  		v := strings.Split(version, ".")
  1065  		if len(v) < 2 {
  1066  			t.Fatalf("unexpected: %v", version)
  1067  		}
  1068  		minor, err = strconv.Atoi(v[1])
  1069  		if err != nil {
  1070  			t.Fatal(err)
  1071  		}
  1072  	} else {
  1073  		// Go devel
  1074  		if fields[0] != "devel" {
  1075  			t.Fatalf("unexpected: %v", fields[0])
  1076  		}
  1077  		parts := strings.Split(fields[1], "-")
  1078  		if len(parts) != 2 {
  1079  			t.Fatalf("unexpected: %v", fields[1])
  1080  		}
  1081  		minor, err = strconv.Atoi(strings.TrimPrefix(parts[0], "go1."))
  1082  		if err != nil {
  1083  			t.Fatal(err)
  1084  		}
  1085  	}
  1086  
  1087  	if minor >= goMinorVersionTest {
  1088  		expectedOutput = "nothing /nowhere: an error\n"
  1089  	}
  1090  
  1091  	output := buf.String()
  1092  	if buf.String() != expectedOutput {
  1093  		t.Fatalf("got: %v, wanted: %v", output, expectedOutput)
  1094  	}
  1095  }
  1096  
  1097  func TestImportPathIsKey(t *testing.T) {
  1098  	// No need to check the results of Eval, as TestFile already does it.
  1099  	i := interp.New(interp.Options{GoPath: filepath.FromSlash("../_test/testdata/redeclaration-global7")})
  1100  	if err := i.Use(stdlib.Symbols); err != nil {
  1101  		t.Fatal(err)
  1102  	}
  1103  
  1104  	filePath := filepath.Join("..", "_test", "ipp_as_key.go")
  1105  	if _, err := i.EvalPath(filePath); err != nil {
  1106  		t.Fatal(err)
  1107  	}
  1108  
  1109  	wantScopes := map[string][]string{
  1110  		"main": {
  1111  			"titi/ipp_as_key.go",
  1112  			"tutu/ipp_as_key.go",
  1113  			"main",
  1114  		},
  1115  		"guthib.com/toto": {
  1116  			"quux/titi.go",
  1117  			"Quux",
  1118  		},
  1119  		"guthib.com/bar": {
  1120  			"Quux",
  1121  		},
  1122  		"guthib.com/tata": {
  1123  			"quux/tutu.go",
  1124  			"Quux",
  1125  		},
  1126  		"guthib.com/baz": {
  1127  			"Quux",
  1128  		},
  1129  	}
  1130  	wantPackages := map[string]string{
  1131  		"guthib.com/baz":  "quux",
  1132  		"guthib.com/tata": "tutu",
  1133  		"main":            "main",
  1134  		"guthib.com/bar":  "quux",
  1135  		"guthib.com/toto": "titi",
  1136  	}
  1137  
  1138  	scopes := i.Scopes()
  1139  	if len(scopes) != len(wantScopes) {
  1140  		t.Fatalf("want %d, got %d", len(wantScopes), len(scopes))
  1141  	}
  1142  	for k, v := range scopes {
  1143  		wantSym := wantScopes[k]
  1144  		if len(v) != len(wantSym) {
  1145  			t.Fatalf("want %d, got %d", len(wantSym), len(v))
  1146  		}
  1147  		for _, sym := range wantSym {
  1148  			if _, ok := v[sym]; !ok {
  1149  				t.Fatalf("symbol %s not found in scope %s", sym, k)
  1150  			}
  1151  		}
  1152  	}
  1153  
  1154  	packages := i.Packages()
  1155  	for k, v := range wantPackages {
  1156  		pkg := packages[k]
  1157  		if pkg != v {
  1158  			t.Fatalf("for import path %s, want %s, got %s", k, v, pkg)
  1159  		}
  1160  	}
  1161  }
  1162  
  1163  // The code in hello1.go and hello2.go spawns a "long-running" goroutine, which
  1164  // means each call to EvalPath actually terminates before the evaled code is done
  1165  // running. So this test demonstrates:
  1166  // 1) That two sequential calls to EvalPath don't see their "compilation phases"
  1167  // collide (no data race on the fields of the interpreter), which is somewhat
  1168  // obvious since the calls (and hence the "compilation phases") are sequential too.
  1169  // 2) That two concurrent goroutine runs spawned by the same interpreter do not
  1170  // collide either.
  1171  func TestConcurrentEvals(t *testing.T) {
  1172  	if testing.Short() {
  1173  		return
  1174  	}
  1175  	pin, pout := io.Pipe()
  1176  	defer func() {
  1177  		_ = pin.Close()
  1178  		_ = pout.Close()
  1179  	}()
  1180  	interpr := interp.New(interp.Options{Stdout: pout})
  1181  	if err := interpr.Use(stdlib.Symbols); err != nil {
  1182  		t.Fatal(err)
  1183  	}
  1184  
  1185  	if _, err := interpr.EvalPath("testdata/concurrent/hello1.go"); err != nil {
  1186  		t.Fatal(err)
  1187  	}
  1188  	if _, err := interpr.EvalPath("testdata/concurrent/hello2.go"); err != nil {
  1189  		t.Fatal(err)
  1190  	}
  1191  
  1192  	c := make(chan error)
  1193  	go func() {
  1194  		hello1, hello2 := false, false
  1195  		sc := bufio.NewScanner(pin)
  1196  		for sc.Scan() {
  1197  			l := sc.Text()
  1198  			switch l {
  1199  			case "hello world1":
  1200  				hello1 = true
  1201  			case "hello world2":
  1202  				hello2 = true
  1203  			case "hello world1hello world2", "hello world2hello world1":
  1204  				hello1 = true
  1205  				hello2 = true
  1206  			default:
  1207  				c <- fmt.Errorf("unexpected output: %v", l)
  1208  				return
  1209  			}
  1210  			if hello1 && hello2 {
  1211  				break
  1212  			}
  1213  		}
  1214  		c <- nil
  1215  	}()
  1216  
  1217  	timeout := time.NewTimer(5 * time.Second)
  1218  	select {
  1219  	case <-timeout.C:
  1220  		t.Fatal("timeout")
  1221  	case err := <-c:
  1222  		if err != nil {
  1223  			t.Fatal(err)
  1224  		}
  1225  	}
  1226  }
  1227  
  1228  // TestConcurrentEvals2 shows that even though EvalWithContext calls Eval in a
  1229  // goroutine, it indeed waits for Eval to terminate, and that therefore the code
  1230  // called by EvalWithContext is sequential. And that there is no data race for the
  1231  // interp package global vars or the interpreter fields in this case.
  1232  func TestConcurrentEvals2(t *testing.T) {
  1233  	if testing.Short() {
  1234  		return
  1235  	}
  1236  	pin, pout := io.Pipe()
  1237  	defer func() {
  1238  		_ = pin.Close()
  1239  		_ = pout.Close()
  1240  	}()
  1241  	interpr := interp.New(interp.Options{Stdout: pout})
  1242  	if err := interpr.Use(stdlib.Symbols); err != nil {
  1243  		t.Fatal(err)
  1244  	}
  1245  
  1246  	done := make(chan error)
  1247  	go func() {
  1248  		hello1 := false
  1249  		sc := bufio.NewScanner(pin)
  1250  		for sc.Scan() {
  1251  			l := sc.Text()
  1252  			if hello1 {
  1253  				if l == "hello world2" {
  1254  					break
  1255  				} else {
  1256  					done <- fmt.Errorf("unexpected output: %v", l)
  1257  					return
  1258  				}
  1259  			}
  1260  			if l == "hello world1" {
  1261  				hello1 = true
  1262  			} else {
  1263  				done <- fmt.Errorf("unexpected output: %v", l)
  1264  				return
  1265  			}
  1266  		}
  1267  		done <- nil
  1268  	}()
  1269  
  1270  	ctx := context.Background()
  1271  	if _, err := interpr.EvalWithContext(ctx, `import "time"`); err != nil {
  1272  		t.Fatal(err)
  1273  	}
  1274  	if _, err := interpr.EvalWithContext(ctx, `time.Sleep(time.Second); println("hello world1")`); err != nil {
  1275  		t.Fatal(err)
  1276  	}
  1277  	if _, err := interpr.EvalWithContext(ctx, `time.Sleep(time.Second); println("hello world2")`); err != nil {
  1278  		t.Fatal(err)
  1279  	}
  1280  
  1281  	timeout := time.NewTimer(5 * time.Second)
  1282  	select {
  1283  	case <-timeout.C:
  1284  		t.Fatal("timeout")
  1285  	case err := <-done:
  1286  		if err != nil {
  1287  			t.Fatal(err)
  1288  		}
  1289  	}
  1290  }
  1291  
  1292  // TestConcurrentEvals3 makes sure that we don't regress into data races at the package level, i.e from:
  1293  // - global vars, which should obviously not be mutated.
  1294  // - when calling Interpreter.Use, the symbols given as argument should be
  1295  // copied when being inserted into interp.binPkg, and not directly used as-is.
  1296  func TestConcurrentEvals3(t *testing.T) {
  1297  	if testing.Short() {
  1298  		return
  1299  	}
  1300  	allDone := make(chan bool)
  1301  	runREPL := func() {
  1302  		done := make(chan error)
  1303  		pinin, poutin := io.Pipe()
  1304  		pinout, poutout := io.Pipe()
  1305  		i := interp.New(interp.Options{Stdin: pinin, Stdout: poutout})
  1306  		if err := i.Use(stdlib.Symbols); err != nil {
  1307  			t.Fatal(err)
  1308  		}
  1309  
  1310  		go func() {
  1311  			_, _ = i.REPL()
  1312  		}()
  1313  
  1314  		input := []string{
  1315  			`hello one`,
  1316  			`hello two`,
  1317  			`hello three`,
  1318  		}
  1319  
  1320  		go func() {
  1321  			sc := bufio.NewScanner(pinout)
  1322  			k := 0
  1323  			for sc.Scan() {
  1324  				l := sc.Text()
  1325  				if l != input[k] {
  1326  					done <- fmt.Errorf("unexpected output, want %q, got %q", input[k], l)
  1327  					return
  1328  				}
  1329  				k++
  1330  				if k > 2 {
  1331  					break
  1332  				}
  1333  			}
  1334  			done <- nil
  1335  		}()
  1336  
  1337  		for _, v := range input {
  1338  			in := strings.NewReader(fmt.Sprintf("println(\"%s\")\n", v))
  1339  			if _, err := io.Copy(poutin, in); err != nil {
  1340  				t.Fatal(err)
  1341  			}
  1342  			time.Sleep(time.Second)
  1343  		}
  1344  
  1345  		if err := <-done; err != nil {
  1346  			t.Fatal(err)
  1347  		}
  1348  		_ = pinin.Close()
  1349  		_ = poutin.Close()
  1350  		_ = pinout.Close()
  1351  		_ = poutout.Close()
  1352  		allDone <- true
  1353  	}
  1354  
  1355  	for i := 0; i < 2; i++ {
  1356  		go func() {
  1357  			runREPL()
  1358  		}()
  1359  	}
  1360  
  1361  	timeout := time.NewTimer(10 * time.Second)
  1362  	for i := 0; i < 2; i++ {
  1363  		select {
  1364  		case <-allDone:
  1365  		case <-timeout.C:
  1366  			t.Fatal("timeout")
  1367  		}
  1368  	}
  1369  }
  1370  
  1371  func TestConcurrentComposite1(t *testing.T) {
  1372  	testConcurrentComposite(t, "./testdata/concurrent/composite/composite_lit.go")
  1373  }
  1374  
  1375  func TestConcurrentComposite2(t *testing.T) {
  1376  	testConcurrentComposite(t, "./testdata/concurrent/composite/composite_sparse.go")
  1377  }
  1378  
  1379  func testConcurrentComposite(t *testing.T, filePath string) {
  1380  	t.Helper()
  1381  
  1382  	if testing.Short() {
  1383  		return
  1384  	}
  1385  	pin, pout := io.Pipe()
  1386  	i := interp.New(interp.Options{Stdout: pout})
  1387  	if err := i.Use(stdlib.Symbols); err != nil {
  1388  		t.Fatal(err)
  1389  	}
  1390  
  1391  	errc := make(chan error)
  1392  	var output string
  1393  	go func() {
  1394  		sc := bufio.NewScanner(pin)
  1395  		k := 0
  1396  		for sc.Scan() {
  1397  			output += sc.Text()
  1398  			k++
  1399  			if k > 1 {
  1400  				break
  1401  			}
  1402  		}
  1403  		errc <- nil
  1404  	}()
  1405  
  1406  	if _, err := i.EvalPath(filePath); err != nil {
  1407  		t.Fatal(err)
  1408  	}
  1409  
  1410  	_ = pin.Close()
  1411  	_ = pout.Close()
  1412  
  1413  	if err := <-errc; err != nil {
  1414  		t.Fatal(err)
  1415  	}
  1416  
  1417  	expected := "{hello}{hello}"
  1418  	if output != expected {
  1419  		t.Fatalf("unexpected output, want %q, got %q", expected, output)
  1420  	}
  1421  }
  1422  
  1423  func TestEvalREPL(t *testing.T) {
  1424  	if testing.Short() {
  1425  		return
  1426  	}
  1427  	type testCase struct {
  1428  		desc      string
  1429  		src       []string
  1430  		errorLine int
  1431  	}
  1432  	tests := []testCase{
  1433  		{
  1434  			desc: "no error",
  1435  			src: []string{
  1436  				`func main() {`,
  1437  				`println("foo")`,
  1438  				`}`,
  1439  			},
  1440  			errorLine: -1,
  1441  		},
  1442  
  1443  		{
  1444  			desc: "no parsing error, but block error",
  1445  			src: []string{
  1446  				`func main() {`,
  1447  				`println(foo)`,
  1448  				`}`,
  1449  			},
  1450  			errorLine: 2,
  1451  		},
  1452  		{
  1453  			desc: "parsing error",
  1454  			src: []string{
  1455  				`func main() {`,
  1456  				`println(/foo)`,
  1457  				`}`,
  1458  			},
  1459  			errorLine: 1,
  1460  		},
  1461  		{
  1462  			desc: "multi-line string literal",
  1463  			src: []string{
  1464  				"var a = `hello",
  1465  				"there, how",
  1466  				"are you?`",
  1467  			},
  1468  			errorLine: -1,
  1469  		},
  1470  
  1471  		{
  1472  			desc: "multi-line comma operand",
  1473  			src: []string{
  1474  				`println(2,`,
  1475  				`3)`,
  1476  			},
  1477  			errorLine: -1,
  1478  		},
  1479  		{
  1480  			desc: "multi-line arithmetic operand",
  1481  			src: []string{
  1482  				`println(2. /`,
  1483  				`3.)`,
  1484  			},
  1485  			errorLine: -1,
  1486  		},
  1487  		{
  1488  			desc: "anonymous func call with no assignment",
  1489  			src: []string{
  1490  				`func() { println(3) }()`,
  1491  			},
  1492  			errorLine: -1,
  1493  		},
  1494  		{
  1495  			// to make sure that special handling of the above anonymous, does not break this general case.
  1496  			desc: "just func",
  1497  			src: []string{
  1498  				`func foo() { println(3) }`,
  1499  			},
  1500  			errorLine: -1,
  1501  		},
  1502  		{
  1503  			// to make sure that special handling of the above anonymous, does not break this general case.
  1504  			desc: "just method",
  1505  			src: []string{
  1506  				`type bar string`,
  1507  				`func (b bar) foo() { println(3) }`,
  1508  			},
  1509  			errorLine: -1,
  1510  		},
  1511  		{
  1512  			desc: "define a label",
  1513  			src: []string{
  1514  				`a:`,
  1515  			},
  1516  			errorLine: -1,
  1517  		},
  1518  	}
  1519  
  1520  	runREPL := func(t *testing.T, test testCase) {
  1521  		// TODO(mpl): use a pipe for the output as well, just as in TestConcurrentEvals5
  1522  		var stdout bytes.Buffer
  1523  		safeStdout := &safeBuffer{buf: &stdout}
  1524  		var stderr bytes.Buffer
  1525  		safeStderr := &safeBuffer{buf: &stderr}
  1526  		pin, pout := io.Pipe()
  1527  		i := interp.New(interp.Options{Stdin: pin, Stdout: safeStdout, Stderr: safeStderr})
  1528  		defer func() {
  1529  			// Closing the pipe also takes care of making i.REPL terminate,
  1530  			// hence freeing its goroutine.
  1531  			_ = pin.Close()
  1532  			_ = pout.Close()
  1533  		}()
  1534  
  1535  		go func() {
  1536  			_, _ = i.REPL()
  1537  		}()
  1538  		for k, v := range test.src {
  1539  			if _, err := pout.Write([]byte(v + "\n")); err != nil {
  1540  				t.Error(err)
  1541  			}
  1542  			Sleep(100 * time.Millisecond)
  1543  
  1544  			errMsg := safeStderr.String()
  1545  			if k == test.errorLine {
  1546  				if errMsg == "" {
  1547  					t.Fatalf("test %q: statement %q should have produced an error", test.desc, v)
  1548  				}
  1549  				break
  1550  			}
  1551  			if errMsg != "" {
  1552  				t.Fatalf("test %q: unexpected error: %v", test.desc, errMsg)
  1553  			}
  1554  		}
  1555  	}
  1556  
  1557  	for _, test := range tests {
  1558  		runREPL(t, test)
  1559  	}
  1560  }
  1561  
  1562  type safeBuffer struct {
  1563  	mu  sync.RWMutex
  1564  	buf *bytes.Buffer
  1565  }
  1566  
  1567  func (sb *safeBuffer) Read(p []byte) (int, error) {
  1568  	return sb.buf.Read(p)
  1569  }
  1570  
  1571  func (sb *safeBuffer) String() string {
  1572  	sb.mu.RLock()
  1573  	defer sb.mu.RUnlock()
  1574  	return sb.buf.String()
  1575  }
  1576  
  1577  func (sb *safeBuffer) Write(p []byte) (int, error) {
  1578  	sb.mu.Lock()
  1579  	defer sb.mu.Unlock()
  1580  	return sb.buf.Write(p)
  1581  }
  1582  
  1583  const (
  1584  	// CITimeoutMultiplier is the multiplier for all timeouts in the CI.
  1585  	CITimeoutMultiplier = 3
  1586  )
  1587  
  1588  // Sleep pauses the current goroutine for at least the duration d.
  1589  func Sleep(d time.Duration) {
  1590  	d = applyCIMultiplier(d)
  1591  	time.Sleep(d)
  1592  }
  1593  
  1594  func applyCIMultiplier(timeout time.Duration) time.Duration {
  1595  	ci := os.Getenv("CI")
  1596  	if ci == "" {
  1597  		return timeout
  1598  	}
  1599  	b, err := strconv.ParseBool(ci)
  1600  	if err != nil || !b {
  1601  		return timeout
  1602  	}
  1603  	return time.Duration(float64(timeout) * CITimeoutMultiplier)
  1604  }
  1605  
  1606  func TestREPLCommands(t *testing.T) {
  1607  	if testing.Short() {
  1608  		return
  1609  	}
  1610  	t.Setenv("YAEGI_PROMPT", "1") // To force prompts over non-tty streams
  1611  
  1612  	allDone := make(chan bool)
  1613  	runREPL := func() {
  1614  		done := make(chan error)
  1615  		pinin, poutin := io.Pipe()
  1616  		pinout, poutout := io.Pipe()
  1617  		i := interp.New(interp.Options{Stdin: pinin, Stdout: poutout})
  1618  		if err := i.Use(stdlib.Symbols); err != nil {
  1619  			t.Fatal(err)
  1620  		}
  1621  
  1622  		go func() {
  1623  			_, _ = i.REPL()
  1624  		}()
  1625  
  1626  		defer func() {
  1627  			_ = pinin.Close()
  1628  			_ = poutin.Close()
  1629  			_ = pinout.Close()
  1630  			_ = poutout.Close()
  1631  			allDone <- true
  1632  		}()
  1633  
  1634  		input := []string{
  1635  			`1/1`,
  1636  			`7/3`,
  1637  			`16/5`,
  1638  			`3./2`, // float
  1639  			`reflect.TypeOf(math_rand.Int)`,
  1640  			`reflect.TypeOf(crypto_rand.Int)`,
  1641  		}
  1642  		output := []string{
  1643  			`1`,
  1644  			`2`,
  1645  			`3`,
  1646  			`1.5`,
  1647  			`func() int`,
  1648  			`func(io.Reader, *big.Int) (*big.Int, error)`,
  1649  		}
  1650  
  1651  		go func() {
  1652  			sc := bufio.NewScanner(pinout)
  1653  			k := 0
  1654  			for sc.Scan() {
  1655  				l := sc.Text()
  1656  				if l != "> : "+output[k] {
  1657  					done <- fmt.Errorf("unexpected output, want %q, got %q", output[k], l)
  1658  					return
  1659  				}
  1660  				k++
  1661  				if k > 3 {
  1662  					break
  1663  				}
  1664  			}
  1665  			done <- nil
  1666  		}()
  1667  
  1668  		for _, v := range input {
  1669  			in := strings.NewReader(v + "\n")
  1670  			if _, err := io.Copy(poutin, in); err != nil {
  1671  				t.Fatal(err)
  1672  			}
  1673  			select {
  1674  			case err := <-done:
  1675  				if err != nil {
  1676  					t.Fatal(err)
  1677  				}
  1678  				return
  1679  			default:
  1680  				time.Sleep(time.Second)
  1681  			}
  1682  		}
  1683  
  1684  		if err := <-done; err != nil {
  1685  			t.Fatal(err)
  1686  		}
  1687  	}
  1688  
  1689  	go func() {
  1690  		runREPL()
  1691  	}()
  1692  
  1693  	timeout := time.NewTimer(10 * time.Second)
  1694  	select {
  1695  	case <-allDone:
  1696  	case <-timeout.C:
  1697  		t.Fatal("timeout")
  1698  	}
  1699  }
  1700  
  1701  func TestStdio(t *testing.T) {
  1702  	i := interp.New(interp.Options{})
  1703  	if err := i.Use(stdlib.Symbols); err != nil {
  1704  		t.Fatal(err)
  1705  	}
  1706  	i.ImportUsed()
  1707  	if _, err := i.Eval(`var x = os.Stdout`); err != nil {
  1708  		t.Fatal(err)
  1709  	}
  1710  	v, _ := i.Eval(`x`)
  1711  	if _, ok := v.Interface().(*os.File); !ok {
  1712  		t.Fatalf("%v not *os.file", v.Interface())
  1713  	}
  1714  }
  1715  
  1716  func TestNoGoFiles(t *testing.T) {
  1717  	i := interp.New(interp.Options{GoPath: build.Default.GOPATH})
  1718  	_, err := i.Eval(`import "github.com/traefik/yaegi/_test/p3"`)
  1719  	if strings.Contains(err.Error(), "no Go files in") {
  1720  		return
  1721  	}
  1722  
  1723  	t.Fatalf("failed to detect no Go files: %v", err)
  1724  }
  1725  
  1726  func TestIssue1142(t *testing.T) {
  1727  	i := interp.New(interp.Options{})
  1728  	runTests(t, i, []testCase{
  1729  		{src: "a := 1; // foo bar", res: "1"},
  1730  	})
  1731  }
  1732  
  1733  type Issue1149Array [3]float32
  1734  
  1735  func (v Issue1149Array) Foo() string  { return "foo" }
  1736  func (v *Issue1149Array) Bar() string { return "foo" }
  1737  
  1738  func TestIssue1149(t *testing.T) {
  1739  	i := interp.New(interp.Options{})
  1740  	if err := i.Use(interp.Exports{
  1741  		"pkg/pkg": map[string]reflect.Value{
  1742  			"Type": reflect.ValueOf((*Issue1149Array)(nil)),
  1743  		},
  1744  	}); err != nil {
  1745  		t.Fatal(err)
  1746  	}
  1747  	i.ImportUsed()
  1748  
  1749  	_, err := i.Eval(`
  1750  		type Type = pkg.Type
  1751  	`)
  1752  	if err != nil {
  1753  		t.Fatal(err)
  1754  	}
  1755  
  1756  	runTests(t, i, []testCase{
  1757  		{src: "Type{1, 2, 3}.Foo()", res: "foo"},
  1758  		{src: "Type{1, 2, 3}.Bar()", res: "foo"},
  1759  	})
  1760  }
  1761  
  1762  func TestIssue1150(t *testing.T) {
  1763  	i := interp.New(interp.Options{})
  1764  	_, err := i.Eval(`
  1765  		type ArrayT [3]float32
  1766  		type SliceT []float32
  1767  		type StructT struct { A, B, C float32 }
  1768  		type StructT2 struct { A, B, C float32 }
  1769  		type FooerT interface { Foo() string }
  1770  
  1771  		func (v ArrayT) Foo() string { return "foo" }
  1772  		func (v SliceT) Foo() string { return "foo" }
  1773  		func (v StructT) Foo() string { return "foo" }
  1774  		func (v *StructT2) Foo() string { return "foo" }
  1775  
  1776  		type Array = ArrayT
  1777  		type Slice = SliceT
  1778  		type Struct = StructT
  1779  		type Struct2 = StructT2
  1780  		type Fooer = FooerT
  1781  	`)
  1782  	if err != nil {
  1783  		t.Fatal(err)
  1784  	}
  1785  
  1786  	runTests(t, i, []testCase{
  1787  		{desc: "array", src: "Array{1, 2, 3}.Foo()", res: "foo"},
  1788  		{desc: "slice", src: "Slice{1, 2, 3}.Foo()", res: "foo"},
  1789  		{desc: "struct", src: "Struct{1, 2, 3}.Foo()", res: "foo"},
  1790  		{desc: "*struct", src: "Struct2{1, 2, 3}.Foo()", res: "foo"},
  1791  		{desc: "interface", src: "v := Fooer(Array{1, 2, 3}); v.Foo()", res: "foo"},
  1792  	})
  1793  }
  1794  
  1795  func TestIssue1151(t *testing.T) {
  1796  	type pkgStruct struct{ X int }
  1797  	type pkgArray [1]int
  1798  
  1799  	i := interp.New(interp.Options{})
  1800  	if err := i.Use(interp.Exports{
  1801  		"pkg/pkg": map[string]reflect.Value{
  1802  			"Struct": reflect.ValueOf((*pkgStruct)(nil)),
  1803  			"Array":  reflect.ValueOf((*pkgArray)(nil)),
  1804  		},
  1805  	}); err != nil {
  1806  		t.Fatal(err)
  1807  	}
  1808  	i.ImportUsed()
  1809  
  1810  	runTests(t, i, []testCase{
  1811  		{src: "x := pkg.Struct{1}", res: "{1}"},
  1812  		{src: "x := pkg.Array{1}", res: "[1]"},
  1813  	})
  1814  }
  1815  
  1816  func TestPassArgs(t *testing.T) {
  1817  	i := interp.New(interp.Options{Args: []string{"arg0", "arg1"}})
  1818  	if err := i.Use(stdlib.Symbols); err != nil {
  1819  		t.Fatal(err)
  1820  	}
  1821  	i.ImportUsed()
  1822  	runTests(t, i, []testCase{
  1823  		{src: "os.Args", res: "[arg0 arg1]"},
  1824  	})
  1825  }
  1826  
  1827  func TestRestrictedEnv(t *testing.T) {
  1828  	i := interp.New(interp.Options{Env: []string{"foo=bar"}})
  1829  	if err := i.Use(stdlib.Symbols); err != nil {
  1830  		t.Fatal(err)
  1831  	}
  1832  	i.ImportUsed()
  1833  	runTests(t, i, []testCase{
  1834  		{src: `os.Getenv("foo")`, res: "bar"},
  1835  		{src: `s, ok := os.LookupEnv("foo"); s`, res: "bar"},
  1836  		{src: `s, ok := os.LookupEnv("foo"); ok`, res: "true"},
  1837  		{src: `s, ok := os.LookupEnv("PATH"); s`, res: ""},
  1838  		{src: `s, ok := os.LookupEnv("PATH"); ok`, res: "false"},
  1839  		{src: `os.Setenv("foo", "baz"); os.Environ()`, res: "[foo=baz]"},
  1840  		{src: `os.ExpandEnv("foo is ${foo}")`, res: "foo is baz"},
  1841  		{src: `os.Unsetenv("foo"); os.Environ()`, res: "[]"},
  1842  		{src: `os.Setenv("foo", "baz"); os.Environ()`, res: "[foo=baz]"},
  1843  		{src: `os.Clearenv(); os.Environ()`, res: "[]"},
  1844  		{src: `os.Setenv("foo", "baz"); os.Environ()`, res: "[foo=baz]"},
  1845  	})
  1846  	if s, ok := os.LookupEnv("foo"); ok {
  1847  		t.Fatal("expected \"\", got " + s)
  1848  	}
  1849  }
  1850  
  1851  func TestIssue1388(t *testing.T) {
  1852  	i := interp.New(interp.Options{Env: []string{"foo=bar"}})
  1853  	err := i.Use(stdlib.Symbols)
  1854  	if err != nil {
  1855  		t.Fatal(err)
  1856  	}
  1857  
  1858  	_, err = i.Eval(`x := errors.New("")`)
  1859  	if err == nil {
  1860  		t.Fatal("Expected an error")
  1861  	}
  1862  
  1863  	_, err = i.Eval(`import "errors"`)
  1864  	if err != nil {
  1865  		t.Fatal(err)
  1866  	}
  1867  
  1868  	_, err = i.Eval(`x := errors.New("")`)
  1869  	if err != nil {
  1870  		t.Fatal(err)
  1871  	}
  1872  }
  1873  
  1874  func TestIssue1383(t *testing.T) {
  1875  	const src = `
  1876  			package main
  1877  
  1878  			func main() {
  1879  				fmt.Println("Hello")
  1880  			}
  1881  		`
  1882  
  1883  	interp := interp.New(interp.Options{})
  1884  	err := interp.Use(stdlib.Symbols)
  1885  	if err != nil {
  1886  		t.Fatal(err)
  1887  	}
  1888  	_, err = interp.Eval(`import "fmt"`)
  1889  	if err != nil {
  1890  		t.Fatal(err)
  1891  	}
  1892  
  1893  	ast, err := parser.ParseFile(interp.FileSet(), "_.go", src, parser.DeclarationErrors)
  1894  	if err != nil {
  1895  		t.Fatal(err)
  1896  	}
  1897  	prog, err := interp.CompileAST(ast)
  1898  	if err != nil {
  1899  		t.Fatal(err)
  1900  	}
  1901  	_, err = interp.Execute(prog)
  1902  	if err != nil {
  1903  		t.Fatal(err)
  1904  	}
  1905  }