github.com/goplus/gossa@v0.3.25/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 gossa_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  	"fmt"
    21  	"log"
    22  	"os"
    23  	"path/filepath"
    24  	"reflect"
    25  	"strings"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/goplus/gossa"
    30  	_ "github.com/goplus/gossa/pkg/bytes"
    31  	_ "github.com/goplus/gossa/pkg/errors"
    32  	_ "github.com/goplus/gossa/pkg/fmt"
    33  	_ "github.com/goplus/gossa/pkg/math"
    34  	_ "github.com/goplus/gossa/pkg/os"
    35  	_ "github.com/goplus/gossa/pkg/reflect"
    36  	_ "github.com/goplus/gossa/pkg/runtime"
    37  	_ "github.com/goplus/gossa/pkg/strings"
    38  	_ "github.com/goplus/gossa/pkg/sync"
    39  	_ "github.com/goplus/gossa/pkg/time"
    40  )
    41  
    42  // These are files in github.com/goplus/gossa/testdata/.
    43  var testdataTests = []string{
    44  	"boundmeth.go",
    45  	"complit.go",
    46  	"coverage.go",
    47  	"defer.go",
    48  	"fieldprom.go",
    49  	"ifaceconv.go",
    50  	"ifaceprom.go",
    51  	"initorder.go",
    52  	"methprom.go",
    53  	"mrvchain.go",
    54  	"range.go",
    55  	"recover.go",
    56  	"reflect.go",
    57  	"static.go",
    58  	"recover2.go",
    59  	"static.go",
    60  	"issue23536.go",
    61  	"tinyfin.go",
    62  	"issue5963.go",
    63  }
    64  
    65  func runInput(t *testing.T, input string) bool {
    66  	fmt.Println("Input:", input)
    67  	start := time.Now()
    68  	_, err := gossa.Run(input, nil, 0)
    69  	sec := time.Since(start).Seconds()
    70  	if err != nil {
    71  		t.Error(err)
    72  		fmt.Printf("FAIL %0.3fs\n", sec)
    73  		return false
    74  	}
    75  	fmt.Printf("PASS %0.3fs\n", sec)
    76  	return true
    77  }
    78  
    79  // TestTestdataFiles runs the interpreter on testdata/*.go.
    80  func TestTestdataFiles(t *testing.T) {
    81  	cwd, err := os.Getwd()
    82  	if err != nil {
    83  		log.Fatal(err)
    84  	}
    85  
    86  	var failures []string
    87  	for _, input := range testdataTests {
    88  		if !runInput(t, filepath.Join(cwd, "testdata", input)) {
    89  			failures = append(failures, input)
    90  		}
    91  	}
    92  	printFailures(failures)
    93  }
    94  
    95  func printFailures(failures []string) {
    96  	if failures != nil {
    97  		fmt.Println("The following tests failed:")
    98  		for _, f := range failures {
    99  			fmt.Printf("\t%s\n", f)
   100  		}
   101  	}
   102  }
   103  
   104  func TestUntypedNil(t *testing.T) {
   105  	src := `package main
   106  
   107  type T func()
   108  
   109  func main() {
   110  	if T(nil) != nil {
   111  		panic("error")
   112  	}
   113  	if !(T(nil) == nil) {
   114  		panic("error")
   115  	}
   116  }
   117  `
   118  	_, err := gossa.RunFile("main.go", src, nil, 0)
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  }
   123  
   124  func TestOverrideFunction(t *testing.T) {
   125  	ctx := gossa.NewContext(0)
   126  	ctx.SetOverrideFunction("main.call", func(i, j int) int {
   127  		return i * j
   128  	})
   129  	src := `package main
   130  
   131  func call(i, j int) int {
   132  	return i+j
   133  }
   134  
   135  func main() {
   136  	if n := call(10,20); n != 200 {
   137  		panic(n)
   138  	}
   139  }
   140  `
   141  	_, err := ctx.RunFile("main.go", src, nil)
   142  	if err != nil {
   143  		t.Fatal(err)
   144  	}
   145  
   146  	// reset override func
   147  	ctx.ClearOverrideFunction("main.call")
   148  	_, err = ctx.RunFile("main.go", src, nil)
   149  	if err == nil || err.Error() != "30" {
   150  		t.Fatal("must panic 30")
   151  	}
   152  }
   153  
   154  func TestOsExit(t *testing.T) {
   155  	src := `package main
   156  
   157  import "os"
   158  
   159  func main() {
   160  	os.Exit(-2)
   161  }
   162  `
   163  	code, err := gossa.RunFile("main.go", src, nil, 0)
   164  	if err != nil {
   165  		t.Fatal(err)
   166  	}
   167  	if code != -2 {
   168  		t.Fatalf("exit code %v, must -2", code)
   169  	}
   170  }
   171  
   172  func TestOpAlloc(t *testing.T) {
   173  	src := `package main
   174  
   175  type T struct {
   176  	n1 int
   177  	n2 int
   178  }
   179  
   180  func (t T) call() int {
   181  	return t.n1 * t.n2
   182  }
   183  
   184  func main() {
   185  	var n int
   186  	for i := 0; i < 3; i++ {
   187  		n += T{i,3}.call()
   188  	}
   189  	if n != 9 {
   190  		panic(n)
   191  	}
   192  }
   193  `
   194  	_, err := gossa.RunFile("main.go", src, nil, 0)
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  }
   199  
   200  func TestOpBin(t *testing.T) {
   201  	src := `package main
   202  
   203  func main() {
   204  	a := 10 // 1010
   205  	b := 12 // 1100
   206  	n1 := a + b
   207  	n2 := a - b
   208  	n3 := a * b
   209  	n4 := a / b
   210  	n5 := a % b
   211  	n6 := a & b
   212  	n7 := a | b
   213  	n8 := a ^ b
   214  	n9 := a &^ b
   215  	n10 := a << 3
   216  	n11 := a >> 3
   217  	v1 := a > b
   218  	v2 := a < b
   219  	v3 := a >= b
   220  	v4 := a <= b
   221  	v5 := a == b
   222  	v6 := a != b
   223  	if n1 != 22 || n2 != -2 || n3 != 120 || n4 != 0 || n5 != 10 || n6 != 8 ||
   224  		n7 != 14 || n8 != 6 || n9 != 2 || n10 != 80 || n11 != 1 ||
   225  		v1 != false || v2 != true || v3 != false || v4 != true || v5 != false || v6 != true {
   226  		println(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11)
   227  		println(v1, v2, v3, v4, v5, v6)
   228  		panic("error")
   229  	}
   230  }
   231  `
   232  	_, err := gossa.RunFile("main.go", src, nil, 0)
   233  	if err != nil {
   234  		t.Fatal(err)
   235  	}
   236  }
   237  
   238  func TestOpChangeType(t *testing.T) {
   239  	src := `package main
   240  
   241  type T func(int, int) int
   242  
   243  func add(i, j int) int {
   244  	return i + j
   245  }
   246  
   247  type I interface{}
   248  
   249  func main() {
   250  	// static change type
   251  	fn := T(add)
   252  	if n := fn(10, 20); n != 30 {
   253  		panic(n)
   254  	}
   255  	var i interface{} = I(nil)
   256  	if i != nil {
   257  		panic("must nil")
   258  	}
   259  	// dynamic change type
   260  	var k interface{}
   261  	i = I(k)
   262  	if i != nil {
   263  		panic("must nil")
   264  	}
   265  	i = I(100)
   266  	if i == nil {
   267  		panic("must not nil")
   268  	}
   269  }
   270  `
   271  	_, err := gossa.RunFile("main.go", src, nil, 0)
   272  	if err != nil {
   273  		t.Fatal(err)
   274  	}
   275  }
   276  
   277  func TestOpIndex(t *testing.T) {
   278  	src := `package main
   279  
   280  func main() {
   281  	var n int
   282  	for _, v := range [3]int{1, 2, 4} {
   283  		n += v
   284  	}
   285  	if n != 7 {
   286  		panic(n)
   287  	}
   288  }
   289  `
   290  	_, err := gossa.RunFile("main.go", src, nil, 0)
   291  	if err != nil {
   292  		t.Fatal(err)
   293  	}
   294  }
   295  
   296  func TestUnderscopeMap(t *testing.T) {
   297  	src := `package main
   298  
   299  type key struct {
   300  	_ int
   301  	x int
   302  }
   303  
   304  var (
   305  	s1 = "s1"
   306  	s2 = "s2"
   307  	s3 = "s3"
   308  	s4 = "s4"
   309  )
   310  
   311  func main() {
   312  	m := make(map[key]string)
   313  	m[key{0, 1}] = s1
   314  	m[key{0, 2}] = s2
   315  	m[key{0, 3}] = s3
   316  	m[key{1, 1}] = s4
   317  	m[key{1, 2}] = "s22"
   318  	if n := len(m); n != 3 {
   319  		panic(n)
   320  	}
   321  	if v := m[key{2, 2}]; v != "s22" {
   322  		panic(v)
   323  	}
   324  	if v, ok := m[key{1,4}]; ok {
   325  		panic(v)
   326  	}
   327  }
   328  `
   329  	_, err := gossa.RunFile("main.go", src, nil, 0)
   330  	if err != nil {
   331  		t.Fatal(err)
   332  	}
   333  }
   334  
   335  func TestOpSend(t *testing.T) {
   336  	src := `package main
   337  
   338  import (
   339  	"fmt"
   340  )
   341  
   342  type T struct{}
   343  
   344  func main() {
   345  	ch := make(chan *T)
   346  	go func() {
   347  		ch <- nil
   348  	}()
   349  	v := <-ch
   350  	if v != nil {
   351  		panic("must nil")
   352  	}
   353  	if s := fmt.Sprintf("%T", v); s != "*main.T" {
   354  		panic(s)
   355  	}
   356  	go func() {
   357  		ch <- &T{}
   358  	}()
   359  	v = <-ch
   360  	if v == nil {
   361  		panic("must not nil")
   362  	}
   363  }
   364  `
   365  	_, err := gossa.RunFile("main.go", src, nil, 0)
   366  	if err != nil {
   367  		t.Fatal(err)
   368  	}
   369  }
   370  
   371  func TestShadowedMethod(t *testing.T) {
   372  	src := `// run
   373  
   374  // Copyright 2018 The Go Authors. All rights reserved.
   375  // Use of this source code is governed by a BSD-style
   376  // license that can be found in the LICENSE file.
   377  
   378  // When computing method sets with shadowed methods, make sure we
   379  // compute whether a method promotion involved a pointer traversal
   380  // based on the promoted method, not the shadowed method.
   381  
   382  package main
   383  
   384  import (
   385  	"bytes"
   386  	"fmt"
   387  )
   388  
   389  type mystruct struct {
   390  	f int
   391  }
   392  
   393  func (t mystruct) String() string {
   394  	return "FAIL"
   395  }
   396  
   397  func main() {
   398  	type deep struct {
   399  		mystruct
   400  	}
   401  	s := struct {
   402  		deep
   403  		*bytes.Buffer
   404  	}{
   405  		deep{},
   406  		bytes.NewBufferString("ok"),
   407  	}
   408  
   409  	if got := s.String(); got != "ok" {
   410  		panic(got)
   411  	}
   412  
   413  	var i fmt.Stringer = s
   414  	if got := i.String(); got != "ok" {
   415  		panic(got)
   416  	}
   417  }
   418  `
   419  	_, err := gossa.RunFile("main.go", src, nil, 0)
   420  	if err != nil {
   421  		t.Fatal(err)
   422  	}
   423  }
   424  
   425  func TestConvertUnsafePointer(t *testing.T) {
   426  	src := `package main
   427  
   428  import (
   429  	"unsafe"
   430  )
   431  
   432  func main() {
   433  	a := [4]int{0, 1, 2, 3}
   434  	p := unsafe.Pointer(&a)
   435  	p2 := unsafe.Pointer(uintptr(p) + 2*unsafe.Sizeof(a[0]))
   436  	*(*int)(p2) = 4
   437  	if a != [4]int{0, 1, 4, 3} {
   438  		panic("error")
   439  	}
   440  }
   441  `
   442  	_, err := gossa.RunFile("main.go", src, nil, 0)
   443  	if err != nil {
   444  		t.Fatal(err)
   445  	}
   446  }
   447  
   448  func TestBuiltinPrintln(t *testing.T) {
   449  	src := `// run
   450  
   451  // Copyright 2014 The Go Authors. All rights reserved.
   452  // Use of this source code is governed by a BSD-style
   453  // license that can be found in the LICENSE file.
   454  
   455  // Test internal print routines that are generated
   456  // by the print builtin.  This test is not exhaustive,
   457  // we're just checking that the formatting is correct.
   458  
   459  package main
   460  
   461  func main() {
   462  	println((interface{})(nil)) // printeface
   463  	println((interface {        // printiface
   464  		f()
   465  	})(nil))
   466  	println((map[int]int)(nil)) // printpointer
   467  	println(([]int)(nil))       // printslice
   468  	println(int64(-7))          // printint
   469  	println(uint64(7))          // printuint
   470  	println(uint32(7))          // printuint
   471  	println(uint16(7))          // printuint
   472  	println(uint8(7))           // printuint
   473  	println(uint(7))            // printuint
   474  	println(uintptr(7))         // printuint
   475  	println(8.0)                // printfloat
   476  	println(complex(9.0, 10.0)) // printcomplex
   477  	println(true)               // printbool
   478  	println(false)              // printbool
   479  	println("hello")            // printstring
   480  	println("one", "two")       // printsp
   481  
   482  	// test goprintf
   483  	defer println((interface{})(nil))
   484  	defer println((interface {
   485  		f()
   486  	})(nil))
   487  	defer println((map[int]int)(nil))
   488  	defer println(([]int)(nil))
   489  	defer println(int64(-11))
   490  	defer println(uint64(12))
   491  	defer println(uint32(12))
   492  	defer println(uint16(12))
   493  	defer println(uint8(12))
   494  	defer println(uint(12))
   495  	defer println(uintptr(12))
   496  	defer println(13.0)
   497  	defer println(complex(14.0, 15.0))
   498  	defer println(true)
   499  	defer println(false)
   500  	defer println("hello")
   501  	defer println("one", "two")
   502  }
   503  `
   504  	out := `(0x0,0x0)
   505  (0x0,0x0)
   506  0x0
   507  [0/0]0x0
   508  -7
   509  7
   510  7
   511  7
   512  7
   513  7
   514  7
   515  +8.000000e+000
   516  (+9.000000e+000+1.000000e+001i)
   517  true
   518  false
   519  hello
   520  one two
   521  one two
   522  hello
   523  false
   524  true
   525  (+1.400000e+001+1.500000e+001i)
   526  +1.300000e+001
   527  12
   528  12
   529  12
   530  12
   531  12
   532  12
   533  -11
   534  [0/0]0x0
   535  0x0
   536  (0x0,0x0)
   537  (0x0,0x0)
   538  `
   539  	ctx := gossa.NewContext(0)
   540  	var buf bytes.Buffer
   541  	ctx.SetPrintOutput(&buf)
   542  	_, err := ctx.RunFile("main.go", src, nil)
   543  	if err != nil {
   544  		t.Fatal(err)
   545  	}
   546  	if buf.String() != out {
   547  		t.Fatal("error")
   548  	}
   549  }
   550  
   551  type panicinfo struct {
   552  	src string
   553  	err string
   554  }
   555  
   556  func TestPanicInfo(t *testing.T) {
   557  	infos := []panicinfo{
   558  		{`panic(100)`, `100`},
   559  		{`panic(100.0)`, `+1.000000e+002`},
   560  		{`panic("hello")`, `hello`},
   561  		{`panic((*interface{})(nil))`, `(*interface {}) 0x0`},
   562  		{`type T int; panic(T(100))`, `main.T(100)`},
   563  		{`type T float64; panic(T(100.0))`, `main.T(+1.000000e+002)`},
   564  		{`type T string; panic(T("hello"))`, `main.T("hello")`},
   565  		{`type T struct{}; panic((*T)(nil))`, `(*main.T) 0x0`},
   566  	}
   567  	ctx := gossa.NewContext(0)
   568  	for _, info := range infos {
   569  		src := fmt.Sprintf("package main;func main(){%v}", info.src)
   570  		code, err := ctx.RunFile("main.go", src, nil)
   571  		if code != 2 || err == nil {
   572  			t.Fatalf("%v must panic", info.src)
   573  		}
   574  		if s := err.Error(); s != info.err {
   575  			t.Fatalf("%v err is %v, want %v", info.src, s, info.err)
   576  		}
   577  	}
   578  }
   579  
   580  func TestPanicError(t *testing.T) {
   581  	src := `package main
   582  import "errors"
   583  func main() {
   584  	panic(errors.New("error info"))
   585  }
   586  `
   587  	_, err := gossa.RunFile("main.go", src, nil, 0)
   588  	if err == nil {
   589  		t.Fatal("must panic")
   590  	}
   591  	if s := err.Error(); s != "error info" {
   592  		t.Fatalf("error %q", s)
   593  	}
   594  }
   595  
   596  func TestPanicErrorRecover(t *testing.T) {
   597  	src := `package main
   598  import "errors"
   599  func main() {
   600  	defer func() {
   601  		err := recover()
   602  		if err == nil {
   603  			panic("must error")
   604  		}
   605  		if s := err.(error).Error(); s != "error info" {
   606  			panic(s)
   607  		}
   608  	}()
   609  	panic(errors.New("error info"))
   610  }
   611  `
   612  	_, err := gossa.RunFile("main.go", src, nil, 0)
   613  	if err != nil {
   614  		t.Fatal(err)
   615  	}
   616  }
   617  
   618  func TestEnablePrintAny(t *testing.T) {
   619  	src := `package main
   620  
   621  type T struct {
   622  	X int
   623  	Y int
   624  }
   625  func main() {
   626  	println([2]int{100,200})
   627  	println(T{100,200})
   628  }
   629  `
   630  	ctx := gossa.NewContext(0)
   631  	var buf bytes.Buffer
   632  	ctx.SetPrintOutput(&buf)
   633  	_, err := ctx.RunFile("main.go", src, nil)
   634  	if err == nil {
   635  		t.Fatal("must panic")
   636  	}
   637  	if s := err.Error(); s != "illegal types for operand: print\n\t[2]int" {
   638  		t.Fatal(s)
   639  	}
   640  	ctx.Mode |= gossa.EnablePrintAny
   641  	_, err = ctx.RunFile("main.go", src, nil)
   642  	if err != nil {
   643  		t.Fatal(err)
   644  	}
   645  	if s := buf.String(); s != "[100 200]\n{100 200}\n" {
   646  		t.Fatal(s)
   647  	}
   648  }
   649  
   650  func TestFib(t *testing.T) {
   651  	src := `package main
   652  
   653  import (
   654  	"sync"
   655  )
   656  
   657  func fib(n int) int {
   658  	if n < 2 {
   659  		return n
   660  	}
   661  	return fib(n-2) + fib(n-1)
   662  }
   663  
   664  func main() {
   665  	var wg sync.WaitGroup
   666  	const N = 10
   667  	for i := 0; i < N; i++ {
   668  		wg.Add(1)
   669  		go func() {
   670  			if fib(20) != 6765 {
   671  				panic("error")
   672  			}
   673  			wg.Done()
   674  		}()
   675  	}
   676  	wg.Wait()
   677  }
   678  `
   679  	_, err := gossa.RunFile("main.go", src, nil, 0)
   680  	if err != nil {
   681  		t.Fatal(err)
   682  	}
   683  }
   684  
   685  func TestFibv(t *testing.T) {
   686  	src := `package main
   687  
   688  import "sync"
   689  
   690  func main() {
   691  	var fib func(n int) int
   692  	fib = func(n int) int {
   693  		if n < 2 {
   694  			return n
   695  		}
   696  		return fib(n-2) + fib(n-1)
   697  	}
   698  
   699  	var wg sync.WaitGroup
   700  	const N = 10
   701  	for i := 0; i < N; i++ {
   702  		wg.Add(1)
   703  		go func() {
   704  			if fib(20) != 6765 {
   705  				panic("error")
   706  			}
   707  			wg.Done()
   708  		}()
   709  	}
   710  	wg.Wait()
   711  }
   712  `
   713  	_, err := gossa.RunFile("main.go", src, nil, 0)
   714  	if err != nil {
   715  		t.Fatal(err)
   716  	}
   717  }
   718  
   719  func TestFibi(t *testing.T) {
   720  	src := `package main
   721  
   722  import "sync"
   723  
   724  type I interface {
   725  	fib(i I, n int) int
   726  }
   727  
   728  type T struct {
   729  }
   730  
   731  func (t *T) fib(i I, n int) int {
   732  	if n < 2 {
   733  		return n
   734  	}
   735  	return i.fib(i, n-2) + i.fib(i, n-1)
   736  }
   737  
   738  func fib(n int) int {
   739  	t := &T{}
   740  	return t.fib(t, n)
   741  }
   742  
   743  func main() {
   744  	var wg sync.WaitGroup
   745  	const N = 10
   746  	for i := 0; i < N; i++ {
   747  		wg.Add(1)
   748  		go func() {
   749  			if fib(20) != 6765 {
   750  				panic("error")
   751  			}
   752  			wg.Done()
   753  		}()
   754  	}
   755  	wg.Wait()
   756  }
   757  `
   758  	_, err := gossa.RunFile("main.go", src, nil, 0)
   759  	if err != nil {
   760  		t.Fatal(err)
   761  	}
   762  }
   763  
   764  func TestBinOpInt(t *testing.T) {
   765  	// + - * / % & ^ &^ < <= > >=
   766  	tsrc := `package main
   767  
   768  import "fmt"
   769  
   770  type T $int
   771  
   772  func main() {
   773  	// 0101 0110
   774  	test(5, 6)
   775  	testConst()
   776  	testDivideZero()
   777  }
   778  
   779  func testConst() {
   780  	var a T = 4
   781  	var b T = 2
   782  	var c T = 4
   783  	check(a+b,6)
   784  	check(a-b,2)
   785  	check(a*b,8)
   786  	check(a/b,2)
   787  	check(a%b,0)
   788  	check(a&b,0)
   789  	check(a|b,6)
   790  	check(a^b,6)
   791  	check(a&^b,4)
   792  	assert(a>b)
   793  	assert(a>=b)
   794  	assert(b<a)
   795  	assert(a<=a)
   796  	assert(a==c)
   797  	assert(a!=b)
   798  }
   799  
   800  func testDivideZero() {
   801  	defer func() {
   802  		if r := recover(); r == nil {
   803  			panic("must panic")
   804  		}
   805  	}()
   806  	var a T
   807  	var b T
   808  	_ = a/b
   809  }
   810  
   811  func test(a, b T) {
   812  	check(a+1, 6)
   813  	check(1+a, 6)
   814  	check(a+b, 11)
   815  	check(a-1, 4)
   816  	check(6-a, 1)
   817  	check(b-a, 1)
   818  	check(a*2, 10)
   819  	check(2*a, 10)
   820  	check(a*b, 30)
   821  	check(a/2, 2)
   822  	check(T(10)/a, 2)
   823  	check(a/b, 0)
   824  	check(a%2, 1)
   825  	check(10%a, 0)
   826  	check(b%a, 1)
   827  	check(a&4, 4)
   828  	check(1&a, 1)
   829  	check(a&b, 4)
   830  	check(a|4, 5)
   831  	check(2|a, 7)
   832  	check(a|b, 7)
   833  	check(a^2, 7)
   834  	check(7^a, 2)
   835  	check(a^b, 3)
   836  	check(a&^3, 4)
   837  	check(3&^a, 2)
   838  	check(a&^b, 1)
   839  	assert(a < 6)
   840  	assert(4 < a)
   841  	assert(a < b)
   842  	assert(a <= 5)
   843  	assert(4 <= a)
   844  	assert(a <= b)
   845  	assert(a > 4)
   846  	assert(6 > a)
   847  	assert(b > a)
   848  	assert(a >= 5)
   849  	assert(6 >= a)
   850  	assert(b >= a)
   851  	assert(a == 5)
   852  	assert(5 == a)
   853  	assert(a != 6)
   854  	assert(6 != a)
   855  	assert(a != b)
   856  	assert(a+1 == b)
   857  }
   858  
   859  func assert(t bool) {
   860  	if !t {
   861  		panic("error")
   862  	}
   863  }
   864  
   865  func check(a, b T) {
   866  	if a != b {
   867  		panic(fmt.Errorf("error %v != %v", a, b))
   868  	}
   869  }
   870  `
   871  	types := []string{
   872  		"int", "int8", "int16", "int32", "int64",
   873  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
   874  	}
   875  	for _, s := range types {
   876  		t.Log("test binop xtype", s)
   877  		src := strings.Replace(tsrc, "$int", "="+s, 1)
   878  		_, err := gossa.RunFile("main.go", src, nil, 0)
   879  		if err != nil {
   880  			t.Fatal(err)
   881  		}
   882  	}
   883  	for _, s := range types {
   884  		t.Log("test binop named", s)
   885  		src := strings.Replace(tsrc, "$int", s, 1)
   886  		_, err := gossa.RunFile("main.go", src, nil, 0)
   887  		if err != nil {
   888  			t.Fatal(err)
   889  		}
   890  	}
   891  }
   892  
   893  func TestBinOpFloat(t *testing.T) {
   894  	tsrc := `package main
   895  
   896  import "fmt"
   897  
   898  type T $float
   899  
   900  func main() {
   901  	test(5.0, 6.5)
   902  	testConst()
   903  }
   904  
   905  func testConst() {
   906  	var a T = 4.0
   907  	var b T = 2.0
   908  	var c T = 4.0
   909  	check(a+b,6)
   910  	check(a-b,2)
   911  	check(a*b,8)
   912  	check(a/b,2)
   913  	assert(a>b)
   914  	assert(a>=b)
   915  	assert(b<a)
   916  	assert(a<=a)
   917  	assert(a==c)
   918  	assert(a!=b)
   919  }
   920  
   921  func test(a, b T) {
   922  	check(a+1, 6)
   923  	check(1+a, 6)
   924  	check(a+b, 11.5)
   925  	check(a-1, 4)
   926  	check(6-a, 1)
   927  	check(b-a, 1.5)
   928  	check(a*2, 10)
   929  	check(2*a, 10)
   930  	check(a*b, 32.5)
   931  	check(a/2, 2.5)
   932  	check(10/a, 2)
   933  	check(a/b, 5.0/6.5)
   934  	assert(a < 6)
   935  	assert(4 < a)
   936  	assert(a < b)
   937  	assert(a <= 5)
   938  	assert(4 <= a)
   939  	assert(a <= b)
   940  	assert(a > 4)
   941  	assert(6 > a)
   942  	assert(b > a)
   943  	assert(a >= 5)
   944  	assert(6 >= a)
   945  	assert(b >= a)
   946  	assert(a == 5)
   947  	assert(5 == a)
   948  	assert(a != 6)
   949  	assert(6 != a)
   950  	assert(a != b)
   951  	assert(a+1.5 == b)
   952  }
   953  
   954  func assert(t bool) {
   955  	if !t {
   956  		panic("error")
   957  	}
   958  }
   959  
   960  func check(a, b T) {
   961  	if a != b {
   962  		panic(fmt.Errorf("error %v != %v", a, b))
   963  	}
   964  }
   965  `
   966  	types := []string{
   967  		"float32",
   968  		"float64",
   969  	}
   970  	for _, s := range types {
   971  		t.Log("test binop xtype", s)
   972  		src := strings.Replace(tsrc, "$float", "="+s, 1)
   973  		_, err := gossa.RunFile("main.go", src, nil, 0)
   974  		if err != nil {
   975  			t.Fatal(err)
   976  		}
   977  	}
   978  	for _, s := range types {
   979  		t.Log("test binop named", s)
   980  		src := strings.Replace(tsrc, "$float", s, 1)
   981  		_, err := gossa.RunFile("main.go", src, nil, 0)
   982  		if err != nil {
   983  			t.Fatal(err)
   984  		}
   985  	}
   986  }
   987  
   988  func TestBinOpComplex(t *testing.T) {
   989  	tsrc := `package main
   990  
   991  import "fmt"
   992  
   993  type T $complex
   994  
   995  func main() {
   996  	test(1+2i, 3+4i)
   997  	testConst()
   998  }
   999  
  1000  func testConst() {
  1001  	var a T = 4i
  1002  	var b T = 2i
  1003  	var c T = 4i
  1004  	check(a+b,6i)
  1005  	check(a-b,2i)
  1006  	check(a*b,-8)
  1007  	check(a/b,2)
  1008  	assert(a == c)
  1009  	assert(a != b)
  1010  }
  1011  
  1012  func test(a, b T) {
  1013  	check(a+1+2i, 2+4i)
  1014  	check(1+a, 2+2i)
  1015  	check(a+b, 4+6i)
  1016  	check(a-1, 2i)
  1017  	check(6-a, 5-2i)
  1018  	check(b-a, 2+2i)
  1019  	check(a*(2+3i), -4+7i)
  1020  	check((2-3i)*a, 8+1i)
  1021  	check(a*b, -5+10i)
  1022  	check(a/2i, 1-0.5i)
  1023  	check(10/a, 2-4i)
  1024  	check(a/b, 0.44+0.08i)
  1025  	assert(a == 1+2i)
  1026  	assert(1+2i == a)
  1027  	assert(a != 2+2i)
  1028  	assert(2+2i != a)
  1029  	assert(a != b)
  1030  	assert(a+2+2i == b)
  1031  }
  1032  
  1033  func assert(t bool) {
  1034  	if !t {
  1035  		panic("error")
  1036  	}
  1037  }
  1038  
  1039  func check(a, b T) {
  1040  	if a != b {
  1041  		panic(fmt.Errorf("error %v != %v", a, b))
  1042  	}
  1043  }
  1044  
  1045  `
  1046  	types := []string{
  1047  		"complex64",
  1048  		"complex128",
  1049  	}
  1050  	for _, s := range types {
  1051  		t.Log("test binop xtype", s)
  1052  		src := strings.Replace(tsrc, "$complex", "="+s, 1)
  1053  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1054  		if err != nil {
  1055  			t.Fatal(err)
  1056  		}
  1057  	}
  1058  	for _, s := range types {
  1059  		t.Log("test binop named", s)
  1060  		src := strings.Replace(tsrc, "$complex", s, 1)
  1061  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1062  		if err != nil {
  1063  			t.Fatal(err)
  1064  		}
  1065  	}
  1066  }
  1067  
  1068  func TestBinOpString(t *testing.T) {
  1069  	tsrc := `package main
  1070  
  1071  import "fmt"
  1072  
  1073  type T = string
  1074  
  1075  func main() {
  1076  	test("go", "ssa", "go")
  1077  	testConst()
  1078  }
  1079  
  1080  func testConst() {
  1081  	var a T = "hello"
  1082  	var b T = "world"
  1083  	var c T = "hello"
  1084  	check(a+b,"helloworld")
  1085  	assert(a < b)
  1086  	assert(a <= b)
  1087  	assert(b > a)
  1088  	assert(b >= a)
  1089  	assert(a == c)
  1090  	assert(a != b)
  1091  }
  1092  
  1093  func test(a, b, c T) {
  1094  	check(a+"run", "gorun")
  1095  	check("run"+a, "rungo")
  1096  	check(a+b, "gossa")
  1097  	assert(a < "go1")
  1098  	assert("ao" < a)
  1099  	assert(a < b)
  1100  	assert(a <= "go")
  1101  	assert("ao" <= a)
  1102  	assert(a <= b)
  1103  	assert(a > "ao")
  1104  	assert("go1" > a)
  1105  	assert(b > a)
  1106  	assert(a >= "go")
  1107  	assert("go1" >= a)
  1108  	assert(b >= a)
  1109  	assert(a == "go")
  1110  	assert("go" == a)
  1111  	assert(a != "go1")
  1112  	assert("go1" != a)
  1113  	assert(a != b)
  1114  	assert(a == c)
  1115  }
  1116  
  1117  func assert(t bool) {
  1118  	if !t {
  1119  		panic("error")
  1120  	}
  1121  }
  1122  
  1123  func check(a, b T) {
  1124  	if a != b {
  1125  		panic(fmt.Errorf("error %v != %v", a, b))
  1126  	}
  1127  }
  1128  `
  1129  	t.Log("test binop string")
  1130  	_, err := gossa.RunFile("main.go", tsrc, nil, 0)
  1131  	if err != nil {
  1132  		t.Fatal(err)
  1133  	}
  1134  	t.Log("test binop named string")
  1135  	src := strings.Replace(tsrc, "= string", "string", 1)
  1136  	_, err = gossa.RunFile("main.go", src, nil, 0)
  1137  	if err != nil {
  1138  		t.Fatal(err)
  1139  	}
  1140  }
  1141  
  1142  func TestBinOpShift(t *testing.T) {
  1143  	tsrc := `package main
  1144  type T1 $T1
  1145  type T2 $T2
  1146  
  1147  func main() {
  1148  	test(4, 2)
  1149  }
  1150  func test(a T1, b T2) {
  1151  	assert(a << b == 16)
  1152  	assert(a >> b == 1)
  1153  	assert(a << T2(2) == 16)
  1154  	assert(a >> T2(2) == 1)
  1155  	assert(T1(4) << b == 16)
  1156  	assert(T1(4) >> b == 1)
  1157  	var c T1 = 4
  1158  	var d T2 = 2
  1159  	assert(c << d == 16)
  1160  	assert(c >> d == 1)
  1161  }
  1162  func assert(t bool) {
  1163  	if !t {
  1164  		panic("error")
  1165  	}
  1166  }
  1167  `
  1168  	types := []string{
  1169  		"int", "int8", "int16", "int32", "int64",
  1170  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  1171  	}
  1172  	for _, t1 := range types {
  1173  		t.Log("test binop shift", t1)
  1174  		for _, t2 := range types {
  1175  			r := strings.NewReplacer("$T1", "="+t1, "$T2", "="+t2)
  1176  			src := r.Replace(tsrc)
  1177  			_, err := gossa.RunFile("main.go", src, nil, 0)
  1178  			if err != nil {
  1179  				t.Fatal(err)
  1180  			}
  1181  		}
  1182  		for _, t2 := range types {
  1183  			r := strings.NewReplacer("$T1", "="+t1, "$T2", t2)
  1184  			src := r.Replace(tsrc)
  1185  			_, err := gossa.RunFile("main.go", src, nil, 0)
  1186  			if err != nil {
  1187  				t.Fatal(err)
  1188  			}
  1189  		}
  1190  		for _, t2 := range types {
  1191  			r := strings.NewReplacer("$T1", t1, "$T2", "="+t2)
  1192  			src := r.Replace(tsrc)
  1193  			_, err := gossa.RunFile("main.go", src, nil, 0)
  1194  			if err != nil {
  1195  				t.Fatal(err)
  1196  			}
  1197  		}
  1198  		for _, t2 := range types {
  1199  			r := strings.NewReplacer("$T1", t1, "$T2", t2)
  1200  			src := r.Replace(tsrc)
  1201  			_, err := gossa.RunFile("main.go", src, nil, 0)
  1202  			if err != nil {
  1203  				t.Fatal(err)
  1204  			}
  1205  		}
  1206  	}
  1207  }
  1208  
  1209  func TestUnOpNot(t *testing.T) {
  1210  	src := `package main
  1211  type T bool
  1212  func main() {
  1213  	test(false,false)
  1214  	testConst()
  1215  }
  1216  func test(b1 bool, b2 T) {
  1217  	if v := !b1; v != true {
  1218  		panic("must true")
  1219  	}
  1220  	if v := !b2; v != true {
  1221  		panic("must true")
  1222  	}
  1223  }
  1224  func testConst() {
  1225  	var b1 bool
  1226  	var b2 T
  1227  	if v := !b1; v != true {
  1228  		panic("must true")
  1229  	}
  1230  	if v := !b2; v != true {
  1231  		panic("must true")
  1232  	}
  1233  }
  1234  `
  1235  	_, err := gossa.RunFile("main.go", src, nil, 0)
  1236  	if err != nil {
  1237  		t.Fatal(err)
  1238  	}
  1239  }
  1240  
  1241  func TestUnOpSubInt(t *testing.T) {
  1242  	tsrc := `package main
  1243  type T $int
  1244  
  1245  func main() {
  1246  	test(10,10)
  1247  	testConst()
  1248  }
  1249  
  1250  func test(a $int, b T) {
  1251  	if r := -a; r != -10 {
  1252  		panic("must -10")
  1253  	}
  1254  	if r := -b; r != -10 {
  1255  		panic("must -10")
  1256  	}
  1257  }
  1258  func testConst() {
  1259  	var a $int = 10
  1260  	var b T = 10
  1261  	if r := -a; r != -10 {
  1262  		panic("must -10")
  1263  	}
  1264  	if r := -b; r != -10 {
  1265  		panic("must -10")
  1266  	}
  1267  }
  1268  `
  1269  	types := []string{
  1270  		"int", "int8", "int16", "int32", "int64",
  1271  	}
  1272  
  1273  	for _, s := range types {
  1274  		t.Log("test unop sub", s)
  1275  		src := strings.Replace(tsrc, "$int", s, -1)
  1276  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1277  		if err != nil {
  1278  			t.Fatal(err)
  1279  		}
  1280  	}
  1281  }
  1282  
  1283  func TestUnOpSubUint(t *testing.T) {
  1284  	tsrc := `package main
  1285  
  1286  type T $uint
  1287  
  1288  func main() {
  1289  	test(0b1010, 0b1011)
  1290  	testConst()
  1291  }
  1292  
  1293  func test(a $uint, b T) {
  1294  	if r := -a; r&0xff != 0b11110110 {
  1295  		panic(r)
  1296  	}
  1297  	if r := -b; r&0xff != 0b11110101 {
  1298  		panic(r)
  1299  	}
  1300  }
  1301  func testConst() {
  1302  	var a $uint = 0b1010
  1303  	var b T = 0b1011
  1304  	if r := -a; r&0xff != 0b11110110 {
  1305  		panic(r)
  1306  	}
  1307  	if r := -b; r&0xff != 0b11110101 {
  1308  		panic(r)
  1309  	}
  1310  }
  1311  `
  1312  	types := []string{
  1313  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  1314  	}
  1315  	for _, s := range types {
  1316  		src := strings.Replace(tsrc, "$uint", s, -1)
  1317  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1318  		if err != nil {
  1319  			t.Fatal(err)
  1320  		}
  1321  	}
  1322  }
  1323  
  1324  func TestUnOpSubFloat(t *testing.T) {
  1325  	tsrc := `package main
  1326  
  1327  type T $float
  1328  
  1329  func main() {
  1330  	test(5.0, 6.5)
  1331  	testConst()
  1332  }
  1333  
  1334  func test(a $float, b T) {
  1335  	if r := -a; r != -5.0 {
  1336  		panic(r)
  1337  	}
  1338  	if r := -b; r != -6.5 {
  1339  		panic(r)
  1340  	}
  1341  }
  1342  func testConst() {
  1343  	var a $float = 5.0
  1344  	var b T = 6.5
  1345  	if r := -a; r != -5.0 {
  1346  		panic(r)
  1347  	}
  1348  	if r := -b; r != -6.5 {
  1349  		panic(r)
  1350  	}
  1351  }
  1352  `
  1353  	types := []string{
  1354  		"float32", "float64",
  1355  	}
  1356  	for _, s := range types {
  1357  		t.Log("test unop sub", s)
  1358  		src := strings.Replace(tsrc, "$float", s, -1)
  1359  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1360  		if err != nil {
  1361  			t.Fatal(err)
  1362  		}
  1363  	}
  1364  }
  1365  
  1366  func TestUnOpSubComplex(t *testing.T) {
  1367  	tsrc := `package main
  1368  
  1369  type T $complex
  1370  
  1371  func main() {
  1372  	test(1+2i, 3+4i)
  1373  	testConst()
  1374  }
  1375  
  1376  func test(a $complex, b T) {
  1377  	if r := -a; r != -1-2i {
  1378  		panic(r)
  1379  	}
  1380  	if r := -b; r != -3-4i {
  1381  		panic(r)
  1382  	}
  1383  }
  1384  func testConst() {
  1385  	var a $complex = 1+2i
  1386  	var b T = 3+4i
  1387  	if r := -a; r != -1-2i {
  1388  		panic(r)
  1389  	}
  1390  	if r := -b; r != -3-4i {
  1391  		panic(r)
  1392  	}
  1393  }
  1394  `
  1395  	types := []string{
  1396  		"complex64", "complex128",
  1397  	}
  1398  	for _, s := range types {
  1399  		t.Log("test unop sub", s)
  1400  		src := strings.Replace(tsrc, "$complex", s, -1)
  1401  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1402  		if err != nil {
  1403  			t.Fatal(err)
  1404  		}
  1405  	}
  1406  }
  1407  
  1408  func TestUnOpXorInt(t *testing.T) {
  1409  	tsrc := `package main
  1410  
  1411  type T $int
  1412  
  1413  func main() {
  1414  	test(10, 11)
  1415  	testConst()
  1416  }
  1417  
  1418  func test(a $int, b T) {
  1419  	if r := ^a; r != -11 {
  1420  		panic(r)
  1421  	}
  1422  	if r := ^b; r != -12 {
  1423  		panic(r)
  1424  	}
  1425  }
  1426  func testConst() {
  1427  	var a $int = 10
  1428  	var b T = 11
  1429  	if r := ^a; r != -11 {
  1430  		panic(r)
  1431  	}
  1432  	if r := ^b; r != -12 {
  1433  		panic(r)
  1434  	}
  1435  }
  1436  `
  1437  	types := []string{
  1438  		"int", "int8", "int16", "int32", "int64",
  1439  	}
  1440  
  1441  	for _, s := range types {
  1442  		t.Log("test unop xor", s)
  1443  		src := strings.Replace(tsrc, "$int", s, -1)
  1444  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1445  		if err != nil {
  1446  			t.Fatal(err)
  1447  		}
  1448  	}
  1449  }
  1450  
  1451  func TestUnOpXorUint(t *testing.T) {
  1452  	tsrc := `package main
  1453  
  1454  type T $uint
  1455  
  1456  func main() {
  1457  	test(0b1010, 0b1011)
  1458  	testConst()
  1459  }
  1460  
  1461  func test(a $uint, b T) {
  1462  	if r := ^a; r&0xff != 0b11110101 {
  1463  		panic(r)
  1464  	}
  1465  	if r := ^b; r&0xff != 0b11110100 {
  1466  		panic(r)
  1467  	}
  1468  }
  1469  func testConst() {
  1470  	var a $uint = 0b1010
  1471  	var b T = 0b1011
  1472  	if r := ^a; r&0xff != 0b11110101 {
  1473  		panic(r)
  1474  	}
  1475  	if r := ^b; r&0xff != 0b11110100 {
  1476  		panic(r)
  1477  	}
  1478  }
  1479  `
  1480  	types := []string{
  1481  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  1482  	}
  1483  
  1484  	for _, s := range types {
  1485  		t.Log("test unop xor", s)
  1486  		src := strings.Replace(tsrc, "$uint", s, -1)
  1487  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1488  		if err != nil {
  1489  			t.Fatal(err)
  1490  		}
  1491  	}
  1492  }
  1493  
  1494  func TestBinOpEQ(t *testing.T) {
  1495  	src := `package main
  1496  
  1497  import "unsafe"
  1498  
  1499  type T struct {
  1500  	a int
  1501  	b int
  1502  	_ int
  1503  	_ int
  1504  }
  1505  
  1506  func main() {
  1507  	// array
  1508  	ar1 := [2]int{10,20}
  1509  	ar2 := [2]int{10,20}
  1510  	if ar1 != ar2 {
  1511  		panic("error array")
  1512  	}
  1513  	ar1[0] = 1
  1514  	if ar1 == ar2 {
  1515  		panic("error array")
  1516  	}
  1517  	// struct & interface{}
  1518  	t1 := T{1,2,3,4}
  1519  	t2 := T{1,2,7,8}
  1520  	if t1 != t2 {
  1521  		panic("error struct")
  1522  	}
  1523  	if (interface{})(t1) != (interface{})(t2) {
  1524  		panic("error interface")
  1525  	}
  1526  	t1.a = 10
  1527  	if t1 == t2 {
  1528  		panic("error struct")
  1529  	}
  1530  	if (interface{})(t1) == (interface{})(t2) {
  1531  		panic("error interface")
  1532  	}
  1533  	// ptr
  1534  	ptr1 := &t1
  1535  	ptr2 := &t2
  1536  	if ptr1 == ptr2 {
  1537  		panic("error ptr")
  1538  	}
  1539  	ptr2 = &t1
  1540  	if ptr1 != ptr2 {
  1541  		panic("error ptr")
  1542  	}
  1543  	// unsafe pointer
  1544  	p1 := unsafe.Pointer(&t1)
  1545  	p2 := unsafe.Pointer(&t2)
  1546  	if p1 == p2 {
  1547  		panic("error unsafe pointer")
  1548  	}
  1549  	p2 = unsafe.Pointer(ptr2)
  1550  	if p1 != p2 {
  1551  		panic("error unsafe pointer")
  1552  	}
  1553  	// chan
  1554  	ch1 := make(chan int)
  1555  	ch2 := make(chan int)
  1556  	if ch1 == ch2 {
  1557  		panic("error chan")
  1558  	}
  1559  	ch3 := ch1
  1560  	if ch1 != ch3 {
  1561  		panic("error chan")
  1562  	}
  1563  	ch4 := (<-chan int)(ch1)
  1564  	ch5 := (chan<- int)(ch1)
  1565  	if ch1 != ch4 {
  1566  		panic("error chan")
  1567  	}
  1568  	if ch5 != ch1 {
  1569  		panic("error chan")
  1570  	}
  1571  	ch6 := (<-chan int)(ch2)
  1572  	ch7 := (chan<- int)(ch2)
  1573  	if ch6 == ch1 {
  1574  		panic("error chan")
  1575  	}
  1576  	if ch1 == ch7 {
  1577  		panic("error chan")
  1578  	}
  1579  }
  1580  `
  1581  	_, err := gossa.RunFile("main.go", src, nil, 0)
  1582  	if err != nil {
  1583  		t.Fatal(err)
  1584  	}
  1585  }
  1586  
  1587  func TestOpTypeChangeBasic(t *testing.T) {
  1588  	src := `package main
  1589  
  1590  import (
  1591  	"bytes"
  1592  	"fmt"
  1593  )
  1594  
  1595  func main() {
  1596  	testNil()
  1597  	testConst()
  1598  	testFunc()
  1599  	testPtr()
  1600  	testSlice()
  1601  	testMap()
  1602  	testStruct()
  1603  	testArray()
  1604  	testChan()
  1605  	testInterface()
  1606  }
  1607  
  1608  func testNil() {
  1609  	var p *int
  1610  	type Ptr *int
  1611  	v := Ptr(p)
  1612  	if s := fmt.Sprintf("%T %v", v, v); s != "main.Ptr <nil>" {
  1613  		panic(s)
  1614  	}
  1615  }
  1616  
  1617  func testConst() {
  1618  	var n int = 10
  1619  	type T int
  1620  	v := T(n)
  1621  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T 10" {
  1622  		panic(s)
  1623  	}
  1624  }
  1625  
  1626  func myfunc(int) {}
  1627  
  1628  type Func func(int)
  1629  
  1630  func testFunc() {
  1631  	v := Func(myfunc)
  1632  	if s := fmt.Sprintf("%T %v", v, v == nil); s != "main.Func false" {
  1633  		panic(s)
  1634  	}
  1635  }
  1636  
  1637  func testPtr() {
  1638  	i := 10
  1639  	p := &i
  1640  	type T *int
  1641  	v := T(p)
  1642  	i = 20
  1643  	if s := fmt.Sprintf("%T %v", v, *v); s != "main.T 20" {
  1644  		panic(s)
  1645  	}
  1646  	p2 := (*int)(v)
  1647  	i = 30
  1648  	if s := fmt.Sprintf("%T %v", p2, *p2); s != "*int 30" {
  1649  		panic(s)
  1650  	}
  1651  }
  1652  
  1653  func testSlice() {
  1654  	i := []int{100, 200, 300}
  1655  	type T []int
  1656  	v := T(i)
  1657  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T [100 200 300]" {
  1658  		panic(s)
  1659  	}
  1660  	p := []int(v)
  1661  	v[0] = 1
  1662  	if s := fmt.Sprintf("%T %v", p, p); s != "[]int [1 200 300]" {
  1663  		panic(s)
  1664  	}
  1665  }
  1666  
  1667  func testMap() {
  1668  	i := map[int]string{1: "hello", 2: "world"}
  1669  	type T map[int]string
  1670  	v := T(i)
  1671  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T map[1:hello 2:world]" {
  1672  		panic(s)
  1673  	}
  1674  	type T2 map[int]string
  1675  	v2 := T(v)
  1676  	i[1] = "hello2"
  1677  	if s := fmt.Sprintf("%T %v", v2, v2); s != "main.T map[1:hello2 2:world]" {
  1678  		panic(s)
  1679  	}
  1680  }
  1681  
  1682  func testStruct() {
  1683  	type Pt struct {
  1684  		x int
  1685  		y int
  1686  	}
  1687  	type T Pt
  1688  	i := Pt{10, 20}
  1689  	v := T(i)
  1690  	i.x = 1
  1691  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T {10 20}" {
  1692  		panic(s)
  1693  	}
  1694  }
  1695  
  1696  func testArray() {
  1697  	ar := [3]int{100, 200, 300}
  1698  	type T [3]int
  1699  	v := T(ar)
  1700  	ar[0] = 1
  1701  	if s := fmt.Sprintf("%T %v", v, v); s != "main.T [100 200 300]" {
  1702  		panic(s)
  1703  	}
  1704  }
  1705  
  1706  func testChan() {
  1707  	ch := make(chan int)
  1708  	v := (chan<- int)(ch)
  1709  	if s := fmt.Sprintf("%T", v); s != "chan<- int" {
  1710  		panic(s)
  1711  	}
  1712  	type T1 chan int
  1713  	v1 := T1(ch)
  1714  	if s := fmt.Sprintf("%T", v1); s != "main.T1" {
  1715  		panic(s)
  1716  	}
  1717  	type T2 <-chan int
  1718  	v2 := T2(ch)
  1719  	if s := fmt.Sprintf("%T", v2); s != "main.T2" {
  1720  		panic(s)
  1721  	}
  1722  	type T3 chan<- int
  1723  	v3 := T3(ch)
  1724  	if s := fmt.Sprintf("%T", v3); s != "main.T3" {
  1725  		panic(s)
  1726  	}
  1727  }
  1728  
  1729  func testInterface() {
  1730  	var buf fmt.Stringer = bytes.NewBufferString("hello")
  1731  	type T fmt.Stringer
  1732  	v := T(buf)
  1733  	if s := fmt.Sprintf("%T %v", v, v.String()); s != "*bytes.Buffer hello" {
  1734  		panic(s)
  1735  	}
  1736  }
  1737  `
  1738  	_, err := gossa.RunFile("main.go", src, nil, 0)
  1739  	if err != nil {
  1740  		t.Fatal(err)
  1741  	}
  1742  }
  1743  
  1744  func TestOpTypeChange3(t *testing.T) {
  1745  	tsrc := `package main
  1746  import "fmt"
  1747  type T $int
  1748  type T2 $int
  1749  func main() {
  1750  	test($value)
  1751  }
  1752  func test(v $int) {
  1753  	r := T(v)
  1754  	if s := fmt.Sprintf("%T", r); s != "main.T" {
  1755  		panic(s)
  1756  	}
  1757  	r2 := T2(r)
  1758  	if s := fmt.Sprintf("%T", r2); s != "main.T2" {
  1759  		panic(s)
  1760  	}
  1761  	n := $int(r2)
  1762  	if s := fmt.Sprintf("%T", n); s != "$int" {
  1763  		panic(s)
  1764  	}
  1765  	if n != v {
  1766  		panic("error")
  1767  	}
  1768  }
  1769  `
  1770  	ints := []string{
  1771  		"int", "int8", "int16", "int32", "int64",
  1772  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  1773  	}
  1774  	for _, s := range ints {
  1775  		t.Log("test changetype xtype", s)
  1776  		r := strings.NewReplacer("$int", s, "$value", "10")
  1777  		src := r.Replace(tsrc)
  1778  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1779  		if err != nil {
  1780  			t.Fatal(err)
  1781  		}
  1782  	}
  1783  	floats := []string{"float32", "float64"}
  1784  	for _, s := range floats {
  1785  		t.Log("test changetype xtype", s)
  1786  		r := strings.NewReplacer("$int", s, "$value", "100.5")
  1787  		src := r.Replace(tsrc)
  1788  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1789  		if err != nil {
  1790  			t.Fatal(err)
  1791  		}
  1792  	}
  1793  	comps := []string{"complex64", "complex128"}
  1794  	for _, s := range comps {
  1795  		t.Log("test changetype xtype", s)
  1796  		r := strings.NewReplacer("$int", s, "$value", "1+2i")
  1797  		src := r.Replace(tsrc)
  1798  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1799  		if err != nil {
  1800  			t.Fatal(err)
  1801  		}
  1802  	}
  1803  	{
  1804  		t.Log("test changetype xtype", "bool")
  1805  		r := strings.NewReplacer("$int", "bool", "$value", "true")
  1806  		src := r.Replace(tsrc)
  1807  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1808  		if err != nil {
  1809  			t.Fatal(err)
  1810  		}
  1811  	}
  1812  	{
  1813  		t.Log("test changetype xtype", "string")
  1814  		r := strings.NewReplacer("$int", "string", "$value", `"hello"`)
  1815  		src := r.Replace(tsrc)
  1816  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1817  		if err != nil {
  1818  			t.Fatal(err)
  1819  		}
  1820  	}
  1821  }
  1822  
  1823  func TestOpConvert(t *testing.T) {
  1824  	tsrc := `package main
  1825  
  1826  type T = $int
  1827  
  1828  const (
  1829  	V = $V
  1830  	N = $N
  1831  	F = $F
  1832  )
  1833  
  1834  func main() {
  1835  	test1(V)
  1836  	test2(V)
  1837  }
  1838  
  1839  func test1(n T) {
  1840  	if int(n) != N {
  1841  		panic("error")
  1842  	}
  1843  	if int8(n) != N {
  1844  		panic("error")
  1845  	}
  1846  	if int16(n) != N {
  1847  		panic("error")
  1848  	}
  1849  	if int32(n) != N {
  1850  		panic("error")
  1851  	}
  1852  	if int64(n) != N {
  1853  		panic("error")
  1854  	}
  1855  	if uint(n) != N {
  1856  		panic("error")
  1857  	}
  1858  	if uint8(n) != N {
  1859  		panic("error")
  1860  	}
  1861  	if uint16(n) != N {
  1862  		panic("error")
  1863  	}
  1864  	if uint32(n) != N {
  1865  		panic("error")
  1866  	}
  1867  	if uint64(n) != N {
  1868  		panic("error")
  1869  	}
  1870  	if uintptr(n) != N {
  1871  		panic("error")
  1872  	}
  1873  	if float32(n) != F {
  1874  		panic("error")
  1875  	}
  1876  	if float64(n) != F {
  1877  		panic("error")
  1878  	}
  1879  }
  1880  
  1881  type Int int
  1882  type Int8 int8
  1883  type Int16 int16
  1884  type Int32 int32
  1885  type Int64 int64
  1886  type Uint uint
  1887  type Uint8 uint8
  1888  type Uint16 uint16
  1889  type Uint32 uint32
  1890  type Uint64 uint64
  1891  type Uintptr uintptr
  1892  type Float32 float32
  1893  type Float64 float64
  1894  
  1895  func test2(n T) {
  1896  	if Int(n) != N {
  1897  		panic("error")
  1898  	}
  1899  	if Int8(n) != N {
  1900  		panic("error")
  1901  	}
  1902  	if Int16(n) != N {
  1903  		panic("error")
  1904  	}
  1905  	if Int32(n) != N {
  1906  		panic("error")
  1907  	}
  1908  	if Int64(n) != N {
  1909  		panic("error")
  1910  	}
  1911  	if Uint(n) != N {
  1912  		panic("error")
  1913  	}
  1914  	if Uint8(n) != N {
  1915  		panic("error")
  1916  	}
  1917  	if Uint16(n) != N {
  1918  		panic("error")
  1919  	}
  1920  	if Uint32(n) != N {
  1921  		panic("error")
  1922  	}
  1923  	if Uint64(n) != N {
  1924  		panic("error")
  1925  	}
  1926  	if Uintptr(n) != N {
  1927  		panic("error")
  1928  	}
  1929  	if Float32(n) != F {
  1930  		panic("error")
  1931  	}
  1932  	if Float64(n) != F {
  1933  		panic("error")
  1934  	}
  1935  }
  1936  `
  1937  	csrc := `package main
  1938  
  1939  type T = $complex
  1940  
  1941  const (
  1942  	N = $N
  1943  )
  1944  
  1945  func main() {
  1946  	test1(N)
  1947  	test2(N)
  1948  }
  1949  
  1950  func test1(n T) {
  1951  	if complex64(n) != N {
  1952  		panic("error")
  1953  	}
  1954  	if complex128(n) != N {
  1955  		panic("error")
  1956  	}
  1957  }
  1958  
  1959  type Complex64 complex64
  1960  type Complex128 complex128
  1961  
  1962  
  1963  func test2(n T) {
  1964  	if Complex64(n) != N {
  1965  		panic("error")
  1966  	}
  1967  	if Complex128(n) != N {
  1968  		panic("error")
  1969  	}
  1970  }
  1971  `
  1972  	ints := []string{
  1973  		"int", "int8", "int16", "int32", "int64",
  1974  		"uint", "uint8", "uint16", "uint32", "uint64", "uintptr",
  1975  	}
  1976  	floats := []string{"float32", "float64"}
  1977  	comps := []string{"complex64", "complex128"}
  1978  	for _, s := range ints {
  1979  		t.Log("test convert xtype", s)
  1980  		r := strings.NewReplacer("$int", s, "$V", "100", "$N", "100", "$F", "100")
  1981  		src := r.Replace(tsrc)
  1982  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1983  		if err != nil {
  1984  			t.Fatal(err)
  1985  		}
  1986  	}
  1987  	for _, s := range ints {
  1988  		t.Log("test convert typed", s)
  1989  		r := strings.NewReplacer("= $int", s, "$V", "100", "$N", "100", "$F", "100")
  1990  		src := r.Replace(tsrc)
  1991  		_, err := gossa.RunFile("main.go", src, nil, 0)
  1992  		if err != nil {
  1993  			t.Fatal(err)
  1994  		}
  1995  	}
  1996  	for _, s := range floats {
  1997  		t.Log("test convert xtype", s)
  1998  		r := strings.NewReplacer("$int", s, "$V", "100.5", "$N", "100", "$F", "100.5")
  1999  		src := r.Replace(tsrc)
  2000  		_, err := gossa.RunFile("main.go", src, nil, 0)
  2001  		if err != nil {
  2002  			t.Fatal(err)
  2003  		}
  2004  	}
  2005  	for _, s := range floats {
  2006  		t.Log("test convert typed", s)
  2007  		r := strings.NewReplacer("= $int", s, "$V", "100.5", "$N", "100", "$F", "100.5")
  2008  		src := r.Replace(tsrc)
  2009  		_, err := gossa.RunFile("main.go", src, nil, 0)
  2010  		if err != nil {
  2011  			t.Fatal(err)
  2012  		}
  2013  	}
  2014  	for _, s := range comps {
  2015  		t.Log("test convert xtype", s)
  2016  		r := strings.NewReplacer("$complex", s, "$N", "1+2i")
  2017  		src := r.Replace(csrc)
  2018  		_, err := gossa.RunFile("main.go", src, nil, 0)
  2019  		if err != nil {
  2020  			t.Fatal(err)
  2021  		}
  2022  	}
  2023  	for _, s := range comps {
  2024  		t.Log("test convert typed", s)
  2025  		r := strings.NewReplacer("= $complex", s, "$N", "1+2i")
  2026  		src := r.Replace(csrc)
  2027  		_, err := gossa.RunFile("main.go", src, nil, 0)
  2028  		if err != nil {
  2029  			t.Fatal(err)
  2030  		}
  2031  	}
  2032  }
  2033  
  2034  func TestOpIf(t *testing.T) {
  2035  	src := `package main
  2036  
  2037  type Bool bool
  2038  
  2039  func main() {
  2040  	test1(true)
  2041  	test1(false)
  2042  	test2(true)
  2043  	test2(false)
  2044  	testConst1()
  2045  	testConst2()
  2046  }
  2047  
  2048  func test1(b bool) {
  2049  	if b {
  2050  		println(true)
  2051  	} else {
  2052  		println(false)
  2053  	}
  2054  }
  2055  func test2(b Bool) {
  2056  	if b {
  2057  		println(true)
  2058  	} else {
  2059  		println(false)
  2060  	}
  2061  }
  2062  func testConst1() {
  2063  	var b bool
  2064  	if !b {
  2065  		println(false)
  2066  	}
  2067  	b = true
  2068  	if b {
  2069  		println(true)
  2070  	}
  2071  }
  2072  func testConst2() {
  2073  	var b Bool
  2074  	if !b {
  2075  		println(false)
  2076  	}
  2077  	b = true
  2078  	if b {
  2079  		println(true)
  2080  	}
  2081  }
  2082  `
  2083  	out := `true
  2084  false
  2085  true
  2086  false
  2087  false
  2088  true
  2089  false
  2090  true
  2091  `
  2092  	ctx := gossa.NewContext(0)
  2093  	var buf bytes.Buffer
  2094  	ctx.SetPrintOutput(&buf)
  2095  	_, err := ctx.RunFile("main.go", src, nil)
  2096  	if err != nil {
  2097  		t.Fatal(err)
  2098  	}
  2099  	if buf.String() != out {
  2100  		t.Fatal("error")
  2101  	}
  2102  }
  2103  
  2104  func TestGoexitDeadlock(t *testing.T) {
  2105  	src := `package main
  2106  import (
  2107  	"os"
  2108  	"runtime"
  2109  )
  2110  
  2111  func init() {
  2112  	runtime.Goexit()
  2113  	os.Exit(-1)
  2114  }
  2115  
  2116  func main() {
  2117  	os.Exit(-2)
  2118  }
  2119  `
  2120  	_, err := gossa.RunFile("main.go", src, nil, 0)
  2121  	if err == nil {
  2122  		t.Fatal("must panic")
  2123  	}
  2124  	if err.Error() != gossa.ErrGoexitDeadlock.Error() {
  2125  		t.Fatal(err)
  2126  	}
  2127  }
  2128  
  2129  func TestGlobalExtFunc(t *testing.T) {
  2130  	src := `package main
  2131  import "math"
  2132  var (
  2133  	max = math.Max
  2134  )
  2135  func main() {
  2136  	if max(1,3) != 3 {
  2137  		panic("error")
  2138  	}
  2139  }
  2140  `
  2141  	_, err := gossa.RunFile("main.go", src, nil, 0)
  2142  	if err != nil {
  2143  		t.Fatal(err)
  2144  	}
  2145  }
  2146  
  2147  func TestRegisterBuiltin(t *testing.T) {
  2148  	src := `package main
  2149  
  2150  func main() {
  2151  	dump_info(typeof("hello"))
  2152  }
  2153  `
  2154  	gossa.RegisterCustomBuiltin("typeof", reflect.TypeOf)
  2155  	var info interface{}
  2156  	gossa.RegisterCustomBuiltin("dump_info", func(v interface{}) {
  2157  		info = v
  2158  	})
  2159  	_, err := gossa.RunFile("main.go", src, nil, 0)
  2160  	if err != nil {
  2161  		panic(err)
  2162  	}
  2163  	if info != reflect.TypeOf("hello") {
  2164  		panic("error")
  2165  	}
  2166  }