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 }