github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/tests/misc_test.go (about) 1 package tests 2 3 import ( 4 "go/token" 5 "math" 6 "reflect" 7 "runtime" 8 "strings" 9 "sync" 10 "testing" 11 "time" 12 "unsafe" 13 14 "github.com/gopherjs/gopherjs/tests/otherpkg" 15 ) 16 17 func TestSyntax1(t *testing.T) { 18 a := 42 19 if *&*&a != 42 { 20 t.Fail() 21 } 22 } 23 24 func TestPointerEquality(t *testing.T) { 25 a := 1 26 b := 1 27 if &a != &a || &a == &b { 28 t.Fail() 29 } 30 m := make(map[*int]int) 31 m[&a] = 2 32 m[&b] = 3 33 if m[&a] != 2 || m[&b] != 3 { 34 t.Fail() 35 } 36 37 for { 38 c := 1 39 d := 1 40 if &c != &c || &c == &d { 41 t.Fail() 42 } 43 break 44 } 45 46 s := struct { 47 e int 48 f int 49 }{1, 1} 50 if &s.e != &s.e || &s.e == &s.f { 51 t.Fail() 52 } 53 54 g := [3]int{1, 2, 3} 55 if &g[0] != &g[0] || &g[:][0] != &g[0] || &g[:][0] != &g[:][0] { 56 t.Fail() 57 } 58 } 59 60 type SingleValue struct { 61 Value uint16 62 } 63 64 type OtherSingleValue struct { 65 Value uint16 66 } 67 68 func TestStructKey(t *testing.T) { 69 m := make(map[SingleValue]int) 70 m[SingleValue{Value: 1}] = 42 71 m[SingleValue{Value: 2}] = 43 72 if m[SingleValue{Value: 1}] != 42 || m[SingleValue{Value: 2}] != 43 || reflect.ValueOf(m).MapIndex(reflect.ValueOf(SingleValue{Value: 1})).Interface() != 42 { 73 t.Fail() 74 } 75 76 m2 := make(map[interface{}]int) 77 m2[SingleValue{Value: 1}] = 42 78 m2[SingleValue{Value: 2}] = 43 79 m2[OtherSingleValue{Value: 1}] = 44 80 if m2[SingleValue{Value: 1}] != 42 || m2[SingleValue{Value: 2}] != 43 || m2[OtherSingleValue{Value: 1}] != 44 || reflect.ValueOf(m2).MapIndex(reflect.ValueOf(SingleValue{Value: 1})).Interface() != 42 { 81 t.Fail() 82 } 83 } 84 85 func TestSelectOnNilChan(t *testing.T) { 86 var c1 chan bool 87 c2 := make(chan bool) 88 89 go func() { 90 close(c2) 91 }() 92 93 select { 94 case <-c1: 95 t.Fail() 96 case <-c2: 97 // ok 98 } 99 } 100 101 type StructA struct { 102 x int 103 } 104 105 type StructB struct { 106 StructA 107 } 108 109 func TestEmbeddedStruct(t *testing.T) { 110 a := StructA{ 111 42, 112 } 113 b := StructB{ 114 StructA: a, 115 } 116 b.x = 0 117 if a.x != 42 { 118 t.Fail() 119 } 120 } 121 122 func TestMapStruct(t *testing.T) { 123 a := StructA{ 124 42, 125 } 126 m := map[int]StructA{ 127 1: a, 128 } 129 m[2] = a 130 a.x = 0 131 if m[1].x != 42 || m[2].x != 42 { 132 t.Fail() 133 } 134 } 135 136 func TestUnnamedParameters(t *testing.T) { 137 ok := false 138 defer func() { 139 if !ok { 140 t.Fail() 141 } 142 }() 143 blockingWithUnnamedParameter(false) // used to cause non-blocking call error, which is ignored by testing 144 ok = true 145 } 146 147 func blockingWithUnnamedParameter(bool) { 148 c := make(chan int, 1) 149 c <- 42 150 } 151 152 func TestGotoLoop(t *testing.T) { 153 goto loop 154 loop: 155 for i := 42; ; { 156 if i != 42 { 157 t.Fail() 158 } 159 break 160 } 161 } 162 163 func TestMaxUint64(t *testing.T) { 164 if math.MaxUint64 != 18446744073709551615 { 165 t.Fail() 166 } 167 } 168 169 func TestCopyBuiltin(t *testing.T) { 170 { 171 s := []string{"a", "b", "c"} 172 copy(s, s[1:]) 173 if s[0] != "b" || s[1] != "c" || s[2] != "c" { 174 t.Fail() 175 } 176 } 177 { 178 s := []string{"a", "b", "c"} 179 copy(s[1:], s) 180 if s[0] != "a" || s[1] != "a" || s[2] != "b" { 181 t.Fail() 182 } 183 } 184 } 185 186 func TestPointerOfStructConversion(t *testing.T) { 187 type A struct { 188 Value int 189 } 190 191 type B A 192 193 type AP *A 194 195 a1 := &A{Value: 1} 196 b1 := (*B)(a1) 197 b1.Value = 2 198 a2 := (*A)(b1) 199 a2.Value = 3 200 b2 := (*B)(a2) 201 b2.Value = 4 202 if a1 != a2 || b1 != b2 || a1.Value != 4 || a2.Value != 4 || b1.Value != 4 || b2.Value != 4 { 203 t.Fail() 204 } 205 206 if got := reflect.TypeOf((AP)(&A{Value: 1})); got.String() != "tests.AP" { 207 t.Errorf("Got: reflect.TypeOf((AP)(&A{Value: 1})) = %v. Want: tests.AP.", got) 208 } 209 } 210 211 func TestCompareStruct(t *testing.T) { 212 type A struct { 213 Value int 214 } 215 216 a := A{42} 217 var b interface{} = a 218 x := A{0} 219 220 if a != b || a == x || b == x { 221 t.Fail() 222 } 223 } 224 225 func TestLoopClosure(t *testing.T) { 226 type S struct{ fn func() int } 227 var fns []*S 228 for i := 0; i < 2; i++ { 229 z := i 230 fns = append(fns, &S{ 231 fn: func() int { 232 return z 233 }, 234 }) 235 } 236 for i, f := range fns { 237 if f.fn() != i { 238 t.Fail() 239 } 240 } 241 } 242 243 func TestLoopClosureWithStruct(t *testing.T) { 244 type T struct{ A int } 245 ts := []T{{0}, {1}, {2}} 246 fns := make([]func() T, 3) 247 for i, t := range ts { 248 t := t 249 fns[i] = func() T { 250 return t 251 } 252 } 253 for i := range fns { 254 if fns[i]().A != i { 255 t.Fail() 256 } 257 } 258 } 259 260 func TestNilInterfaceError(t *testing.T) { 261 defer func() { 262 if err := recover(); err == nil || !strings.Contains(err.(error).Error(), "nil pointer dereference") { 263 t.Fail() 264 } 265 }() 266 var err error 267 _ = err.Error() 268 } 269 270 func TestIndexOutOfRangeError(t *testing.T) { 271 defer func() { 272 if err := recover(); err == nil || !strings.Contains(err.(error).Error(), "index out of range") { 273 t.Fail() 274 } 275 }() 276 x := []int{1, 2, 3}[10] 277 _ = x 278 } 279 280 func TestNilAtLhs(t *testing.T) { 281 type F func(string) string 282 var f F 283 if nil != f { 284 t.Fail() 285 } 286 } 287 288 func TestZeroResultByPanic(t *testing.T) { 289 if zero() != 0 { 290 t.Fail() 291 } 292 } 293 294 func zero() int { 295 defer func() { 296 recover() 297 }() 298 panic("") 299 } 300 301 func TestNumGoroutine(t *testing.T) { 302 n := runtime.NumGoroutine() 303 c := make(chan bool) 304 go func() { 305 <-c 306 <-c 307 <-c 308 <-c 309 }() 310 c <- true 311 c <- true 312 c <- true 313 if got, want := runtime.NumGoroutine(), n+1; got != want { 314 t.Errorf("runtime.NumGoroutine(): Got %d, want %d.", got, want) 315 } 316 c <- true 317 } 318 319 func TestMapAssign(t *testing.T) { 320 x := 0 321 m := map[string]string{} 322 x, m["foo"] = 5, "bar" 323 if x != 5 || m["foo"] != "bar" { 324 t.Fail() 325 } 326 } 327 328 func TestSwitchStatement(t *testing.T) { 329 zero := 0 330 var interfaceZero interface{} = zero 331 switch { 332 case interfaceZero: 333 t.Fail() 334 default: 335 // ok 336 } 337 } 338 339 func TestAddAssignOnPackageVar(t *testing.T) { 340 otherpkg.Test = 0 341 otherpkg.Test += 42 342 if otherpkg.Test != 42 { 343 t.Fail() 344 } 345 } 346 347 func TestPointerOfPackageVar(t *testing.T) { 348 otherpkg.Test = 42 349 p := &otherpkg.Test 350 if *p != 42 { 351 t.Fail() 352 } 353 } 354 355 func TestFuncInSelect(t *testing.T) { 356 f := func(_ func()) chan int { 357 return make(chan int, 1) 358 } 359 select { 360 case <-f(func() {}): 361 case _ = <-f(func() {}): 362 case f(func() {}) <- 42: 363 } 364 } 365 366 func TestEscapeAnalysisOnForLoopVariableScope(t *testing.T) { 367 for i := 0; ; { 368 p := &i 369 time.Sleep(0) 370 i = 42 371 if *p != 42 { 372 t.Fail() 373 } 374 break 375 } 376 } 377 378 func TestGoStmtWithStructArg(t *testing.T) { 379 type S struct { 380 i int 381 } 382 383 f := func(s S, c chan int) { 384 c <- s.i 385 c <- s.i 386 } 387 388 c := make(chan int) 389 s := S{42} 390 go f(s, c) 391 s.i = 0 392 if <-c != 42 { 393 t.Fail() 394 } 395 if <-c != 42 { 396 t.Fail() 397 } 398 } 399 400 type methodExprCallType int 401 402 func (i methodExprCallType) test() int { 403 return int(i) + 2 404 } 405 406 func TestMethodExprCall(t *testing.T) { 407 if methodExprCallType.test(40) != 42 { 408 t.Fail() 409 } 410 } 411 412 func TestCopyOnSend(t *testing.T) { 413 type S struct{ i int } 414 c := make(chan S, 2) 415 go func() { 416 var s S 417 s.i = 42 418 c <- s 419 select { 420 case c <- s: 421 } 422 s.i = 10 423 }() 424 if (<-c).i != 42 { 425 t.Fail() 426 } 427 if (<-c).i != 42 { 428 t.Fail() 429 } 430 } 431 432 func TestEmptySelectCase(t *testing.T) { 433 ch := make(chan int, 1) 434 ch <- 42 435 436 v := 0 437 select { 438 case v = <-ch: 439 } 440 if v != 42 { 441 t.Fail() 442 } 443 } 444 445 var ( 446 a int 447 b int 448 C int 449 D int 450 ) 451 452 var ( 453 a1 = &a 454 a2 = &a 455 b1 = &b 456 C1 = &C 457 C2 = &C 458 D1 = &D 459 ) 460 461 func TestPkgVarPointers(t *testing.T) { 462 if a1 != a2 || a1 == b1 || C1 != C2 || C1 == D1 { 463 t.Fail() 464 } 465 } 466 467 func TestStringMap(t *testing.T) { 468 m := make(map[string]interface{}) 469 if m["__proto__"] != nil { 470 t.Fail() 471 } 472 m["__proto__"] = 42 473 if m["__proto__"] != 42 { 474 t.Fail() 475 } 476 } 477 478 type Int int 479 480 func (i Int) Value() int { 481 return int(i) 482 } 483 484 func (i *Int) ValueByPtr() int { 485 return int(*i) 486 } 487 488 func TestWrappedTypeMethod(t *testing.T) { 489 i := Int(42) 490 p := &i 491 if p.Value() != 42 { 492 t.Fail() 493 } 494 } 495 496 type EmbeddedInt struct { 497 Int 498 } 499 500 func TestEmbeddedMethod(t *testing.T) { 501 e := EmbeddedInt{42} 502 if e.ValueByPtr() != 42 { 503 t.Fail() 504 } 505 } 506 507 func TestBoolConvert(t *testing.T) { 508 if !reflect.ValueOf(true).Convert(reflect.TypeOf(true)).Bool() { 509 t.Fail() 510 } 511 } 512 513 func TestGoexit(t *testing.T) { 514 go func() { 515 runtime.Goexit() 516 }() 517 } 518 519 func TestShift(t *testing.T) { 520 if x := uint(32); uint32(1)<<x != 0 { 521 t.Fail() 522 } 523 if x := uint64(0); uint32(1)<<x != 1 { 524 t.Fail() 525 } 526 if x := uint(4294967295); x>>32 != 0 { 527 t.Fail() 528 } 529 if x := uint(4294967295); x>>35 != 0 { 530 t.Fail() 531 } 532 } 533 534 func TestTrivialSwitch(t *testing.T) { 535 for { 536 switch { 537 default: 538 break 539 } 540 return 541 } 542 t.Fail() //nolint:govet // unreachable code intentional for test 543 } 544 545 func TestTupleFnReturnImplicitCast(t *testing.T) { 546 var ycalled int = 0 547 x := func(fn func() (int, error)) (interface{}, error) { 548 return fn() 549 } 550 y, _ := x(func() (int, error) { 551 ycalled++ 552 return 14, nil 553 }) 554 if y != 14 || ycalled != 1 { 555 t.Fail() 556 } 557 } 558 559 var tuple2called = 0 560 561 func tuple1() (interface{}, error) { 562 return tuple2() 563 } 564 565 func tuple2() (int, error) { 566 tuple2called++ 567 return 14, nil 568 } 569 570 func TestTupleReturnImplicitCast(t *testing.T) { 571 x, _ := tuple1() 572 if x != 14 || tuple2called != 1 { 573 t.Fail() 574 } 575 } 576 577 func TestDeferNamedTupleReturnImplicitCast(t *testing.T) { 578 var ycalled int = 0 579 var zcalled int = 0 580 z := func() { 581 zcalled++ 582 } 583 x := func(fn func() (int, error)) (i interface{}, e error) { 584 defer z() 585 i, e = fn() 586 return 587 } 588 y, _ := x(func() (int, error) { 589 ycalled++ 590 return 14, nil 591 }) 592 if y != 14 || ycalled != 1 || zcalled != 1 { 593 t.Fail() 594 } 595 } 596 597 func TestSliceOfString(t *testing.T) { 598 defer func() { 599 if err := recover(); err == nil || !strings.Contains(err.(error).Error(), "slice bounds out of range") { 600 t.Fail() 601 } 602 }() 603 604 str := "foo" 605 print(str[0:10]) 606 } 607 608 func TestSliceOutOfRange(t *testing.T) { 609 defer func() { 610 if err := recover(); err == nil || !strings.Contains(err.(error).Error(), "slice bounds out of range") { 611 t.Fail() 612 } 613 }() 614 615 a := make([]byte, 4) 616 b := a[8:] 617 _ = b 618 } 619 620 type R struct{ v int } 621 622 func (r R) Val() int { 623 return r.v 624 } 625 626 func TestReceiverCapture(t *testing.T) { 627 r := R{1} 628 f1 := r.Val 629 r = R{2} 630 f2 := r.Val 631 if f1() != 1 || f2() != 2 { 632 t.Fail() 633 } 634 } 635 636 func TestTypeConversion(t *testing.T) { 637 i1, i2, i3 := 4, 2, 2 638 if (i1-i2)/i3 != int(i1-i2)/int(i3) { 639 t.Fail() 640 } 641 f1, f2, f3 := 4.0, 2.0, 2.0 642 if (f1-f2)/f3 != float64(f1-f2)/float64(f3) { 643 t.Fail() 644 } 645 } 646 647 // See https://github.com/gopherjs/gopherjs/issues/851. 648 func TestSlicingNilSlice(t *testing.T) { 649 t.Run("StaysNil", func(t *testing.T) { 650 var s []int 651 s = s[:] 652 if s != nil { 653 t.Errorf("nil slice became non-nil after slicing with s[:]: %#v, want []int(nil)", s) 654 } 655 s = nil 656 s = s[0:0] 657 if s != nil { 658 t.Errorf("nil slice became non-nil after slicing with s[0:0]: %#v, want []int(nil)", s) 659 } 660 s = nil 661 s = s[0:0:0] 662 if s != nil { 663 t.Errorf("nil slice became non-nil after slicing with s[0:0:0]: %#v, want []int(nil)", s) 664 } 665 }) 666 t.Run("Panics", func(t *testing.T) { 667 defer func() { 668 if err := recover(); err == nil || !strings.Contains(err.(error).Error(), "slice bounds out of range") { 669 t.Error("slicing nil slice out of range didn't panic, want panic") 670 } 671 }() 672 var s []int 673 s = s[5:10] 674 }) 675 t.Run("DoesNotBecomeNil", func(t *testing.T) { 676 s := []int{} 677 s = s[:] 678 if s == nil { 679 t.Errorf("non-nil slice became nil after slicing: %#v, want []int{}", s) 680 } 681 }) 682 } 683 684 func TestConvertingNilSlice(t *testing.T) { 685 type mySlice []byte 686 687 a := []byte(nil) 688 if a != nil { 689 t.Errorf("[]byte(nil) != nil") 690 } 691 692 b := mySlice(a) 693 if b != nil { 694 t.Errorf("mySlice([]byte(nil)) != nil") 695 } 696 697 c := mySlice(nil) 698 if c != nil { 699 t.Errorf("mySlice(nil) != nil") 700 } 701 } 702 703 // Ensure that doing an interface conversion that fails 704 // produces an expected error type with the right error text. 705 func TestInterfaceConversionRuntimeError(t *testing.T) { 706 defer func() { 707 r := recover() 708 if r == nil { 709 t.Fatal("got no panic, want panic") 710 } 711 re, ok := r.(runtime.Error) 712 if !ok { 713 t.Fatalf("got %T (%s), want runtime.Error", r, r) 714 } 715 if got, want := re.Error(), "interface conversion: int is not tests.I: missing method Get"; got != want { 716 t.Fatalf("got %q, want %q", got, want) 717 } 718 }() 719 type I interface { 720 Get() int 721 } 722 e := (interface{})(0) 723 _ = e.(I) 724 } 725 726 func TestReflectMapIterationAndDelete(t *testing.T) { 727 m := map[string]int{ 728 "one": 1, 729 "two": 2, 730 "three": 3, 731 } 732 iter := reflect.ValueOf(m).MapRange() 733 for iter.Next() { 734 delete(m, iter.Key().String()) 735 } 736 if got, want := len(m), 0; got != want { 737 t.Fatalf("got %d, want %d", got, want) 738 } 739 } 740 741 func TestUntypedNil(t *testing.T) { 742 // This test makes sure GopherJS compiler is able to correctly infer the 743 // desired type of an untyped nil ident. 744 // See https://github.com/gopherjs/gopherjs/issues/1011 for details. 745 746 // Code below is based on test cases from https://golang.org/cl/284052. 747 var _ *int = nil 748 var _ func() = nil 749 var _ []byte = nil 750 var _ map[int]int = nil 751 var _ chan int = nil 752 var _ interface{} = nil 753 754 { 755 var ( 756 x *int = nil 757 _ = x 758 ) 759 } 760 { 761 var ( 762 x func() = nil 763 _ = x 764 ) 765 } 766 { 767 var ( 768 x []byte = nil 769 _ = x 770 ) 771 } 772 { 773 var ( 774 x map[int]int = nil 775 _ = x 776 ) 777 } 778 { 779 var ( 780 x chan int = nil 781 _ = x 782 ) 783 } 784 { 785 var ( 786 x interface{} = nil 787 _ = x 788 ) 789 } 790 791 { 792 var ( 793 x *int 794 _ = x == nil 795 ) 796 } 797 { 798 var ( 799 x func() 800 _ = x == nil 801 ) 802 } 803 { 804 var ( 805 x []byte 806 _ = x == nil 807 ) 808 } 809 { 810 var ( 811 x map[int]int 812 _ = x == nil 813 ) 814 } 815 { 816 var ( 817 x chan int 818 _ = x == nil 819 ) 820 } 821 { 822 var ( 823 x interface{} 824 _ = x == nil 825 ) 826 } 827 _ = (*int)(nil) 828 _ = (func())(nil) 829 _ = ([]byte)(nil) 830 _ = (map[int]int)(nil) 831 _ = (chan int)(nil) 832 _ = (interface{})(nil) 833 { 834 f := func(*int) {} 835 f(nil) 836 } 837 { 838 f := func(func()) {} 839 f(nil) 840 } 841 { 842 f := func([]byte) {} 843 f(nil) 844 } 845 { 846 f := func(map[int]int) {} 847 f(nil) 848 } 849 { 850 f := func(chan int) {} 851 f(nil) 852 } 853 { 854 f := func(interface{}) {} 855 f(nil) 856 } 857 { 858 f := func(*int) {} 859 f(nil) 860 } 861 { 862 f := func(*int) {} 863 f(nil) 864 } 865 { 866 f := func(*int) {} 867 f(nil) 868 } 869 { 870 f := func(*int) {} 871 f(nil) 872 } 873 } 874 875 func TestVersion(t *testing.T) { 876 if got := runtime.Version(); !strings.HasPrefix(got, "go1.") { 877 t.Fatalf("Got: runtime.Version() returned %q. Want: a valid Go version.", got) 878 } 879 } 880 881 // https://github.com/gopherjs/gopherjs/issues/1163 882 func TestReflectSetForEmbed(t *testing.T) { 883 type Point struct { 884 x int 885 y int 886 } 887 type Embed struct { 888 value bool 889 point Point 890 } 891 type A struct { 892 Embed 893 } 894 c := &A{} 895 c.value = true 896 c.point = Point{100, 200} 897 in := reflect.ValueOf(c).Elem() 898 v := reflect.New(in.Type()) 899 e := v.Elem() 900 f0 := e.Field(0) 901 e.Set(in) 902 if e.Field(0) != f0 { 903 t.Fatalf("reflect.Set got %v, want %v", f0, e.Field(0)) 904 } 905 } 906 907 func TestAssignImplicitConversion(t *testing.T) { 908 type S struct{} 909 type SP *S 910 911 t.Run("Pointer to named type", func(t *testing.T) { 912 var sp SP = &S{} 913 if got := reflect.TypeOf(sp); got.String() != "tests.SP" { 914 t.Errorf("Got: reflect.TypeOf(sp) = %v. Want: tests.SP", got) 915 } 916 }) 917 918 t.Run("Anonymous struct to named type", func(t *testing.T) { 919 var s S = struct{}{} 920 if got := reflect.TypeOf(s); got.String() != "tests.S" { 921 t.Errorf("Got: reflect.TypeOf(s) = %v. Want: tests.S", got) 922 } 923 }) 924 925 t.Run("Named type to anonymous type", func(t *testing.T) { 926 var x struct{} = S{} 927 if got := reflect.TypeOf(x); got.String() != "struct {}" { 928 t.Errorf("Got: reflect.TypeOf(x) = %v. Want: struct {}", got) 929 } 930 }) 931 } 932 933 func TestCompositeLiterals(t *testing.T) { 934 type S struct{} 935 type SP *S 936 937 s1 := []*S{{}} 938 if got := reflect.TypeOf(s1[0]); got.String() != "*tests.S" { 939 t.Errorf("Got: reflect.TypeOf(s1[0]) = %v. Want: *tests.S", got) 940 } 941 942 s2 := []SP{{}} 943 if got := reflect.TypeOf(s2[0]); got.String() != "tests.SP" { 944 t.Errorf("Got: reflect.TypeOf(s2[0]) = %v. Want: tests.SP", got) 945 } 946 } 947 948 func TestFileSetSize(t *testing.T) { 949 type tokenFileSet struct { 950 // This type remained essentially consistent from go1.16 to go1.21. 951 mutex sync.RWMutex 952 base int 953 files []*token.File 954 _ *token.File // changed to atomic.Pointer[token.File] in go1.19 955 } 956 n1 := unsafe.Sizeof(tokenFileSet{}) 957 n2 := unsafe.Sizeof(token.FileSet{}) 958 if n1 != n2 { 959 t.Errorf("Got: unsafe.Sizeof(token.FileSet{}) %v, Want: %v", n2, n1) 960 } 961 }