gitlab.com/ethan.reesor/vscode-notebooks/yaegi@v0.0.0-20220417214422-5c573557938e/interp/interp_eval_test.go (about)

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