github.com/goplus/igop@v0.25.0/interp_test.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package igop_test
     6  
     7  // This test runs the SSA interpreter over sample Go programs.
     8  // Because the interpreter requires intrinsics for assembly
     9  // functions and many low-level runtime routines, it is inherently
    10  // not robust to evolutionary change in the standard library.
    11  // Therefore the test cases are restricted to programs that
    12  // use a fake standard library in testdata/src containing a tiny
    13  // subset of simple functions useful for writing assertions.
    14  //
    15  // We no longer attempt to interpret any real standard packages such as
    16  // fmt or testing, as it proved too fragile.
    17  
    18  import (
    19  	"bytes"
    20  	"context"
    21  	"fmt"
    22  	"log"
    23  	"os"
    24  	"path/filepath"
    25  	"reflect"
    26  	"runtime"
    27  	"strings"
    28  	"testing"
    29  	"time"
    30  
    31  	"github.com/goplus/igop"
    32  	"github.com/goplus/igop/testdata/info"
    33  
    34  	_ "github.com/goplus/igop/pkg/bytes"
    35  	_ "github.com/goplus/igop/pkg/errors"
    36  	_ "github.com/goplus/igop/pkg/fmt"
    37  	_ "github.com/goplus/igop/pkg/math"
    38  	_ "github.com/goplus/igop/pkg/os"
    39  	_ "github.com/goplus/igop/pkg/path/filepath"
    40  	_ "github.com/goplus/igop/pkg/reflect"
    41  	_ "github.com/goplus/igop/pkg/runtime"
    42  	_ "github.com/goplus/igop/pkg/strings"
    43  	_ "github.com/goplus/igop/pkg/sync"
    44  	_ "github.com/goplus/igop/pkg/time"
    45  )
    46  
    47  // These are files in github.com/goplus/igop/testdata/.
    48  var testdataTests = []string{
    49  	"boundmeth.go",
    50  	"complit.go",
    51  	"coverage.go",
    52  	"defer.go",
    53  	"fieldprom.go",
    54  	"ifaceconv.go",
    55  	"ifaceprom.go",
    56  	"initorder.go",
    57  	"methprom.go",
    58  	"mrvchain.go",
    59  	"range.go",
    60  	"recover.go",
    61  	"reflect.go",
    62  	"static.go",
    63  	"recover2.go",
    64  	"static.go",
    65  	"issue23536.go",
    66  	"tinyfin.go",
    67  	"issue5963.go",
    68  }
    69  
    70  func runInput(t *testing.T, input string) bool {
    71  	fmt.Println("Input:", input)
    72  	start := time.Now()
    73  	_, err := igop.Run(input, nil, 0)
    74  	sec := time.Since(start).Seconds()
    75  	if err != nil {
    76  		t.Error(err)
    77  		fmt.Printf("FAIL %0.3fs\n", sec)
    78  		return false
    79  	}
    80  	fmt.Printf("PASS %0.3fs\n", sec)
    81  	return true
    82  }
    83  
    84  // TestTestdataFiles runs the interpreter on testdata/*.go.
    85  func TestTestdataFiles(t *testing.T) {
    86  	cwd, err := os.Getwd()
    87  	if err != nil {
    88  		log.Fatal(err)
    89  	}
    90  
    91  	var failures []string
    92  	for _, input := range testdataTests {
    93  		if !runInput(t, filepath.Join(cwd, "testdata", input)) {
    94  			failures = append(failures, input)
    95  		}
    96  	}
    97  	printFailures(failures)
    98  }
    99  
   100  func printFailures(failures []string) {
   101  	if failures != nil {
   102  		fmt.Println("The following tests failed:")
   103  		for _, f := range failures {
   104  			fmt.Printf("\t%s\n", f)
   105  		}
   106  	}
   107  }
   108  
   109  func TestUntypedNil(t *testing.T) {
   110  	src := `package main
   111  
   112  type T func()
   113  
   114  func main() {
   115  	if T(nil) != nil {
   116  		panic("error")
   117  	}
   118  	if !(T(nil) == nil) {
   119  		panic("error")
   120  	}
   121  }
   122  `
   123  	_, err := igop.RunFile("main.go", src, nil, 0)
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  }
   128  
   129  func TestRegisterExternal(t *testing.T) {
   130  	ctx := igop.NewContext(0)
   131  	ctx.RegisterExternal("main.call", func(i, j int) int {
   132  		return i * j
   133  	})
   134  	var v int = 200
   135  	ctx.RegisterExternal("main.v", &v)
   136  	src := `package main
   137  
   138  func call(i, j int) int {
   139  	return i+j
   140  }
   141  
   142  var v int
   143  
   144  func main() {
   145  	if n := call(10,20); n != 200 {
   146  		panic(n)
   147  	}
   148  	if v != 200 {
   149  		panic(v)
   150  	}
   151  }
   152  `
   153  	_, err := ctx.RunFile("main.go", src, nil)
   154  	if err != nil {
   155  		t.Fatal(err)
   156  	}
   157  
   158  	// reset override func
   159  	ctx.RegisterExternal("main.call", nil)
   160  	_, err = ctx.RunFile("main.go", src, nil)
   161  	if err == nil || err.Error() != "30" {
   162  		t.Fatal("must panic 30")
   163  	}
   164  }
   165  
   166  func TestOsExit(t *testing.T) {
   167  	src := `package main
   168  
   169  import "os"
   170  
   171  func main() {
   172  	os.Exit(-2)
   173  }
   174  `
   175  	code, err := igop.RunFile("main.go", src, nil, 0)
   176  	if err != nil {
   177  		t.Fatal(err)
   178  	}
   179  	if code != -2 {
   180  		t.Fatalf("exit code %v, must -2", code)
   181  	}
   182  }
   183  
   184  func TestOpAlloc(t *testing.T) {
   185  	src := `package main
   186  
   187  type T struct {
   188  	n1 int
   189  	n2 int
   190  }
   191  
   192  func (t T) call() int {
   193  	return t.n1 * t.n2
   194  }
   195  
   196  func main() {
   197  	var n int
   198  	for i := 0; i < 3; i++ {
   199  		n += T{i,3}.call()
   200  	}
   201  	if n != 9 {
   202  		panic(n)
   203  	}
   204  }
   205  `
   206  	_, err := igop.RunFile("main.go", src, nil, 0)
   207  	if err != nil {
   208  		t.Fatal(err)
   209  	}
   210  }
   211  
   212  func TestOpBin(t *testing.T) {
   213  	src := `package main
   214  
   215  func main() {
   216  	a := 10 // 1010
   217  	b := 12 // 1100
   218  	n1 := a + b
   219  	n2 := a - b
   220  	n3 := a * b
   221  	n4 := a / b
   222  	n5 := a % b
   223  	n6 := a & b
   224  	n7 := a | b
   225  	n8 := a ^ b
   226  	n9 := a &^ b
   227  	n10 := a << 3
   228  	n11 := a >> 3
   229  	v1 := a > b
   230  	v2 := a < b
   231  	v3 := a >= b
   232  	v4 := a <= b
   233  	v5 := a == b
   234  	v6 := a != b
   235  	if n1 != 22 || n2 != -2 || n3 != 120 || n4 != 0 || n5 != 10 || n6 != 8 ||
   236  		n7 != 14 || n8 != 6 || n9 != 2 || n10 != 80 || n11 != 1 ||
   237  		v1 != false || v2 != true || v3 != false || v4 != true || v5 != false || v6 != true {
   238  		println(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11)
   239  		println(v1, v2, v3, v4, v5, v6)
   240  		panic("error")
   241  	}
   242  }
   243  `
   244  	_, err := igop.RunFile("main.go", src, nil, 0)
   245  	if err != nil {
   246  		t.Fatal(err)
   247  	}
   248  }
   249  
   250  func TestOpChangeType(t *testing.T) {
   251  	src := `package main
   252  
   253  type T func(int, int) int
   254  
   255  func add(i, j int) int {
   256  	return i + j
   257  }
   258  
   259  type I interface{}
   260  
   261  func main() {
   262  	// static change type
   263  	fn := T(add)
   264  	if n := fn(10, 20); n != 30 {
   265  		panic(n)
   266  	}
   267  	var i interface{} = I(nil)
   268  	if i != nil {
   269  		panic("must nil")
   270  	}
   271  	// dynamic change type
   272  	var k interface{}
   273  	i = I(k)
   274  	if i != nil {
   275  		panic("must nil")
   276  	}
   277  	i = I(100)
   278  	if i == nil {
   279  		panic("must not nil")
   280  	}
   281  }
   282  `
   283  	_, err := igop.RunFile("main.go", src, nil, 0)
   284  	if err != nil {
   285  		t.Fatal(err)
   286  	}
   287  }
   288  
   289  func TestOpIndex(t *testing.T) {
   290  	src := `package main
   291  
   292  func main() {
   293  	var n int
   294  	for _, v := range [3]int{1, 2, 4} {
   295  		n += v
   296  	}
   297  	if n != 7 {
   298  		panic(n)
   299  	}
   300  }
   301  `
   302  	_, err := igop.RunFile("main.go", src, nil, 0)
   303  	if err != nil {
   304  		t.Fatal(err)
   305  	}
   306  }
   307  
   308  func TestUnderscopeMap(t *testing.T) {
   309  	src := `package main
   310  
   311  type key struct {
   312  	_ int
   313  	x int
   314  }
   315  
   316  var (
   317  	s1 = "s1"
   318  	s2 = "s2"
   319  	s3 = "s3"
   320  	s4 = "s4"
   321  )
   322  
   323  func main() {
   324  	m := make(map[key]string)
   325  	m[key{0, 1}] = s1
   326  	m[key{0, 2}] = s2
   327  	m[key{0, 3}] = s3
   328  	m[key{1, 1}] = s4
   329  	m[key{1, 2}] = "s22"
   330  	if n := len(m); n != 3 {
   331  		panic(n)
   332  	}
   333  	if v := m[key{2, 2}]; v != "s22" {
   334  		panic(v)
   335  	}
   336  	if v, ok := m[key{1,4}]; ok {
   337  		panic(v)
   338  	}
   339  }
   340  `
   341  	_, err := igop.RunFile("main.go", src, nil, 0)
   342  	if err != nil {
   343  		t.Fatal(err)
   344  	}
   345  }
   346  
   347  func TestOpSend(t *testing.T) {
   348  	src := `package main
   349  
   350  import (
   351  	"fmt"
   352  )
   353  
   354  type T struct{}
   355  
   356  func main() {
   357  	ch := make(chan *T)
   358  	go func() {
   359  		ch <- nil
   360  	}()
   361  	v := <-ch
   362  	if v != nil {
   363  		panic("must nil")
   364  	}
   365  	if s := fmt.Sprintf("%T", v); s != "*main.T" {
   366  		panic(s)
   367  	}
   368  	go func() {
   369  		ch <- &T{}
   370  	}()
   371  	v = <-ch
   372  	if v == nil {
   373  		panic("must not nil")
   374  	}
   375  }
   376  `
   377  	_, err := igop.RunFile("main.go", src, nil, 0)
   378  	if err != nil {
   379  		t.Fatal(err)
   380  	}
   381  }
   382  
   383  func TestShadowedMethod(t *testing.T) {
   384  	src := `// run
   385  
   386  // Copyright 2018 The Go Authors. All rights reserved.
   387  // Use of this source code is governed by a BSD-style
   388  // license that can be found in the LICENSE file.
   389  
   390  // When computing method sets with shadowed methods, make sure we
   391  // compute whether a method promotion involved a pointer traversal
   392  // based on the promoted method, not the shadowed method.
   393  
   394  package main
   395  
   396  import (
   397  	"bytes"
   398  	"fmt"
   399  )
   400  
   401  type mystruct struct {
   402  	f int
   403  }
   404  
   405  func (t mystruct) String() string {
   406  	return "FAIL"
   407  }
   408  
   409  func main() {
   410  	type deep struct {
   411  		mystruct
   412  	}
   413  	s := struct {
   414  		deep
   415  		*bytes.Buffer
   416  	}{
   417  		deep{},
   418  		bytes.NewBufferString("ok"),
   419  	}
   420  
   421  	if got := s.String(); got != "ok" {
   422  		panic(got)
   423  	}
   424  
   425  	var i fmt.Stringer = s
   426  	if got := i.String(); got != "ok" {
   427  		panic(got)
   428  	}
   429  }
   430  `
   431  	_, err := igop.RunFile("main.go", src, nil, 0)
   432  	if err != nil {
   433  		t.Fatal(err)
   434  	}
   435  }
   436  
   437  func TestConvertUnsafePointer(t *testing.T) {
   438  	src := `package main
   439  
   440  import (
   441  	"unsafe"
   442  )
   443  
   444  func main() {
   445  	a := [4]int{0, 1, 2, 3}
   446  	p := unsafe.Pointer(&a)
   447  	p2 := unsafe.Pointer(uintptr(p) + 2*unsafe.Sizeof(a[0]))
   448  	*(*int)(p2) = 4
   449  	if a != [4]int{0, 1, 4, 3} {
   450  		panic("error")
   451  	}
   452  }
   453  `
   454  	_, err := igop.RunFile("main.go", src, nil, 0)
   455  	if err != nil {
   456  		t.Fatal(err)
   457  	}
   458  }
   459  
   460  func TestBuiltinPrintln(t *testing.T) {
   461  	src := `// run
   462  
   463  // Copyright 2014 The Go Authors. All rights reserved.
   464  // Use of this source code is governed by a BSD-style
   465  // license that can be found in the LICENSE file.
   466  
   467  // Test internal print routines that are generated
   468  // by the print builtin.  This test is not exhaustive,
   469  // we're just checking that the formatting is correct.
   470  
   471  package main
   472  
   473  func main() {
   474  	println((interface{})(nil)) // printeface
   475  	println((interface {        // printiface
   476  		f()
   477  	})(nil))
   478  	println((map[int]int)(nil)) // printpointer
   479  	println(([]int)(nil))       // printslice
   480  	println(int64(-7))          // printint
   481  	println(uint64(7))          // printuint
   482  	println(uint32(7))          // printuint
   483  	println(uint16(7))          // printuint
   484  	println(uint8(7))           // printuint
   485  	println(uint(7))            // printuint
   486  	println(uintptr(7))         // printuint
   487  	println(8.0)                // printfloat
   488  	println(complex(9.0, 10.0)) // printcomplex
   489  	println(true)               // printbool
   490  	println(false)              // printbool
   491  	println("hello")            // printstring
   492  	println("one", "two")       // printsp
   493  
   494  	// test goprintf
   495  	defer println((interface{})(nil))
   496  	defer println((interface {
   497  		f()
   498  	})(nil))
   499  	defer println((map[int]int)(nil))
   500  	defer println(([]int)(nil))
   501  	defer println(int64(-11))
   502  	defer println(uint64(12))
   503  	defer println(uint32(12))
   504  	defer println(uint16(12))
   505  	defer println(uint8(12))
   506  	defer println(uint(12))
   507  	defer println(uintptr(12))
   508  	defer println(13.0)
   509  	defer println(complex(14.0, 15.0))
   510  	defer println(true)
   511  	defer println(false)
   512  	defer println("hello")
   513  	defer println("one", "two")
   514  }
   515  `
   516  	out := `(0x0,0x0)
   517  (0x0,0x0)
   518  0x0
   519  [0/0]0x0
   520  -7
   521  7
   522  7
   523  7
   524  7
   525  7
   526  7
   527  +8.000000e+000
   528  (+9.000000e+000+1.000000e+001i)
   529  true
   530  false
   531  hello
   532  one two
   533  one two
   534  hello
   535  false
   536  true
   537  (+1.400000e+001+1.500000e+001i)
   538  +1.300000e+001
   539  12
   540  12
   541  12
   542  12
   543  12
   544  12
   545  -11
   546  [0/0]0x0
   547  0x0
   548  (0x0,0x0)
   549  (0x0,0x0)
   550  `
   551  	ctx := igop.NewContext(0)
   552  	var buf bytes.Buffer
   553  	ctx.SetPrintOutput(&buf)
   554  	_, err := ctx.RunFile("main.go", src, nil)
   555  	if err != nil {
   556  		t.Fatal(err)
   557  	}
   558  	if buf.String() != out {
   559  		t.Fatal("error")
   560  	}
   561  }
   562  
   563  type panicinfo struct {
   564  	src string
   565  	err string
   566  }
   567  
   568  func TestPanicInfo(t *testing.T) {
   569  	infos := []panicinfo{
   570  		{`panic(100)`, `100`},
   571  		{`panic(100.0)`, `+1.000000e+002`},
   572  		{`panic("hello")`, `hello`},
   573  		{`panic((*interface{})(nil))`, `(*interface {}) 0x0`},
   574  		{`type T int; panic(T(100))`, `main.T(100)`},
   575  		{`type T float64; panic(T(100.0))`, `main.T(+1.000000e+002)`},
   576  		{`type T string; panic(T("hello"))`, `main.T("hello")`},
   577  		{`type T struct{}; panic((*T)(nil))`, `(*main.T) 0x0`},
   578  	}
   579  	ctx := igop.NewContext(0)
   580  	for _, info := range infos {
   581  		src := fmt.Sprintf("package main;func main(){%v}", info.src)
   582  		code, err := ctx.RunFile("main.go", src, nil)
   583  		if code != 2 || err == nil {
   584  			t.Fatalf("%v must panic", info.src)
   585  		}
   586  		if s := err.Error(); s != info.err {
   587  			t.Fatalf("%v err is %v, want %v", info.src, s, info.err)
   588  		}
   589  	}
   590  }
   591  
   592  func TestPanicError(t *testing.T) {
   593  	src := `package main
   594  import "errors"
   595  
   596  func test() {
   597  	panic(errors.New("error info"))
   598  }
   599  
   600  func main() {
   601  	test()
   602  }
   603  `
   604  	_, err := igop.RunFile("main.go", src, nil, 0)
   605  	if err == nil {
   606  		t.Fatal("must panic")
   607  	}
   608  	if s := err.Error(); s != "error info" {
   609  		t.Fatalf("error %q", s)
   610  	}
   611  	pe, ok := err.(igop.PanicError)
   612  	if !ok {
   613  		t.Fatal("error type must igop.PanicError")
   614  	}
   615  	ve, ok := pe.Value.(error)
   616  	if !ok {
   617  		t.Fatal("e.Value type must error")
   618  	}
   619  	if s := ve.Error(); s != "error info" {
   620  		t.Fatalf("e.Value %q", s)
   621  	}
   622  	t.Log("dump panic stack\n", string(pe.Stack()))
   623  }
   624  
   625  func TestPanicErrorRecover(t *testing.T) {
   626  	src := `package main
   627  import "errors"
   628  func main() {
   629  	defer func() {
   630  		err := recover()
   631  		if err == nil {
   632  			panic("must error")
   633  		}
   634  		if s := err.(error).Error(); s != "error info" {
   635  			panic(s)
   636  		}
   637  	}()
   638  	panic(errors.New("error info"))
   639  }
   640  `
   641  	_, err := igop.RunFile("main.go", src, nil, 0)
   642  	if err != nil {
   643  		t.Fatal(err)
   644  	}
   645  }
   646  
   647  func TestEnablePrintAny(t *testing.T) {
   648  	src := `package main
   649  
   650  type T struct {
   651  	X int
   652  	Y int
   653  }
   654  func main() {
   655  	println([2]int{100,200})
   656  	println(T{100,200})
   657  }
   658  `
   659  	ctx := igop.NewContext(0)
   660  	var buf bytes.Buffer
   661  	ctx.SetPrintOutput(&buf)
   662  	_, err := ctx.RunFile("main.go", src, nil)
   663  	if err == nil {
   664  		t.Fatal("must panic")
   665  	}
   666  	if s := err.Error(); s != "illegal types for operand: print\n\t[2]int" {
   667  		t.Fatal(s)
   668  	}
   669  	ctx.Mode |= igop.EnablePrintAny
   670  	_, err = ctx.RunFile("main.go", src, nil)
   671  	if err != nil {
   672  		t.Fatal(err)
   673  	}
   674  	if s := buf.String(); s != "[100 200]\n{100 200}\n" {
   675  		t.Fatal(s)
   676  	}
   677  }
   678  
   679  func TestFib(t *testing.T) {
   680  	src := `package main
   681  
   682  import (
   683  	"sync"
   684  )
   685  
   686  func fib(n int) int {
   687  	if n < 2 {
   688  		return n
   689  	}
   690  	return fib(n-2) + fib(n-1)
   691  }
   692  
   693  func main() {
   694  	var wg sync.WaitGroup
   695  	const N = 10
   696  	for i := 0; i < N; i++ {
   697  		wg.Add(1)
   698  		go func() {
   699  			if fib(20) != 6765 {
   700  				panic("error")
   701  			}
   702  			wg.Done()
   703  		}()
   704  	}
   705  	wg.Wait()
   706  }
   707  `
   708  	_, err := igop.RunFile("main.go", src, nil, 0)
   709  	if err != nil {
   710  		t.Fatal(err)
   711  	}
   712  }
   713  
   714  func TestFibv(t *testing.T) {
   715  	src := `package main
   716  
   717  import "sync"
   718  
   719  func main() {
   720  	var fib func(n int) int
   721  	fib = func(n int) int {
   722  		if n < 2 {
   723  			return n
   724  		}
   725  		return fib(n-2) + fib(n-1)
   726  	}
   727  
   728  	var wg sync.WaitGroup
   729  	const N = 10
   730  	for i := 0; i < N; i++ {
   731  		wg.Add(1)
   732  		go func() {
   733  			if fib(20) != 6765 {
   734  				panic("error")
   735  			}
   736  			wg.Done()
   737  		}()
   738  	}
   739  	wg.Wait()
   740  }
   741  `
   742  	_, err := igop.RunFile("main.go", src, nil, 0)
   743  	if err != nil {
   744  		t.Fatal(err)
   745  	}
   746  }
   747  
   748  func TestFibi(t *testing.T) {
   749  	src := `package main
   750  
   751  import "sync"
   752  
   753  type I interface {
   754  	fib(i I, n int) int
   755  }
   756  
   757  type T struct {
   758  }
   759  
   760  func (t *T) fib(i I, n int) int {
   761  	if n < 2 {
   762  		return n
   763  	}
   764  	return i.fib(i, n-2) + i.fib(i, n-1)
   765  }
   766  
   767  func fib(n int) int {
   768  	t := &T{}
   769  	return t.fib(t, n)
   770  }
   771  
   772  func main() {
   773  	var wg sync.WaitGroup
   774  	const N = 10
   775  	for i := 0; i < N; i++ {
   776  		wg.Add(1)
   777  		go func() {
   778  			if fib(20) != 6765 {
   779  				panic("error")
   780  			}
   781  			wg.Done()
   782  		}()
   783  	}
   784  	wg.Wait()
   785  }
   786  `
   787  	_, err := igop.RunFile("main.go", src, nil, 0)
   788  	if err != nil {
   789  		t.Fatal(err)
   790  	}
   791  }
   792  
   793  func TestBinOpInt(t *testing.T) {
   794  	// + - * / % & ^ &^ < <= > >=
   795  	tsrc := `package main
   796  
   797  import "fmt"
   798  
   799  type T $int
   800  
   801  func main() {
   802  	// 0101 0110
   803  	test(5, 6)
   804  	testConst()
   805  	testDivideZero()
   806  }
   807  
   808  func testConst() {
   809  	var a T = 4
   810  	var b T = 2
   811  	var c T = 4
   812  	check(a+b,6)
   813  	check(a-b,2)
   814  	check(a*b,8)
   815  	check(a/b,2)
   816  	check(a%b,0)
   817  	check(a&b,0)
   818  	check(a|b,6)
   819  	check(a^b,6)
   820  	check(a&^b,4)
   821  	assert(a>b)
   822  	assert(a>=b)
   823  	assert(b<a)
   824  	assert(a<=a)
   825  	assert(a==c)
   826  	assert(a!=b)
   827  }
   828  
   829  func testDivideZero() {
   830  	defer func() {
   831  		if r := recover(); r == nil {
   832  			panic("must panic")
   833  		}
   834  	}()
   835  	var a T
   836  	var b T
   837  	_ = a/b
   838  }
   839  
   840  func test(a, b T) {
   841  	check(a+1, 6)
   842  	check(1+a, 6)
   843  	check(a+b, 11)
   844  	check(a-1, 4)
   845  	check(6-a, 1)
   846  	check(b-a, 1)
   847  	check(a*2, 10)
   848  	check(2*a, 10)
   849  	check(a*b, 30)
   850  	check(a/2, 2)
   851  	check(T(10)/a, 2)
   852  	check(a/b, 0)
   853  	check(a%2, 1)
   854  	check(10%a, 0)
   855  	check(b%a, 1)
   856  	check(a&4, 4)
   857  	check(1&a, 1)
   858  	check(a&b, 4)
   859  	check(a|4, 5)
   860  	check(2|a, 7)
   861  	check(a|b, 7)
   862  	check(a^2, 7)
   863  	check(7^a, 2)
   864  	check(a^b, 3)
   865  	check(a&^3, 4)
   866  	check(3&^a, 2)
   867  	check(a&^b, 1)
   868  	assert(a < 6)
   869  	assert(4 < a)
   870  	assert(a < b)
   871  	assert(a <= 5)
   872  	assert(4 <= a)
   873  	assert(a <= b)
   874  	assert(a > 4)
   875  	assert(6 > a)
   876  	assert(b > a)
   877  	assert(a >= 5)
   878  	assert(6 >= a)
   879  	assert(b >= a)
   880  	assert(a == 5)
   881  	assert(5 == a)
   882  	assert(a != 6)
   883  	assert(6 != a)
   884  	assert(a != b)
   885  	assert(a+1 == b)
   886  }
   887  
   888  func assert(t bool) {
   889  	if !t {
   890  		panic("error")
   891  	}
   892  }
   893  
   894  func check(a, b T) {
   895  	if a != b {
   896  		panic(fmt.Errorf("error %v != %v", a, b))
   897  	}
   898  }
   899  `
   900  	types := []string{
   901  		"int", "int8", "int16", "int32", "int64",
   902  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
   903  	}
   904  	for _, s := range types {
   905  		t.Log("test binop xtype", s)
   906  		src := strings.Replace(tsrc, "$int", "="+s, 1)
   907  		_, err := igop.RunFile("main.go", src, nil, 0)
   908  		if err != nil {
   909  			t.Fatal(err)
   910  		}
   911  	}
   912  	for _, s := range types {
   913  		t.Log("test binop named", s)
   914  		src := strings.Replace(tsrc, "$int", s, 1)
   915  		_, err := igop.RunFile("main.go", src, nil, 0)
   916  		if err != nil {
   917  			t.Fatal(err)
   918  		}
   919  	}
   920  }
   921  
   922  func TestBinOpFloat(t *testing.T) {
   923  	tsrc := `package main
   924  
   925  import "fmt"
   926  
   927  type T $float
   928  
   929  func main() {
   930  	test(5.0, 6.5)
   931  	testConst()
   932  }
   933  
   934  func testConst() {
   935  	var a T = 4.0
   936  	var b T = 2.0
   937  	var c T = 4.0
   938  	check(a+b,6)
   939  	check(a-b,2)
   940  	check(a*b,8)
   941  	check(a/b,2)
   942  	assert(a>b)
   943  	assert(a>=b)
   944  	assert(b<a)
   945  	assert(a<=a)
   946  	assert(a==c)
   947  	assert(a!=b)
   948  }
   949  
   950  func test(a, b T) {
   951  	check(a+1, 6)
   952  	check(1+a, 6)
   953  	check(a+b, 11.5)
   954  	check(a-1, 4)
   955  	check(6-a, 1)
   956  	check(b-a, 1.5)
   957  	check(a*2, 10)
   958  	check(2*a, 10)
   959  	check(a*b, 32.5)
   960  	check(a/2, 2.5)
   961  	check(10/a, 2)
   962  	check(a/b, 5.0/6.5)
   963  	assert(a < 6)
   964  	assert(4 < a)
   965  	assert(a < b)
   966  	assert(a <= 5)
   967  	assert(4 <= a)
   968  	assert(a <= b)
   969  	assert(a > 4)
   970  	assert(6 > a)
   971  	assert(b > a)
   972  	assert(a >= 5)
   973  	assert(6 >= a)
   974  	assert(b >= a)
   975  	assert(a == 5)
   976  	assert(5 == a)
   977  	assert(a != 6)
   978  	assert(6 != a)
   979  	assert(a != b)
   980  	assert(a+1.5 == b)
   981  }
   982  
   983  func assert(t bool) {
   984  	if !t {
   985  		panic("error")
   986  	}
   987  }
   988  
   989  func check(a, b T) {
   990  	if a != b {
   991  		panic(fmt.Errorf("error %v != %v", a, b))
   992  	}
   993  }
   994  `
   995  	types := []string{
   996  		"float32",
   997  		"float64",
   998  	}
   999  	for _, s := range types {
  1000  		t.Log("test binop xtype", s)
  1001  		src := strings.Replace(tsrc, "$float", "="+s, 1)
  1002  		_, err := igop.RunFile("main.go", src, nil, 0)
  1003  		if err != nil {
  1004  			t.Fatal(err)
  1005  		}
  1006  	}
  1007  	for _, s := range types {
  1008  		t.Log("test binop named", s)
  1009  		src := strings.Replace(tsrc, "$float", s, 1)
  1010  		_, err := igop.RunFile("main.go", src, nil, 0)
  1011  		if err != nil {
  1012  			t.Fatal(err)
  1013  		}
  1014  	}
  1015  }
  1016  
  1017  func TestBinOpComplex(t *testing.T) {
  1018  	tsrc := `package main
  1019  
  1020  import "fmt"
  1021  
  1022  type T $complex
  1023  
  1024  func main() {
  1025  	test(1+2i, 3+4i)
  1026  	testConst()
  1027  }
  1028  
  1029  func testConst() {
  1030  	var a T = 4i
  1031  	var b T = 2i
  1032  	var c T = 4i
  1033  	check(a+b,6i)
  1034  	check(a-b,2i)
  1035  	check(a*b,-8)
  1036  	check(a/b,2)
  1037  	assert(a == c)
  1038  	assert(a != b)
  1039  }
  1040  
  1041  func test(a, b T) {
  1042  	check(a+1+2i, 2+4i)
  1043  	check(1+a, 2+2i)
  1044  	check(a+b, 4+6i)
  1045  	check(a-1, 2i)
  1046  	check(6-a, 5-2i)
  1047  	check(b-a, 2+2i)
  1048  	check(a*(2+3i), -4+7i)
  1049  	check((2-3i)*a, 8+1i)
  1050  	check(a*b, -5+10i)
  1051  	check(a/2i, 1-0.5i)
  1052  	check(10/a, 2-4i)
  1053  	check(a/b, 0.44+0.08i)
  1054  	assert(a == 1+2i)
  1055  	assert(1+2i == a)
  1056  	assert(a != 2+2i)
  1057  	assert(2+2i != a)
  1058  	assert(a != b)
  1059  	assert(a+2+2i == b)
  1060  }
  1061  
  1062  func assert(t bool) {
  1063  	if !t {
  1064  		panic("error")
  1065  	}
  1066  }
  1067  
  1068  func check(a, b T) {
  1069  	if a != b {
  1070  		panic(fmt.Errorf("error %v != %v", a, b))
  1071  	}
  1072  }
  1073  
  1074  `
  1075  	types := []string{
  1076  		"complex64",
  1077  		"complex128",
  1078  	}
  1079  	for _, s := range types {
  1080  		t.Log("test binop xtype", s)
  1081  		src := strings.Replace(tsrc, "$complex", "="+s, 1)
  1082  		_, err := igop.RunFile("main.go", src, nil, 0)
  1083  		if err != nil {
  1084  			t.Fatal(err)
  1085  		}
  1086  	}
  1087  	for _, s := range types {
  1088  		t.Log("test binop named", s)
  1089  		src := strings.Replace(tsrc, "$complex", s, 1)
  1090  		_, err := igop.RunFile("main.go", src, nil, 0)
  1091  		if err != nil {
  1092  			t.Fatal(err)
  1093  		}
  1094  	}
  1095  }
  1096  
  1097  func TestBinOpString(t *testing.T) {
  1098  	tsrc := `package main
  1099  
  1100  import "fmt"
  1101  
  1102  type T = string
  1103  
  1104  func main() {
  1105  	test("go", "ssa", "go")
  1106  	testConst()
  1107  }
  1108  
  1109  func testConst() {
  1110  	var a T = "hello"
  1111  	var b T = "world"
  1112  	var c T = "hello"
  1113  	check(a+b,"helloworld")
  1114  	assert(a < b)
  1115  	assert(a <= b)
  1116  	assert(b > a)
  1117  	assert(b >= a)
  1118  	assert(a == c)
  1119  	assert(a != b)
  1120  }
  1121  
  1122  func test(a, b, c T) {
  1123  	check(a+"run", "gorun")
  1124  	check("run"+a, "rungo")
  1125  	check(a+b, "gossa")
  1126  	assert(a < "go1")
  1127  	assert("ao" < a)
  1128  	assert(a < b)
  1129  	assert(a <= "go")
  1130  	assert("ao" <= a)
  1131  	assert(a <= b)
  1132  	assert(a > "ao")
  1133  	assert("go1" > a)
  1134  	assert(b > a)
  1135  	assert(a >= "go")
  1136  	assert("go1" >= a)
  1137  	assert(b >= a)
  1138  	assert(a == "go")
  1139  	assert("go" == a)
  1140  	assert(a != "go1")
  1141  	assert("go1" != a)
  1142  	assert(a != b)
  1143  	assert(a == c)
  1144  }
  1145  
  1146  func assert(t bool) {
  1147  	if !t {
  1148  		panic("error")
  1149  	}
  1150  }
  1151  
  1152  func check(a, b T) {
  1153  	if a != b {
  1154  		panic(fmt.Errorf("error %v != %v", a, b))
  1155  	}
  1156  }
  1157  `
  1158  	t.Log("test binop string")
  1159  	_, err := igop.RunFile("main.go", tsrc, nil, 0)
  1160  	if err != nil {
  1161  		t.Fatal(err)
  1162  	}
  1163  	t.Log("test binop named string")
  1164  	src := strings.Replace(tsrc, "= string", "string", 1)
  1165  	_, err = igop.RunFile("main.go", src, nil, 0)
  1166  	if err != nil {
  1167  		t.Fatal(err)
  1168  	}
  1169  }
  1170  
  1171  func TestBinOpShift(t *testing.T) {
  1172  	tsrc := `package main
  1173  type T1 $T1
  1174  type T2 $T2
  1175  
  1176  func main() {
  1177  	test(4, 2)
  1178  }
  1179  func test(a T1, b T2) {
  1180  	assert(a << b == 16)
  1181  	assert(a >> b == 1)
  1182  	assert(a << T2(2) == 16)
  1183  	assert(a >> T2(2) == 1)
  1184  	assert(T1(4) << b == 16)
  1185  	assert(T1(4) >> b == 1)
  1186  	var c T1 = 4
  1187  	var d T2 = 2
  1188  	assert(c << d == 16)
  1189  	assert(c >> d == 1)
  1190  }
  1191  func assert(t bool) {
  1192  	if !t {
  1193  		panic("error")
  1194  	}
  1195  }
  1196  `
  1197  	types := []string{
  1198  		"int", "int8", "int16", "int32", "int64",
  1199  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  1200  	}
  1201  	for _, t1 := range types {
  1202  		t.Log("test binop shift", t1)
  1203  		for _, t2 := range types {
  1204  			r := strings.NewReplacer("$T1", "="+t1, "$T2", "="+t2)
  1205  			src := r.Replace(tsrc)
  1206  			_, err := igop.RunFile("main.go", src, nil, 0)
  1207  			if err != nil {
  1208  				t.Fatal(err)
  1209  			}
  1210  		}
  1211  		for _, t2 := range types {
  1212  			r := strings.NewReplacer("$T1", "="+t1, "$T2", t2)
  1213  			src := r.Replace(tsrc)
  1214  			_, err := igop.RunFile("main.go", src, nil, 0)
  1215  			if err != nil {
  1216  				t.Fatal(err)
  1217  			}
  1218  		}
  1219  		for _, t2 := range types {
  1220  			r := strings.NewReplacer("$T1", t1, "$T2", "="+t2)
  1221  			src := r.Replace(tsrc)
  1222  			_, err := igop.RunFile("main.go", src, nil, 0)
  1223  			if err != nil {
  1224  				t.Fatal(err)
  1225  			}
  1226  		}
  1227  		for _, t2 := range types {
  1228  			r := strings.NewReplacer("$T1", t1, "$T2", t2)
  1229  			src := r.Replace(tsrc)
  1230  			_, err := igop.RunFile("main.go", src, nil, 0)
  1231  			if err != nil {
  1232  				t.Fatal(err)
  1233  			}
  1234  		}
  1235  	}
  1236  }
  1237  
  1238  func TestUnOpNot(t *testing.T) {
  1239  	src := `package main
  1240  type T bool
  1241  func main() {
  1242  	test(false,false)
  1243  	testConst()
  1244  }
  1245  func test(b1 bool, b2 T) {
  1246  	if v := !b1; v != true {
  1247  		panic("must true")
  1248  	}
  1249  	if v := !b2; v != true {
  1250  		panic("must true")
  1251  	}
  1252  }
  1253  func testConst() {
  1254  	var b1 bool
  1255  	var b2 T
  1256  	if v := !b1; v != true {
  1257  		panic("must true")
  1258  	}
  1259  	if v := !b2; v != true {
  1260  		panic("must true")
  1261  	}
  1262  }
  1263  `
  1264  	_, err := igop.RunFile("main.go", src, nil, 0)
  1265  	if err != nil {
  1266  		t.Fatal(err)
  1267  	}
  1268  }
  1269  
  1270  func TestUnOpSubInt(t *testing.T) {
  1271  	tsrc := `package main
  1272  type T $int
  1273  
  1274  func main() {
  1275  	test(10,10)
  1276  	testConst()
  1277  }
  1278  
  1279  func test(a $int, b T) {
  1280  	if r := -a; r != -10 {
  1281  		panic("must -10")
  1282  	}
  1283  	if r := -b; r != -10 {
  1284  		panic("must -10")
  1285  	}
  1286  }
  1287  func testConst() {
  1288  	var a $int = 10
  1289  	var b T = 10
  1290  	if r := -a; r != -10 {
  1291  		panic("must -10")
  1292  	}
  1293  	if r := -b; r != -10 {
  1294  		panic("must -10")
  1295  	}
  1296  }
  1297  `
  1298  	types := []string{
  1299  		"int", "int8", "int16", "int32", "int64",
  1300  	}
  1301  
  1302  	for _, s := range types {
  1303  		t.Log("test unop sub", s)
  1304  		src := strings.Replace(tsrc, "$int", s, -1)
  1305  		_, err := igop.RunFile("main.go", src, nil, 0)
  1306  		if err != nil {
  1307  			t.Fatal(err)
  1308  		}
  1309  	}
  1310  }
  1311  
  1312  func TestUnOpSubUint(t *testing.T) {
  1313  	tsrc := `package main
  1314  
  1315  type T $uint
  1316  
  1317  func main() {
  1318  	test(0b1010, 0b1011)
  1319  	testConst()
  1320  }
  1321  
  1322  func test(a $uint, b T) {
  1323  	if r := -a; r&0xff != 0b11110110 {
  1324  		panic(r)
  1325  	}
  1326  	if r := -b; r&0xff != 0b11110101 {
  1327  		panic(r)
  1328  	}
  1329  }
  1330  func testConst() {
  1331  	var a $uint = 0b1010
  1332  	var b T = 0b1011
  1333  	if r := -a; r&0xff != 0b11110110 {
  1334  		panic(r)
  1335  	}
  1336  	if r := -b; r&0xff != 0b11110101 {
  1337  		panic(r)
  1338  	}
  1339  }
  1340  `
  1341  	types := []string{
  1342  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  1343  	}
  1344  	for _, s := range types {
  1345  		src := strings.Replace(tsrc, "$uint", s, -1)
  1346  		_, err := igop.RunFile("main.go", src, nil, 0)
  1347  		if err != nil {
  1348  			t.Fatal(err)
  1349  		}
  1350  	}
  1351  }
  1352  
  1353  func TestUnOpSubFloat(t *testing.T) {
  1354  	tsrc := `package main
  1355  
  1356  type T $float
  1357  
  1358  func main() {
  1359  	test(5.0, 6.5)
  1360  	testConst()
  1361  }
  1362  
  1363  func test(a $float, b T) {
  1364  	if r := -a; r != -5.0 {
  1365  		panic(r)
  1366  	}
  1367  	if r := -b; r != -6.5 {
  1368  		panic(r)
  1369  	}
  1370  }
  1371  func testConst() {
  1372  	var a $float = 5.0
  1373  	var b T = 6.5
  1374  	if r := -a; r != -5.0 {
  1375  		panic(r)
  1376  	}
  1377  	if r := -b; r != -6.5 {
  1378  		panic(r)
  1379  	}
  1380  }
  1381  `
  1382  	types := []string{
  1383  		"float32", "float64",
  1384  	}
  1385  	for _, s := range types {
  1386  		t.Log("test unop sub", s)
  1387  		src := strings.Replace(tsrc, "$float", s, -1)
  1388  		_, err := igop.RunFile("main.go", src, nil, 0)
  1389  		if err != nil {
  1390  			t.Fatal(err)
  1391  		}
  1392  	}
  1393  }
  1394  
  1395  func TestUnOpSubComplex(t *testing.T) {
  1396  	tsrc := `package main
  1397  
  1398  type T $complex
  1399  
  1400  func main() {
  1401  	test(1+2i, 3+4i)
  1402  	testConst()
  1403  }
  1404  
  1405  func test(a $complex, b T) {
  1406  	if r := -a; r != -1-2i {
  1407  		panic(r)
  1408  	}
  1409  	if r := -b; r != -3-4i {
  1410  		panic(r)
  1411  	}
  1412  }
  1413  func testConst() {
  1414  	var a $complex = 1+2i
  1415  	var b T = 3+4i
  1416  	if r := -a; r != -1-2i {
  1417  		panic(r)
  1418  	}
  1419  	if r := -b; r != -3-4i {
  1420  		panic(r)
  1421  	}
  1422  }
  1423  `
  1424  	types := []string{
  1425  		"complex64", "complex128",
  1426  	}
  1427  	for _, s := range types {
  1428  		t.Log("test unop sub", s)
  1429  		src := strings.Replace(tsrc, "$complex", s, -1)
  1430  		_, err := igop.RunFile("main.go", src, nil, 0)
  1431  		if err != nil {
  1432  			t.Fatal(err)
  1433  		}
  1434  	}
  1435  }
  1436  
  1437  func TestUnOpXorInt(t *testing.T) {
  1438  	tsrc := `package main
  1439  
  1440  type T $int
  1441  
  1442  func main() {
  1443  	test(10, 11)
  1444  	testConst()
  1445  }
  1446  
  1447  func test(a $int, b T) {
  1448  	if r := ^a; r != -11 {
  1449  		panic(r)
  1450  	}
  1451  	if r := ^b; r != -12 {
  1452  		panic(r)
  1453  	}
  1454  }
  1455  func testConst() {
  1456  	var a $int = 10
  1457  	var b T = 11
  1458  	if r := ^a; r != -11 {
  1459  		panic(r)
  1460  	}
  1461  	if r := ^b; r != -12 {
  1462  		panic(r)
  1463  	}
  1464  }
  1465  `
  1466  	types := []string{
  1467  		"int", "int8", "int16", "int32", "int64",
  1468  	}
  1469  
  1470  	for _, s := range types {
  1471  		t.Log("test unop xor", s)
  1472  		src := strings.Replace(tsrc, "$int", s, -1)
  1473  		_, err := igop.RunFile("main.go", src, nil, 0)
  1474  		if err != nil {
  1475  			t.Fatal(err)
  1476  		}
  1477  	}
  1478  }
  1479  
  1480  func TestUnOpXorUint(t *testing.T) {
  1481  	tsrc := `package main
  1482  
  1483  type T $uint
  1484  
  1485  func main() {
  1486  	test(0b1010, 0b1011)
  1487  	testConst()
  1488  }
  1489  
  1490  func test(a $uint, b T) {
  1491  	if r := ^a; r&0xff != 0b11110101 {
  1492  		panic(r)
  1493  	}
  1494  	if r := ^b; r&0xff != 0b11110100 {
  1495  		panic(r)
  1496  	}
  1497  }
  1498  func testConst() {
  1499  	var a $uint = 0b1010
  1500  	var b T = 0b1011
  1501  	if r := ^a; r&0xff != 0b11110101 {
  1502  		panic(r)
  1503  	}
  1504  	if r := ^b; r&0xff != 0b11110100 {
  1505  		panic(r)
  1506  	}
  1507  }
  1508  `
  1509  	types := []string{
  1510  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  1511  	}
  1512  
  1513  	for _, s := range types {
  1514  		t.Log("test unop xor", s)
  1515  		src := strings.Replace(tsrc, "$uint", s, -1)
  1516  		_, err := igop.RunFile("main.go", src, nil, 0)
  1517  		if err != nil {
  1518  			t.Fatal(err)
  1519  		}
  1520  	}
  1521  }
  1522  
  1523  func TestBinOpEQ(t *testing.T) {
  1524  	src := `package main
  1525  
  1526  import "unsafe"
  1527  
  1528  type T struct {
  1529  	a int
  1530  	b int
  1531  	_ int
  1532  	_ int
  1533  }
  1534  
  1535  func main() {
  1536  	// array
  1537  	ar1 := [2]int{10,20}
  1538  	ar2 := [2]int{10,20}
  1539  	if ar1 != ar2 {
  1540  		panic("error array")
  1541  	}
  1542  	ar1[0] = 1
  1543  	if ar1 == ar2 {
  1544  		panic("error array")
  1545  	}
  1546  	// struct & interface{}
  1547  	t1 := T{1,2,3,4}
  1548  	t2 := T{1,2,7,8}
  1549  	if t1 != t2 {
  1550  		panic("error struct")
  1551  	}
  1552  	if (interface{})(t1) != (interface{})(t2) {
  1553  		panic("error interface")
  1554  	}
  1555  	t1.a = 10
  1556  	if t1 == t2 {
  1557  		panic("error struct")
  1558  	}
  1559  	if (interface{})(t1) == (interface{})(t2) {
  1560  		panic("error interface")
  1561  	}
  1562  	// ptr
  1563  	ptr1 := &t1
  1564  	ptr2 := &t2
  1565  	if ptr1 == ptr2 {
  1566  		panic("error ptr")
  1567  	}
  1568  	ptr2 = &t1
  1569  	if ptr1 != ptr2 {
  1570  		panic("error ptr")
  1571  	}
  1572  	// unsafe pointer
  1573  	p1 := unsafe.Pointer(&t1)
  1574  	p2 := unsafe.Pointer(&t2)
  1575  	if p1 == p2 {
  1576  		panic("error unsafe pointer")
  1577  	}
  1578  	p2 = unsafe.Pointer(ptr2)
  1579  	if p1 != p2 {
  1580  		panic("error unsafe pointer")
  1581  	}
  1582  	// chan
  1583  	ch1 := make(chan int)
  1584  	ch2 := make(chan int)
  1585  	if ch1 == ch2 {
  1586  		panic("error chan")
  1587  	}
  1588  	ch3 := ch1
  1589  	if ch1 != ch3 {
  1590  		panic("error chan")
  1591  	}
  1592  	ch4 := (<-chan int)(ch1)
  1593  	ch5 := (chan<- int)(ch1)
  1594  	if ch1 != ch4 {
  1595  		panic("error chan")
  1596  	}
  1597  	if ch5 != ch1 {
  1598  		panic("error chan")
  1599  	}
  1600  	ch6 := (<-chan int)(ch2)
  1601  	ch7 := (chan<- int)(ch2)
  1602  	if ch6 == ch1 {
  1603  		panic("error chan")
  1604  	}
  1605  	if ch1 == ch7 {
  1606  		panic("error chan")
  1607  	}
  1608  }
  1609  `
  1610  	_, err := igop.RunFile("main.go", src, nil, 0)
  1611  	if err != nil {
  1612  		t.Fatal(err)
  1613  	}
  1614  }
  1615  
  1616  func TestOpTypeChangeBasic(t *testing.T) {
  1617  	src := `package main
  1618  
  1619  import (
  1620  	"bytes"
  1621  	"fmt"
  1622  )
  1623  
  1624  func main() {
  1625  	testNil()
  1626  	testConst()
  1627  	testFunc()
  1628  	testPtr()
  1629  	testSlice()
  1630  	testMap()
  1631  	testStruct()
  1632  	testArray()
  1633  	testChan()
  1634  	testInterface()
  1635  }
  1636  
  1637  func testNil() {
  1638  	var p *int
  1639  	type Ptr *int
  1640  	v := Ptr(p)
  1641  	if s := fmt.Sprintf("%T %v", v, v); s != "main.Ptr <nil>" {
  1642  		panic(s)
  1643  	}
  1644  }
  1645  
  1646  func testConst() {
  1647  	var n int = 10
  1648  	type T int
  1649  	v := T(n)
  1650  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T 10" {
  1651  		panic(s)
  1652  	}
  1653  }
  1654  
  1655  func myfunc(int) {}
  1656  
  1657  type Func func(int)
  1658  
  1659  func testFunc() {
  1660  	v := Func(myfunc)
  1661  	if s := fmt.Sprintf("%T %v", v, v == nil); s != "main.Func false" {
  1662  		panic(s)
  1663  	}
  1664  }
  1665  
  1666  func testPtr() {
  1667  	i := 10
  1668  	p := &i
  1669  	type T *int
  1670  	v := T(p)
  1671  	i = 20
  1672  	if s := fmt.Sprintf("%T %v", v, *v); s != "main.T 20" {
  1673  		panic(s)
  1674  	}
  1675  	p2 := (*int)(v)
  1676  	i = 30
  1677  	if s := fmt.Sprintf("%T %v", p2, *p2); s != "*int 30" {
  1678  		panic(s)
  1679  	}
  1680  }
  1681  
  1682  func testSlice() {
  1683  	i := []int{100, 200, 300}
  1684  	type T []int
  1685  	v := T(i)
  1686  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T [100 200 300]" {
  1687  		panic(s)
  1688  	}
  1689  	p := []int(v)
  1690  	v[0] = 1
  1691  	if s := fmt.Sprintf("%T %v", p, p); s != "[]int [1 200 300]" {
  1692  		panic(s)
  1693  	}
  1694  }
  1695  
  1696  func testMap() {
  1697  	i := map[int]string{1: "hello", 2: "world"}
  1698  	type T map[int]string
  1699  	v := T(i)
  1700  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T map[1:hello 2:world]" {
  1701  		panic(s)
  1702  	}
  1703  	type T2 map[int]string
  1704  	v2 := T(v)
  1705  	i[1] = "hello2"
  1706  	if s := fmt.Sprintf("%T %v", v2, v2); s != "main.T map[1:hello2 2:world]" {
  1707  		panic(s)
  1708  	}
  1709  }
  1710  
  1711  func testStruct() {
  1712  	type Pt struct {
  1713  		x int
  1714  		y int
  1715  	}
  1716  	type T Pt
  1717  	i := Pt{10, 20}
  1718  	v := T(i)
  1719  	i.x = 1
  1720  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T {10 20}" {
  1721  		panic(s)
  1722  	}
  1723  }
  1724  
  1725  func testArray() {
  1726  	ar := [3]int{100, 200, 300}
  1727  	type T [3]int
  1728  	v := T(ar)
  1729  	ar[0] = 1
  1730  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T [100 200 300]" {
  1731  		panic(s)
  1732  	}
  1733  }
  1734  
  1735  func testChan() {
  1736  	ch := make(chan int)
  1737  	v := (chan<- int)(ch)
  1738  	if s := fmt.Sprintf("%T", v); s != "chan<- int" {
  1739  		panic(s)
  1740  	}
  1741  	type T1 chan int
  1742  	v1 := T1(ch)
  1743  	if s := fmt.Sprintf("%T", v1); s != "main.T1" {
  1744  		panic(s)
  1745  	}
  1746  	type T2 <-chan int
  1747  	v2 := T2(ch)
  1748  	if s := fmt.Sprintf("%T", v2); s != "main.T2" {
  1749  		panic(s)
  1750  	}
  1751  	type T3 chan<- int
  1752  	v3 := T3(ch)
  1753  	if s := fmt.Sprintf("%T", v3); s != "main.T3" {
  1754  		panic(s)
  1755  	}
  1756  }
  1757  
  1758  func testInterface() {
  1759  	var buf fmt.Stringer = bytes.NewBufferString("hello")
  1760  	type T fmt.Stringer
  1761  	v := T(buf)
  1762  	if s := fmt.Sprintf("%T %v", v, v.String()); s != "*bytes.Buffer hello" {
  1763  		panic(s)
  1764  	}
  1765  }
  1766  `
  1767  	_, err := igop.RunFile("main.go", src, nil, 0)
  1768  	if err != nil {
  1769  		t.Fatal(err)
  1770  	}
  1771  }
  1772  
  1773  func TestOpTypeChange3(t *testing.T) {
  1774  	tsrc := `package main
  1775  import "fmt"
  1776  type T $int
  1777  type T2 $int
  1778  func main() {
  1779  	test($value)
  1780  }
  1781  func test(v $int) {
  1782  	r := T(v)
  1783  	if s := fmt.Sprintf("%T", r); s != "main.T" {
  1784  		panic(s)
  1785  	}
  1786  	r2 := T2(r)
  1787  	if s := fmt.Sprintf("%T", r2); s != "main.T2" {
  1788  		panic(s)
  1789  	}
  1790  	n := $int(r2)
  1791  	if s := fmt.Sprintf("%T", n); s != "$int" {
  1792  		panic(s)
  1793  	}
  1794  	if n != v {
  1795  		panic("error")
  1796  	}
  1797  }
  1798  `
  1799  	ints := []string{
  1800  		"int", "int8", "int16", "int32", "int64",
  1801  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  1802  	}
  1803  	for _, s := range ints {
  1804  		t.Log("test changetype xtype", s)
  1805  		r := strings.NewReplacer("$int", s, "$value", "10")
  1806  		src := r.Replace(tsrc)
  1807  		_, err := igop.RunFile("main.go", src, nil, 0)
  1808  		if err != nil {
  1809  			t.Fatal(err)
  1810  		}
  1811  	}
  1812  	floats := []string{"float32", "float64"}
  1813  	for _, s := range floats {
  1814  		t.Log("test changetype xtype", s)
  1815  		r := strings.NewReplacer("$int", s, "$value", "100.5")
  1816  		src := r.Replace(tsrc)
  1817  		_, err := igop.RunFile("main.go", src, nil, 0)
  1818  		if err != nil {
  1819  			t.Fatal(err)
  1820  		}
  1821  	}
  1822  	comps := []string{"complex64", "complex128"}
  1823  	for _, s := range comps {
  1824  		t.Log("test changetype xtype", s)
  1825  		r := strings.NewReplacer("$int", s, "$value", "1+2i")
  1826  		src := r.Replace(tsrc)
  1827  		_, err := igop.RunFile("main.go", src, nil, 0)
  1828  		if err != nil {
  1829  			t.Fatal(err)
  1830  		}
  1831  	}
  1832  	{
  1833  		t.Log("test changetype xtype", "bool")
  1834  		r := strings.NewReplacer("$int", "bool", "$value", "true")
  1835  		src := r.Replace(tsrc)
  1836  		_, err := igop.RunFile("main.go", src, nil, 0)
  1837  		if err != nil {
  1838  			t.Fatal(err)
  1839  		}
  1840  	}
  1841  	{
  1842  		t.Log("test changetype xtype", "string")
  1843  		r := strings.NewReplacer("$int", "string", "$value", `"hello"`)
  1844  		src := r.Replace(tsrc)
  1845  		_, err := igop.RunFile("main.go", src, nil, 0)
  1846  		if err != nil {
  1847  			t.Fatal(err)
  1848  		}
  1849  	}
  1850  }
  1851  
  1852  func TestOpConvert(t *testing.T) {
  1853  	tsrc := `package main
  1854  
  1855  type T = $int
  1856  
  1857  const (
  1858  	V = $V
  1859  	N = $N
  1860  	F = $F
  1861  )
  1862  
  1863  func main() {
  1864  	test1(V)
  1865  	test2(V)
  1866  }
  1867  
  1868  func test1(n T) {
  1869  	if int(n) != N {
  1870  		panic("error")
  1871  	}
  1872  	if int8(n) != N {
  1873  		panic("error")
  1874  	}
  1875  	if int16(n) != N {
  1876  		panic("error")
  1877  	}
  1878  	if int32(n) != N {
  1879  		panic("error")
  1880  	}
  1881  	if int64(n) != N {
  1882  		panic("error")
  1883  	}
  1884  	if uint(n) != N {
  1885  		panic("error")
  1886  	}
  1887  	if uint8(n) != N {
  1888  		panic("error")
  1889  	}
  1890  	if uint16(n) != N {
  1891  		panic("error")
  1892  	}
  1893  	if uint32(n) != N {
  1894  		panic("error")
  1895  	}
  1896  	if uint64(n) != N {
  1897  		panic("error")
  1898  	}
  1899  	if uintptr(n) != N {
  1900  		panic("error")
  1901  	}
  1902  	if float32(n) != F {
  1903  		panic("error")
  1904  	}
  1905  	if float64(n) != F {
  1906  		panic("error")
  1907  	}
  1908  }
  1909  
  1910  type Int int
  1911  type Int8 int8
  1912  type Int16 int16
  1913  type Int32 int32
  1914  type Int64 int64
  1915  type Uint uint
  1916  type Uint8 uint8
  1917  type Uint16 uint16
  1918  type Uint32 uint32
  1919  type Uint64 uint64
  1920  type Uintptr uintptr
  1921  type Float32 float32
  1922  type Float64 float64
  1923  
  1924  func test2(n T) {
  1925  	if Int(n) != N {
  1926  		panic("error")
  1927  	}
  1928  	if Int8(n) != N {
  1929  		panic("error")
  1930  	}
  1931  	if Int16(n) != N {
  1932  		panic("error")
  1933  	}
  1934  	if Int32(n) != N {
  1935  		panic("error")
  1936  	}
  1937  	if Int64(n) != N {
  1938  		panic("error")
  1939  	}
  1940  	if Uint(n) != N {
  1941  		panic("error")
  1942  	}
  1943  	if Uint8(n) != N {
  1944  		panic("error")
  1945  	}
  1946  	if Uint16(n) != N {
  1947  		panic("error")
  1948  	}
  1949  	if Uint32(n) != N {
  1950  		panic("error")
  1951  	}
  1952  	if Uint64(n) != N {
  1953  		panic("error")
  1954  	}
  1955  	if Uintptr(n) != N {
  1956  		panic("error")
  1957  	}
  1958  	if Float32(n) != F {
  1959  		panic("error")
  1960  	}
  1961  	if Float64(n) != F {
  1962  		panic("error")
  1963  	}
  1964  }
  1965  `
  1966  	csrc := `package main
  1967  
  1968  type T = $complex
  1969  
  1970  const (
  1971  	N = $N
  1972  )
  1973  
  1974  func main() {
  1975  	test1(N)
  1976  	test2(N)
  1977  }
  1978  
  1979  func test1(n T) {
  1980  	if complex64(n) != N {
  1981  		panic("error")
  1982  	}
  1983  	if complex128(n) != N {
  1984  		panic("error")
  1985  	}
  1986  }
  1987  
  1988  type Complex64 complex64
  1989  type Complex128 complex128
  1990  
  1991  
  1992  func test2(n T) {
  1993  	if Complex64(n) != N {
  1994  		panic("error")
  1995  	}
  1996  	if Complex128(n) != N {
  1997  		panic("error")
  1998  	}
  1999  }
  2000  `
  2001  	ints := []string{
  2002  		"int", "int8", "int16", "int32", "int64",
  2003  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  2004  	}
  2005  	floats := []string{"float32", "float64"}
  2006  	comps := []string{"complex64", "complex128"}
  2007  	for _, s := range ints {
  2008  		t.Log("test convert xtype", s)
  2009  		r := strings.NewReplacer("$int", s, "$V", "100", "$N", "100", "$F", "100")
  2010  		src := r.Replace(tsrc)
  2011  		_, err := igop.RunFile("main.go", src, nil, 0)
  2012  		if err != nil {
  2013  			t.Fatal(err)
  2014  		}
  2015  	}
  2016  	for _, s := range ints {
  2017  		t.Log("test convert typed", s)
  2018  		r := strings.NewReplacer("= $int", s, "$V", "100", "$N", "100", "$F", "100")
  2019  		src := r.Replace(tsrc)
  2020  		_, err := igop.RunFile("main.go", src, nil, 0)
  2021  		if err != nil {
  2022  			t.Fatal(err)
  2023  		}
  2024  	}
  2025  	for _, s := range floats {
  2026  		t.Log("test convert xtype", s)
  2027  		r := strings.NewReplacer("$int", s, "$V", "100.5", "$N", "100", "$F", "100.5")
  2028  		src := r.Replace(tsrc)
  2029  		_, err := igop.RunFile("main.go", src, nil, 0)
  2030  		if err != nil {
  2031  			t.Fatal(err)
  2032  		}
  2033  	}
  2034  	for _, s := range floats {
  2035  		t.Log("test convert typed", s)
  2036  		r := strings.NewReplacer("= $int", s, "$V", "100.5", "$N", "100", "$F", "100.5")
  2037  		src := r.Replace(tsrc)
  2038  		_, err := igop.RunFile("main.go", src, nil, 0)
  2039  		if err != nil {
  2040  			t.Fatal(err)
  2041  		}
  2042  	}
  2043  	for _, s := range comps {
  2044  		t.Log("test convert xtype", s)
  2045  		r := strings.NewReplacer("$complex", s, "$N", "1+2i")
  2046  		src := r.Replace(csrc)
  2047  		_, err := igop.RunFile("main.go", src, nil, 0)
  2048  		if err != nil {
  2049  			t.Fatal(err)
  2050  		}
  2051  	}
  2052  	for _, s := range comps {
  2053  		t.Log("test convert typed", s)
  2054  		r := strings.NewReplacer("= $complex", s, "$N", "1+2i")
  2055  		src := r.Replace(csrc)
  2056  		_, err := igop.RunFile("main.go", src, nil, 0)
  2057  		if err != nil {
  2058  			t.Fatal(err)
  2059  		}
  2060  	}
  2061  }
  2062  
  2063  func TestOpIf(t *testing.T) {
  2064  	src := `package main
  2065  
  2066  type Bool bool
  2067  
  2068  func main() {
  2069  	test1(true)
  2070  	test1(false)
  2071  	test2(true)
  2072  	test2(false)
  2073  	testConst1()
  2074  	testConst2()
  2075  }
  2076  
  2077  func test1(b bool) {
  2078  	if b {
  2079  		println(true)
  2080  	} else {
  2081  		println(false)
  2082  	}
  2083  }
  2084  func test2(b Bool) {
  2085  	if b {
  2086  		println(true)
  2087  	} else {
  2088  		println(false)
  2089  	}
  2090  }
  2091  func testConst1() {
  2092  	var b bool
  2093  	if !b {
  2094  		println(false)
  2095  	}
  2096  	b = true
  2097  	if b {
  2098  		println(true)
  2099  	}
  2100  }
  2101  func testConst2() {
  2102  	var b Bool
  2103  	if !b {
  2104  		println(false)
  2105  	}
  2106  	b = true
  2107  	if b {
  2108  		println(true)
  2109  	}
  2110  }
  2111  `
  2112  	out := `true
  2113  false
  2114  true
  2115  false
  2116  false
  2117  true
  2118  false
  2119  true
  2120  `
  2121  	ctx := igop.NewContext(0)
  2122  	var buf bytes.Buffer
  2123  	ctx.SetPrintOutput(&buf)
  2124  	_, err := ctx.RunFile("main.go", src, nil)
  2125  	if err != nil {
  2126  		t.Fatal(err)
  2127  	}
  2128  	if buf.String() != out {
  2129  		t.Fatal("error")
  2130  	}
  2131  }
  2132  
  2133  func TestGoexitDeadlock(t *testing.T) {
  2134  	src := `package main
  2135  import (
  2136  	"os"
  2137  	"runtime"
  2138  )
  2139  
  2140  func init() {
  2141  	runtime.Goexit()
  2142  	os.Exit(-1)
  2143  }
  2144  
  2145  func main() {
  2146  	os.Exit(-2)
  2147  }
  2148  `
  2149  	_, err := igop.RunFile("main.go", src, nil, 0)
  2150  	if err == nil {
  2151  		t.Fatal("must panic")
  2152  	}
  2153  	if err.Error() != igop.ErrGoexitDeadlock.Error() {
  2154  		t.Fatal(err)
  2155  	}
  2156  }
  2157  
  2158  func TestGlobalExtFunc(t *testing.T) {
  2159  	src := `package main
  2160  import "math"
  2161  var (
  2162  	max = math.Max
  2163  )
  2164  func main() {
  2165  	if max(1,3) != 3 {
  2166  		panic("error")
  2167  	}
  2168  }
  2169  `
  2170  	_, err := igop.RunFile("main.go", src, nil, 0)
  2171  	if err != nil {
  2172  		t.Fatal(err)
  2173  	}
  2174  }
  2175  
  2176  func TestRegisterBuiltin(t *testing.T) {
  2177  	src := `package main
  2178  
  2179  func main() {
  2180  	dump_info(typeof("hello"))
  2181  	dump_ints(20,30,50)
  2182  }
  2183  `
  2184  	igop.RegisterCustomBuiltin("typeof", reflect.TypeOf)
  2185  	var info interface{}
  2186  	igop.RegisterCustomBuiltin("dump_info", func(v interface{}) {
  2187  		info = v
  2188  	})
  2189  	var all int
  2190  	igop.RegisterCustomBuiltin("dump_ints", func(a ...int) {
  2191  		for _, v := range a {
  2192  			all += v
  2193  		}
  2194  	})
  2195  	_, err := igop.RunFile("main.go", src, nil, 0)
  2196  	if err != nil {
  2197  		panic(err)
  2198  	}
  2199  	if info != reflect.TypeOf("hello") {
  2200  		panic("error")
  2201  	}
  2202  	if all != 100 {
  2203  		panic(all)
  2204  	}
  2205  }
  2206  
  2207  func TestVariadicFunc(t *testing.T) {
  2208  	src := `package main
  2209  type Context struct{}
  2210  type ClientConn struct{}
  2211  type CallOption struct{}
  2212  
  2213  type UnaryInvoker func(ctx Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error
  2214  
  2215  func main() {
  2216  }
  2217  `
  2218  	_, err := igop.RunFile("main.go", src, nil, 0)
  2219  	if err != nil {
  2220  		t.Fatal(err)
  2221  	}
  2222  }
  2223  
  2224  func TestUnsafePointer(t *testing.T) {
  2225  	src := `package main
  2226  
  2227  import (
  2228  	"unsafe"
  2229  )
  2230  
  2231  func main() {
  2232  	type T1 unsafe.Pointer
  2233  	type T2 unsafe.Pointer
  2234  	i := 10
  2235  	p := unsafe.Pointer(&i)
  2236  	p1 := T1(uintptr(unsafe.Pointer(&i)))
  2237  	p2 := T2(&i)
  2238  	if T1(p) != p1 {
  2239  		panic("error T1")
  2240  	}
  2241  	if T2(p1) != (p2) {
  2242  		panic("error T2")
  2243  	}
  2244  	if unsafe.Pointer(p1) != unsafe.Pointer(p2) {
  2245  		panic("error unsafe")
  2246  	}
  2247  }
  2248  `
  2249  	_, err := igop.RunFile("main.go", src, nil, 0)
  2250  	if err != nil {
  2251  		t.Fatal(err)
  2252  	}
  2253  }
  2254  
  2255  func TestAddImport(t *testing.T) {
  2256  	pkg := `package pkg
  2257  import "fmt"
  2258  
  2259  func Add(i, j int) int {
  2260  	return i+j
  2261  }
  2262  
  2263  func Println(a ...interface{}) {
  2264  	fmt.Println(a...)
  2265  }
  2266  `
  2267  	src := `package main
  2268  import "pkg"
  2269  
  2270  func main() {
  2271  	if pkg.Add(100, 200) != 300 {
  2272  		panic("error pkg.Add")
  2273  	}
  2274  	pkg.Println("Hello")
  2275  }
  2276  `
  2277  	ctx := igop.NewContext(0)
  2278  	err := ctx.AddImportFile("pkg", "pkg.go", pkg)
  2279  	if err != nil {
  2280  		t.Fatal(err)
  2281  	}
  2282  	_, err = ctx.RunFile("main.go", src, nil)
  2283  	if err != nil {
  2284  		t.Fatal(err)
  2285  	}
  2286  }
  2287  
  2288  func TestAddImportDir(t *testing.T) {
  2289  	src := `package main
  2290  import "igop/pkg"
  2291  
  2292  func main() {
  2293  	if pkg.Add(100, 200) != 300 {
  2294  		panic("error pkg.Add")
  2295  	}
  2296  	pkg.Println("Hello")
  2297  }
  2298  `
  2299  	ctx := igop.NewContext(0)
  2300  	err := ctx.AddImport("igop/pkg", "./testdata/pkg")
  2301  	if err != nil {
  2302  		t.Fatal(err)
  2303  	}
  2304  	_, err = ctx.RunFile("main.go", src, nil)
  2305  	if err != nil {
  2306  		t.Fatal(err)
  2307  	}
  2308  }
  2309  
  2310  func TestLoadImport(t *testing.T) {
  2311  	if runtime.GOOS == "darwin" {
  2312  		switch runtime.Version()[:6] {
  2313  		case "go1.14", "go1.15":
  2314  			t.Skip("skip for workflows")
  2315  		}
  2316  	}
  2317  	src := `package main
  2318  import "github.com/goplus/igop/testdata/pkg"
  2319  
  2320  func main() {
  2321  	if pkg.Add(100, 200) != 300 {
  2322  		panic("error pkg.Add")
  2323  	}
  2324  	pkg.Println("Hello")
  2325  }
  2326  `
  2327  	ctx := igop.NewContext(0)
  2328  	_, err := ctx.RunFile("main.go", src, nil)
  2329  	if err != nil {
  2330  		t.Fatal(err)
  2331  	}
  2332  }
  2333  
  2334  func TestAppend(t *testing.T) {
  2335  	src := `package main
  2336  
  2337  type T string
  2338  
  2339  func main() {
  2340  	a := []uint8("hello")
  2341  	b := "world"
  2342  	c := T("world")
  2343  	_ = append(a,b...)
  2344  	_ = append(a,c...)
  2345  }
  2346  	`
  2347  	ctx := igop.NewContext(0)
  2348  	_, err := ctx.RunFile("main.go", src, nil)
  2349  	if err != nil {
  2350  		t.Fatal(err)
  2351  	}
  2352  }
  2353  
  2354  func TestStructEmbed(t *testing.T) {
  2355  	p := &igop.Package{
  2356  		Name: "info",
  2357  		Path: "github.com/goplus/igop/testdata/info",
  2358  		Interfaces: map[string]reflect.Type{
  2359  			"Info": reflect.TypeOf((*info.Info)(nil)).Elem(),
  2360  		},
  2361  		NamedTypes: map[string]reflect.Type{
  2362  			"MyInfo": reflect.TypeOf((*info.MyInfo)(nil)).Elem(),
  2363  		},
  2364  		Funcs: map[string]reflect.Value{
  2365  			"NewInfo": reflect.ValueOf(info.NewInfo),
  2366  		},
  2367  	}
  2368  	igop.RegisterPackage(p)
  2369  
  2370  	src := `package main
  2371  
  2372  import (
  2373  	"github.com/goplus/igop/testdata/info"
  2374  )
  2375  
  2376  type MyInfo struct {
  2377  	*info.MyInfo
  2378  }
  2379  
  2380  type MyInfo2 struct {
  2381  	info.Info
  2382  }
  2383  
  2384  func main() {
  2385  	info := info.NewInfo(1)
  2386  	m := &MyInfo{info}
  2387  	check(m)
  2388  	m2 := &MyInfo2{info}
  2389  	check(m2)
  2390  }
  2391  
  2392  func check(info info.Info) {
  2393  	info.SetMode(-1)
  2394  	if info.Mode() != -1 {
  2395  		panic("mode")
  2396  	}
  2397  	if info.Count(1, 2, 3) != 3 {
  2398  		panic("count")
  2399  	}
  2400  }
  2401  `
  2402  	_, err := igop.RunFile("main.go", src, nil, 0)
  2403  	if err != nil {
  2404  		t.Fatal(err)
  2405  	}
  2406  }
  2407  
  2408  func TestBuildTags(t *testing.T) {
  2409  	if runtime.GOOS == "darwin" {
  2410  		switch runtime.Version()[:6] {
  2411  		case "go1.14", "go1.15":
  2412  			t.Skip("skip for workflows")
  2413  		}
  2414  	}
  2415  	src1 := `package main
  2416  
  2417  import (
  2418  	"github.com/goplus/igop/testdata/msg"
  2419  )
  2420  
  2421  func main() {
  2422  	if msg.Info != "nomsg" {
  2423  		panic(msg.Info)
  2424  	}
  2425  }
  2426  `
  2427  	ctx1 := igop.NewContext(0)
  2428  	_, err := ctx1.RunFile("main.go", src1, nil)
  2429  	if err != nil {
  2430  		t.Fatal(err)
  2431  	}
  2432  
  2433  	src2 := `package main
  2434  
  2435  import (
  2436  	"github.com/goplus/igop/testdata/msg"
  2437  )
  2438  
  2439  func main() {
  2440  	if msg.Info != "msg" {
  2441  		panic(msg.Info)
  2442  	}
  2443  }
  2444  `
  2445  	ctx2 := igop.NewContext(0)
  2446  	ctx2.BuildContext.BuildTags = []string{"msg"}
  2447  	_, err = ctx2.RunFile("main.go", src2, nil)
  2448  	if err != nil {
  2449  		t.Fatal(err)
  2450  	}
  2451  }
  2452  
  2453  func TestEqualChan(t *testing.T) {
  2454  	src := `package main
  2455  
  2456  func main() {
  2457  	ch := make(chan bool)
  2458  	ch1 := (<-chan bool)(ch)
  2459  	ch2 := (chan<- bool)(ch)
  2460  	var i interface{} = ch
  2461  	var i1 interface{} = ch1
  2462  	var i2 interface{} = ch2
  2463  
  2464  	check(ch == ch1, true)
  2465  	check(ch == ch2, true)
  2466  	check(i == i1, false)
  2467  	check(i == i2, false)
  2468  	check(i1 == i2, false)
  2469  
  2470  	check(ch != ch1, false)
  2471  	check(ch != ch2, false)
  2472  	check(i != i1, true)
  2473  	check(i != i2, true)
  2474  	check(i1 != i2, true)
  2475  }
  2476  
  2477  func check(b1 bool, b2 bool) {
  2478  	if b1 != b2 {
  2479  		panic("error")
  2480  	}
  2481  }
  2482  `
  2483  	ctx := igop.NewContext(0)
  2484  	_, err := ctx.RunFile("main.go", src, nil)
  2485  	if err != nil {
  2486  		t.Fatal(err)
  2487  	}
  2488  }
  2489  
  2490  func TestIssue23545(t *testing.T) {
  2491  	src := `package main
  2492  
  2493  func main() {
  2494  	if a := Get(); a != dummyID(1234) {
  2495  		panic("FAIL")
  2496  	}
  2497  	var i1 interface{} = Get()
  2498  	var i2 interface{} = dummyID(1234)
  2499  	if i1 == i2 {
  2500  		panic("FAIL")
  2501  	}
  2502  }
  2503  
  2504  func dummyID(x int) [Size]interface{} {
  2505  	var out [Size]interface{}
  2506  	out[0] = x
  2507  	return out
  2508  }
  2509  
  2510  const Size = 32
  2511  
  2512  type OutputID [Size]interface{}
  2513  
  2514  //go:noinline
  2515  func Get() OutputID {
  2516  	return dummyID(1234)
  2517  }
  2518  `
  2519  	ctx := igop.NewContext(0)
  2520  	_, err := ctx.RunFile("main.go", src, nil)
  2521  	if err != nil {
  2522  		t.Fatal(err)
  2523  	}
  2524  }
  2525  
  2526  func TestMakeChan(t *testing.T) {
  2527  	src := `package main
  2528  
  2529  type Send chan<- int
  2530  type Recv <-chan int
  2531  
  2532  func main() {
  2533  	_ = make(chan int)
  2534  	_ = make(<-chan int)
  2535  	_ = make(chan<- int)
  2536  	_ = make(Send)
  2537  	_ = make(Recv)
  2538  }
  2539  `
  2540  	_, err := igop.RunFile("main.go", src, nil, 0)
  2541  	if err != nil {
  2542  		t.Fatal(err)
  2543  	}
  2544  }
  2545  
  2546  func TestNoStrictMode(t *testing.T) {
  2547  	src := `package main
  2548  import "fmt"
  2549  
  2550  func f() int
  2551  
  2552  func main() {
  2553  	var a int
  2554  	println(100)
  2555  }
  2556  `
  2557  	ctx := igop.NewContext(igop.EnableNoStrict)
  2558  	_, err := ctx.RunFile("main.go", src, nil)
  2559  	if err != nil {
  2560  		t.Fatal(err)
  2561  	}
  2562  }
  2563  
  2564  func TestUserFuncConvert(t *testing.T) {
  2565  	src := `package main
  2566  
  2567  import "fmt"
  2568  
  2569  type myint int
  2570  type point struct {
  2571  	x int
  2572  	y int
  2573  }
  2574  
  2575  func mytest1(n myint, pt point) myint
  2576  func mytest2(n myint, pt *point) myint
  2577  
  2578  func main() {
  2579  	n := mytest1(100, point{100,200})
  2580  	if n != 400 {
  2581  		panic(fmt.Errorf("error mytest1, must 400, have %v",n))
  2582  	}
  2583  	n = mytest2(100, &point{100,200})
  2584  	if n != 30000 {
  2585  		panic(fmt.Errorf("error mytest2, must 30000, have %v",n))
  2586  	}
  2587  }
  2588  `
  2589  	ctx := igop.NewContext(0)
  2590  	igop.RegisterExternal("main.mytest1", func(n int, pt struct {
  2591  		x int
  2592  		y int
  2593  	}) int {
  2594  		return n + pt.x + pt.y
  2595  	})
  2596  	ctx.RegisterExternal("main.mytest2", func(n int, pt *struct {
  2597  		x int
  2598  		y int
  2599  	}) int {
  2600  		return n * (pt.x + pt.y)
  2601  	})
  2602  	_, err := ctx.RunFile("main.go", src, nil)
  2603  	if err != nil {
  2604  		t.Fatal(err)
  2605  	}
  2606  }
  2607  
  2608  func TestRunContext(t *testing.T) {
  2609  	var src string = `
  2610  package main
  2611  
  2612  import "time"
  2613  
  2614  func main() {
  2615  	println("hello world")
  2616  	ch := make(chan int)
  2617  	go func() {
  2618  		for i := 0; i < 10; i++ {
  2619  			timeout := time.After(time.Second * 1)
  2620  			select {
  2621  			case <-timeout:
  2622  				println("work")
  2623  			}
  2624  		}
  2625  		ch <- 1
  2626  	}()
  2627  	<-ch
  2628  	println("exit")
  2629  }
  2630  `
  2631  	ctx := igop.NewContext(0)
  2632  	ctx.RunContext, _ = context.WithTimeout(context.Background(), 1e9)
  2633  	code, err := ctx.RunFile("main.go", src, nil)
  2634  	if code != 2 {
  2635  		t.Fatalf("exit code must 2")
  2636  	}
  2637  	t.Log("cancel context:", err)
  2638  }
  2639  
  2640  func TestReflectArray(t *testing.T) {
  2641  	var src = `package main
  2642  
  2643  import (
  2644  	"reflect"
  2645  	"fmt"
  2646  )
  2647  
  2648  type IntArray [2]int
  2649  
  2650  func (i IntArray) String() string {
  2651  	return fmt.Sprintf("(%v,%v)", i[0], i[1])
  2652  }
  2653  
  2654  func (i *IntArray) Set(x, y int) {
  2655  	*(*int)(&i[0]), *(*int)(&i[1]) = x, y
  2656  }
  2657  
  2658  func (i IntArray) Get() (int, int) {
  2659  	return i[0], i[1]
  2660  }
  2661  
  2662  func (i IntArray) Scale(v int) IntArray {
  2663  	return IntArray{i[0] * v, i[1] * v}
  2664  }
  2665  
  2666  func main() {
  2667  	var a IntArray
  2668  	a.Set(100,200)
  2669  	b := a.Scale(5)
  2670  	if b[0] != 500 || b[1] != 1000 {
  2671  		panic("error")
  2672  	}
  2673  	typ := reflect.TypeOf((*IntArray)(nil)).Elem()
  2674  	v := reflect.New(typ).Elem()
  2675  	v.Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100),reflect.ValueOf(200)})
  2676  	x := v.MethodByName("Scale").Call([]reflect.Value{reflect.ValueOf(5)})
  2677  	if x[0].Index(0).Int() != 500 || x[0].Index(1).Int() != 1000 {
  2678  		panic("error reflect")
  2679  	}
  2680  }
  2681  `
  2682  	ctx := igop.NewContext(0)
  2683  	_, err := ctx.RunFile("main.go", src, nil)
  2684  	if err != nil {
  2685  		t.Fatal(err)
  2686  	}
  2687  }