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 }