github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/natives/src/reflect/reflect_test.go (about)

     1  //go:build js
     2  // +build js
     3  
     4  package reflect_test
     5  
     6  import (
     7  	"math"
     8  	. "reflect"
     9  	"testing"
    10  )
    11  
    12  func TestAlignment(t *testing.T) {
    13  	t.Skip()
    14  }
    15  
    16  func TestSliceOverflow(t *testing.T) {
    17  	t.Skip()
    18  }
    19  
    20  func TestFuncLayout(t *testing.T) {
    21  	t.Skip()
    22  }
    23  
    24  func TestArrayOfDirectIface(t *testing.T) {
    25  	t.Skip()
    26  }
    27  
    28  func TestTypelinksSorted(t *testing.T) {
    29  	t.Skip()
    30  }
    31  
    32  func TestGCBits(t *testing.T) {
    33  	t.Skip()
    34  }
    35  
    36  func TestChanAlloc(t *testing.T) {
    37  	t.Skip()
    38  }
    39  
    40  func TestNameBytesAreAligned(t *testing.T) {
    41  	t.Skip()
    42  }
    43  
    44  func TestOffsetLock(t *testing.T) {
    45  	t.Skip()
    46  }
    47  
    48  func TestSelectOnInvalid(t *testing.T) {
    49  	Select([]SelectCase{
    50  		{
    51  			Dir:  SelectRecv,
    52  			Chan: Value{},
    53  		}, {
    54  			Dir:  SelectSend,
    55  			Chan: Value{},
    56  			Send: ValueOf(1),
    57  		}, {
    58  			Dir: SelectDefault,
    59  		},
    60  	})
    61  }
    62  
    63  func TestStructOfDirectIface(t *testing.T) {
    64  	t.Skip("reflect.Value.InterfaceData is not supported by GopherJS.")
    65  }
    66  
    67  func TestStructOfWithInterface(t *testing.T) {
    68  	// TODO(nevkontakte) Most of this test actually passes, but there is something
    69  	// about embedding fields with methods that can or can't be stored in an
    70  	// interface value directly that GopherJS does differently from upstream. As
    71  	// a result, GopherJS's implementation of StructOf() doesn't panic where
    72  	// upstream does. It seems to be a result of our implementation not propagating
    73  	// the kindDirectIface flag in struct types created by StructOf(), but at this
    74  	// point I wasn't able to figure out what that flag actually means in the
    75  	// GopherJS context or how it maps onto our own reflection implementation.
    76  	t.Skip("GopherJS doesn't support storing types directly in interfaces.")
    77  }
    78  
    79  var deepEqualTests = []DeepEqualTest{
    80  	// Equalities
    81  	{nil, nil, true},
    82  	{1, 1, true},
    83  	{int32(1), int32(1), true},
    84  	{0.5, 0.5, true},
    85  	{float32(0.5), float32(0.5), true},
    86  	{"hello", "hello", true},
    87  	{make([]int, 10), make([]int, 10), true},
    88  	{&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},
    89  	{Basic{1, 0.5}, Basic{1, 0.5}, true},
    90  	{error(nil), error(nil), true},
    91  	{map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true},
    92  	{fn1, fn2, true},
    93  
    94  	// Inequalities
    95  	{1, 2, false},
    96  	{int32(1), int32(2), false},
    97  	{0.5, 0.6, false},
    98  	{float32(0.5), float32(0.6), false},
    99  	{"hello", "hey", false},
   100  	{make([]int, 10), make([]int, 11), false},
   101  	{&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false},
   102  	{Basic{1, 0.5}, Basic{1, 0.6}, false},
   103  	{Basic{1, 0}, Basic{2, 0}, false},
   104  	{map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false},
   105  	{map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false},
   106  	{map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false},
   107  	{map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false},
   108  	{nil, 1, false},
   109  	{1, nil, false},
   110  	{fn1, fn3, false},
   111  	{fn3, fn3, false},
   112  	{[][]int{{1}}, [][]int{{2}}, false},
   113  	{math.NaN(), math.NaN(), false},
   114  	{&[1]float64{math.NaN()}, &[1]float64{math.NaN()}, false},
   115  	{&[1]float64{math.NaN()}, self{}, true},
   116  	{[]float64{math.NaN()}, []float64{math.NaN()}, false},
   117  	{[]float64{math.NaN()}, self{}, true},
   118  	{map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false},
   119  	{map[float64]float64{math.NaN(): 1}, self{}, true},
   120  
   121  	// Nil vs empty: not the same.
   122  	{[]int{}, []int(nil), false},
   123  	{[]int{}, []int{}, true},
   124  	{[]int(nil), []int(nil), true},
   125  	{map[int]int{}, map[int]int(nil), false},
   126  	{map[int]int{}, map[int]int{}, true},
   127  	{map[int]int(nil), map[int]int(nil), true},
   128  
   129  	// Mismatched types
   130  	{1, 1.0, false},
   131  	{int32(1), int64(1), false},
   132  	{0.5, "hello", false},
   133  	{[]int{1, 2, 3}, [3]int{1, 2, 3}, false},
   134  	{&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false},
   135  	{Basic{1, 0.5}, NotBasic{1, 0.5}, false},
   136  	{map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
   137  
   138  	// Possible loops.
   139  	{&loop1, &loop1, true},
   140  	//{&loop1, &loop2, true}, // TODO: Fix.
   141  	{&loopy1, &loopy1, true},
   142  	//{&loopy1, &loopy2, true}, // TODO: Fix.
   143  }
   144  
   145  // TODO: Fix this. See https://github.com/gopherjs/gopherjs/issues/763.
   146  func TestIssue22073(t *testing.T) {
   147  	m := ValueOf(NonExportedFirst(0)).Method(0)
   148  
   149  	if got := m.Type().NumOut(); got != 0 {
   150  		t.Errorf("NumOut: got %v, want 0", got)
   151  	}
   152  
   153  	// TODO: Fix this. The call below fails with:
   154  	//
   155  	// 	var $call = function(fn, rcvr, args) { return fn.apply(rcvr, args); };
   156  	// 	                                                 ^
   157  	// 	TypeError: Cannot read property 'apply' of undefined
   158  
   159  	// Shouldn't panic.
   160  	// m.Call(nil)
   161  }
   162  
   163  func TestCallReturnsEmpty(t *testing.T) {
   164  	t.Skip("test uses runtime.SetFinalizer, which is not supported by GopherJS")
   165  }
   166  
   167  func init() {
   168  	// TODO: This is a failure in 1.11, try to determine the cause and fix.
   169  	typeTests = append(typeTests[:31], typeTests[32:]...) // skip test case #31
   170  }
   171  
   172  func TestConvertNaNs(t *testing.T) {
   173  	// This test is exactly the same as the upstream, except it uses a "quiet NaN"
   174  	// value instead of "signalling NaN". JavaScript appears to coerce all NaNs
   175  	// into quiet ones, but for the purpose of this test either is fine.
   176  
   177  	const qnan uint32 = 0x7fc00001 // Originally: 0x7f800001.
   178  	type myFloat32 float32
   179  	x := V(myFloat32(math.Float32frombits(qnan)))
   180  	y := x.Convert(TypeOf(float32(0)))
   181  	z := y.Interface().(float32)
   182  	if got := math.Float32bits(z); got != qnan {
   183  		t.Errorf("quiet nan conversion got %x, want %x", got, qnan)
   184  	}
   185  }
   186  
   187  func TestMapIterSet(t *testing.T) {
   188  	m := make(map[string]any, len(valueTests))
   189  	for _, tt := range valueTests {
   190  		m[tt.s] = tt.i
   191  	}
   192  	v := ValueOf(m)
   193  
   194  	k := New(v.Type().Key()).Elem()
   195  	e := New(v.Type().Elem()).Elem()
   196  
   197  	iter := v.MapRange()
   198  	for iter.Next() {
   199  		k.SetIterKey(iter)
   200  		e.SetIterValue(iter)
   201  		want := m[k.String()]
   202  		got := e.Interface()
   203  		if got != want {
   204  			t.Errorf("%q: want (%T) %v, got (%T) %v", k.String(), want, want, got, got)
   205  		}
   206  		if setkey, key := valueToString(k), valueToString(iter.Key()); setkey != key {
   207  			t.Errorf("MapIter.Key() = %q, MapIter.SetKey() = %q", key, setkey)
   208  		}
   209  		if setval, val := valueToString(e), valueToString(iter.Value()); setval != val {
   210  			t.Errorf("MapIter.Value() = %q, MapIter.SetValue() = %q", val, setval)
   211  		}
   212  	}
   213  
   214  	// Upstream test also tests allocations made by the iterator. GopherJS doesn't
   215  	// support runtime.ReadMemStats(), so we leave that part out.
   216  }
   217  
   218  type inner struct {
   219  	x int
   220  }
   221  
   222  type outer struct {
   223  	y int
   224  	inner
   225  }
   226  
   227  func (*inner) M() int { return 1 }
   228  func (*outer) M() int { return 2 }
   229  
   230  func TestNestedMethods(t *testing.T) {
   231  	// This test is similar to the upstream, but avoids using the unsupported
   232  	// Value.UnsafePointer() method.
   233  	typ := TypeOf((*outer)(nil))
   234  	args := []Value{
   235  		ValueOf((*outer)(nil)), // nil receiver
   236  	}
   237  	if typ.NumMethod() != 1 {
   238  		t.Errorf("Wrong method table for outer, found methods:")
   239  		for i := 0; i < typ.NumMethod(); i++ {
   240  			m := typ.Method(i)
   241  			t.Errorf("\t%d: %s\n", i, m.Name)
   242  		}
   243  	}
   244  	if got := typ.Method(0).Func.Call(args)[0]; got.Int() != 2 {
   245  		t.Errorf("Wrong method table for outer, expected return value 2, got: %v", got)
   246  	}
   247  	if got := ValueOf((*outer).M).Call(args)[0]; got.Int() != 2 {
   248  		t.Errorf("Wrong method table for outer, expected return value 2, got: %v", got)
   249  	}
   250  }
   251  
   252  func TestEmbeddedMethods(t *testing.T) {
   253  	// This test is similar to the upstream, but avoids using the unsupported
   254  	// Value.UnsafePointer() method.
   255  	typ := TypeOf((*OuterInt)(nil))
   256  	if typ.NumMethod() != 1 {
   257  		t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M)
   258  		for i := 0; i < typ.NumMethod(); i++ {
   259  			m := typ.Method(i)
   260  			t.Errorf("\t%d: %s %p\n", i, m.Name, m.Func.UnsafePointer())
   261  		}
   262  	}
   263  
   264  	i := &InnerInt{3}
   265  	if v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 {
   266  		t.Errorf("i.M() = %d, want 3", v)
   267  	}
   268  
   269  	o := &OuterInt{1, InnerInt{2}}
   270  	if v := ValueOf(o).Method(0).Call(nil)[0].Int(); v != 2 {
   271  		t.Errorf("i.M() = %d, want 2", v)
   272  	}
   273  
   274  	f := (*OuterInt).M
   275  	if v := f(o); v != 2 {
   276  		t.Errorf("f(o) = %d, want 2", v)
   277  	}
   278  }
   279  
   280  func TestNotInHeapDeref(t *testing.T) {
   281  	t.Skip("GopherJS doesn't support //go:notinheap")
   282  }
   283  
   284  func TestMethodCallValueCodePtr(t *testing.T) {
   285  	t.Skip("methodValueCallCodePtr() is not applicable in GopherJS")
   286  }
   287  
   288  //gopherjs:purge for go1.19 without generics
   289  type (
   290  	A        struct{}
   291  	B[T any] struct{}
   292  )
   293  
   294  func TestIssue50208(t *testing.T) {
   295  	t.Skip("This test required generics, which are not yet supported: https://github.com/gopherjs/gopherjs/issues/1013")
   296  }
   297  
   298  func TestStructOfTooLarge(t *testing.T) {
   299  	t.Skip("This test is dependent on field alignment to determine if a struct size would exceed virtual address space.")
   300  }