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