github.com/goplus/reflectx@v1.2.2/reflectx_test.go (about) 1 package reflectx_test 2 3 import ( 4 "bytes" 5 "fmt" 6 "reflect" 7 "runtime" 8 "testing" 9 "unsafe" 10 11 "github.com/goplus/reflectx" 12 ) 13 14 type nPoint struct { 15 x int 16 y int 17 } 18 19 func TestFieldCanSet(t *testing.T) { 20 x := &nPoint{10, 20} 21 v := reflect.ValueOf(x).Elem() 22 23 sf := v.Field(0) 24 if sf.CanSet() { 25 t.Fatal("x unexport cannot set") 26 } 27 28 sf = reflectx.CanSet(sf) 29 if !sf.CanSet() { 30 t.Fatal("CanSet failed") 31 } 32 33 sf.Set(reflect.ValueOf(201)) 34 if x.x != 201 { 35 t.Fatalf("x value %v", x.x) 36 } 37 sf.SetInt(202) 38 if x.x != 202 { 39 t.Fatalf("x value %v", x.x) 40 } 41 } 42 43 type Rect struct { 44 pt1 nPoint 45 pt2 *nPoint 46 } 47 48 func TestField(t *testing.T) { 49 x := &Rect{nPoint{1, 2}, &nPoint{3, 4}} 50 v := reflect.ValueOf(x).Elem() 51 reflectx.Field(v, 0).Set(reflect.ValueOf(nPoint{10, 20})) 52 if x.pt1.x != 10 || x.pt1.y != 20 { 53 t.Fatalf("pt1 %v", x.pt1) 54 } 55 reflectx.FieldByName(v, "pt2").Set(reflect.ValueOf(&nPoint{30, 40})) 56 if x.pt2.x != 30 || x.pt2.y != 40 { 57 t.Fatalf("pt2 %v", x.pt2) 58 } 59 reflectx.FieldByNameFunc(v, func(name string) bool { 60 return name == "pt2" 61 }).Set(reflect.ValueOf(&nPoint{50, 60})) 62 if x.pt2.x != 50 || x.pt2.y != 60 { 63 t.Fatalf("pt2 %v", x.pt2) 64 } 65 reflectx.FieldByIndex(v, []int{0, 1}).SetInt(100) 66 if x.pt1.y != 100 { 67 t.Fatalf("pt1.y %v", x.pt1) 68 } 69 } 70 71 func TestFieldX(t *testing.T) { 72 x := &Rect{nPoint{1, 2}, &nPoint{3, 4}} 73 v := reflect.ValueOf(x).Elem() 74 reflectx.FieldX(v, 0).Set(reflect.ValueOf(nPoint{10, 20})) 75 if x.pt1.x != 10 || x.pt1.y != 20 { 76 t.Fatalf("pt1 %v", x.pt1) 77 } 78 reflectx.FieldByNameX(v, "pt2").Set(reflect.ValueOf(&nPoint{30, 40})) 79 if x.pt2.x != 30 || x.pt2.y != 40 { 80 t.Fatalf("pt2 %v", x.pt2) 81 } 82 reflectx.FieldByNameFuncX(v, func(name string) bool { 83 return name == "pt2" 84 }).Set(reflect.ValueOf(&nPoint{50, 60})) 85 if x.pt2.x != 50 || x.pt2.y != 60 { 86 t.Fatalf("pt2 %v", x.pt2) 87 } 88 reflectx.FieldByIndexX(v, []int{0, 1}).SetInt(100) 89 if x.pt1.y != 100 { 90 t.Fatalf("pt1.y %v", x.pt1) 91 } 92 } 93 94 func TestStructOfUnderscore(t *testing.T) { 95 fs := []reflect.StructField{ 96 reflect.StructField{ 97 Name: "_", 98 PkgPath: "main", 99 Type: tyInt, 100 }, 101 reflect.StructField{ 102 Name: "_", 103 PkgPath: "main", 104 Type: tyInt, 105 }, 106 } 107 typ := reflectx.NamedStructOf("main", "Point", fs) 108 if typ.Field(0).Name != "_" { 109 t.Fatalf("field name must underscore") 110 } 111 if typ.Field(1).Name != "_" { 112 t.Fatalf("field name must underscore") 113 } 114 } 115 116 func TestStructOfExport(t *testing.T) { 117 fs := []reflect.StructField{ 118 reflect.StructField{ 119 Name: "x", 120 PkgPath: "main", 121 Type: tyInt, 122 }, 123 reflect.StructField{ 124 Name: "y", 125 PkgPath: "main", 126 Type: tyInt, 127 }, 128 } 129 typ := reflectx.NamedStructOf("main", "Point", fs) 130 v := reflect.New(typ).Elem() 131 reflectx.FieldByIndex(v, []int{0}).SetInt(100) 132 reflectx.FieldByIndex(v, []int{1}).SetInt(200) 133 if s := fmt.Sprint(v); s != "{100 200}" { 134 t.Fatalf("have %v, want {100 200}", s) 135 } 136 } 137 138 type Buffer struct { 139 *bytes.Buffer 140 size int 141 value reflect.Value 142 *bytes.Reader 143 } 144 145 func TestStructOf(t *testing.T) { 146 defer func() { 147 v := recover() 148 if v != nil { 149 t.Fatalf("reflectx.StructOf %v", v) 150 } 151 }() 152 typ := reflect.TypeOf((*Buffer)(nil)).Elem() 153 var fs []reflect.StructField 154 for i := 0; i < typ.NumField(); i++ { 155 fs = append(fs, typ.Field(i)) 156 } 157 dst := reflectx.StructOf(fs) 158 for i := 0; i < dst.NumField(); i++ { 159 if dst.Field(i).Anonymous != fs[i].Anonymous { 160 t.Errorf("error field %v", dst.Field(i)) 161 } 162 } 163 164 v := reflect.New(dst) 165 v.Elem().Field(0).Set(reflect.ValueOf(bytes.NewBufferString("hello"))) 166 reflectx.CanSet(v.Elem().Field(1)).SetInt(100) 167 } 168 169 func TestNamedStruct(t *testing.T) { 170 fs := []reflect.StructField{ 171 reflect.StructField{Name: "X", Type: reflect.TypeOf(0)}, 172 reflect.StructField{Name: "Y", Type: reflect.TypeOf(0)}, 173 } 174 t1 := reflect.StructOf(fs) 175 t2 := reflect.StructOf(fs) 176 if t1 != t2 { 177 t.Fatalf("reflect.StructOf %v != %v", t1, t2) 178 } 179 t3 := reflectx.NamedStructOf("github.com/goplus/reflectx_test", "Point", fs) 180 t4 := reflectx.NamedStructOf("github.com/goplus/reflectx_test", "Point2", fs) 181 if t3 == t4 { 182 t.Fatalf("NamedStructOf %v == %v", t3, t4) 183 } 184 if t4.String() != "reflectx_test.Point2" { 185 t.Fatalf("t4.String=%v", t4.String()) 186 } 187 if t4.Name() != "Point2" { 188 t.Fatalf("t4.Name=%v", t4.Name()) 189 } 190 if t4.PkgPath() != "github.com/goplus/reflectx_test" { 191 t.Fatalf("t4.PkgPath=%v", t4.PkgPath()) 192 } 193 } 194 195 var ( 196 ch = make(chan bool) 197 fn = func(int, string) (bool, int) { 198 return true, 0 199 } 200 fn2 = func(*nPoint, int, bool, []byte) int { 201 return 0 202 } 203 testNamedValue = []interface{}{ 204 true, 205 false, 206 int(2), 207 int8(3), 208 int16(4), 209 int32(5), 210 int64(6), 211 uint(7), 212 uint8(8), 213 uint16(9), 214 uint32(10), 215 uint64(11), 216 uintptr(12), 217 float32(13), 218 float64(14), 219 complex64(15), 220 complex128(16), 221 "hello", 222 unsafe.Pointer(nil), 223 unsafe.Pointer(&fn), 224 []byte("hello"), 225 []int{1, 2, 3}, 226 [5]byte{'a', 'b', 'c', 'd', 'e'}, 227 [5]int{1, 2, 3, 4, 5}, 228 []string{"a", "b"}, 229 []int{100, 200}, 230 map[int]string{1: "hello", 2: "world"}, 231 new(uint8), 232 &fn, 233 &fn2, 234 &ch, 235 ch, 236 fn, 237 fn2, 238 } 239 ) 240 241 func TestNamedType(t *testing.T) { 242 pkgpath := "github.com/goplus/reflectx" 243 for i, v := range testNamedValue { 244 value := reflect.ValueOf(v) 245 typ := value.Type() 246 nt := reflectx.NamedTypeOf("github.com/goplus/reflectx", fmt.Sprintf("MyType%v", i), typ) 247 if nt.Kind() != typ.Kind() { 248 t.Errorf("kind: have %v, want %v", nt.Kind(), typ.Kind()) 249 } 250 if nt == typ { 251 t.Errorf("same type, %v", typ) 252 } 253 name := fmt.Sprintf("My_Type%v", i) 254 nt2 := reflectx.NamedTypeOf(pkgpath, name, typ) 255 if nt == nt2 { 256 t.Errorf("same type, %v", nt) 257 } 258 nv := reflect.New(nt).Elem() 259 reflectx.SetValue(nv, value) // 260 s1 := fmt.Sprint((nv)) 261 s2 := fmt.Sprint(v) 262 if s1 != s2 { 263 t.Errorf("%v: have %v, want %v", nt.Kind(), s1, s2) 264 } 265 if nt2.Name() != name { 266 t.Errorf("name: have %v, want %v", nt2.Name(), name) 267 } 268 if nt2.PkgPath() != pkgpath { 269 t.Errorf("pkgpath: have %v, want %v", nt2.PkgPath(), pkgpath) 270 } 271 } 272 } 273 274 var testInterfaceType = []reflect.Type{ 275 reflect.TypeOf((*interface{})(nil)).Elem(), 276 reflect.TypeOf((*fmt.Stringer)(nil)).Elem(), 277 reflect.TypeOf((*interface { 278 Read(p []byte) (n int, err error) 279 Write(p []byte) (n int, err error) 280 Close() error 281 })(nil)), 282 } 283 284 func TestNamedInterface(t *testing.T) { 285 pkgpath := "main" 286 for i, styp := range testInterfaceType { 287 name := fmt.Sprintf("T%v", i) 288 typ := reflectx.NamedTypeOf(pkgpath, name, styp) 289 if typ.Name() != name { 290 t.Errorf("name: have %v, want %v", typ.Name(), name) 291 } 292 if typ.PkgPath() != pkgpath { 293 t.Errorf("pkgpath: have %v, want %v", typ.PkgPath(), pkgpath) 294 } 295 if typ.NumMethod() != styp.NumMethod() { 296 t.Errorf("num method: have %v, want %v", typ.NumMethod(), styp.NumMethod()) 297 } 298 for i := 0; i < typ.NumMethod(); i++ { 299 if typ.Method(i) != styp.Method(i) { 300 t.Errorf("method: have %v, want %v", typ.Method(i), styp.Method(i)) 301 } 302 } 303 if !typ.ConvertibleTo(styp) { 304 t.Errorf("%v cannot ConvertibleTo %v", typ, styp) 305 } 306 if !styp.ConvertibleTo(typ) { 307 t.Errorf("%v cannot ConvertibleTo %v", styp, typ) 308 } 309 } 310 } 311 312 func TestNamedTypeStruct(t *testing.T) { 313 typ := reflect.TypeOf((*nPoint)(nil)).Elem() 314 pkgpath := typ.PkgPath() 315 nt := reflectx.NamedTypeOf(pkgpath, "MyPoint", typ) 316 nt2 := reflectx.NamedTypeOf(pkgpath, "MyPoint2", typ) 317 if nt.NumField() != typ.NumField() { 318 t.Fatal("NumField != 2", nt.NumField()) 319 } 320 if nt.Name() != "MyPoint" { 321 t.Fatal("Name != MyPoint", nt.Name()) 322 } 323 if nt == nt2 { 324 t.Fatalf("same type %v", nt) 325 } 326 v := reflect.New(nt).Elem() 327 reflectx.Field(v, 0).SetInt(100) 328 reflectx.Field(v, 1).SetInt(200) 329 if v.FieldByName("x").Int() != 100 || v.FieldByName("y").Int() != 200 { 330 t.Fatal("Value != {100 200},", v) 331 } 332 } 333 334 func TestSetElem(t *testing.T) { 335 if runtime.Compiler == "gopherjs" { 336 t.Skip("skip gopherjs") 337 } 338 typ := reflectx.NamedTypeOf("main", "T", reflect.TypeOf(([]struct{})(nil))) 339 reflectx.SetElem(typ, typ) 340 v := reflect.MakeSlice(typ, 3, 3) 341 v.Index(0).Set(reflect.MakeSlice(typ, 1, 1)) 342 v.Index(1).Set(reflect.MakeSlice(typ, 2, 2)) 343 s := fmt.Sprintf("%v", v.Interface()) 344 if s != "[[[]] [[] []] []]" { 345 t.Fatalf("failed SetElem s=%v", s) 346 } 347 } 348 349 func TestNamedStructComparable(t *testing.T) { 350 if runtime.Compiler == "gopherjs" { 351 t.Skip("skip gopherjs") 352 } 353 fs := []reflect.StructField{ 354 reflect.StructField{Name: "_", PkgPath: "main", Type: reflect.TypeOf(0)}, 355 reflect.StructField{Name: "x", PkgPath: "main", Type: reflect.TypeOf(0)}, 356 } 357 typ := reflectx.NamedStructOf("main", "blankStruct", fs) 358 v1 := reflect.New(typ).Elem() 359 reflectx.Field(v1, 0).SetInt(100) 360 reflectx.Field(v1, 1).SetInt(200) 361 v2 := reflect.New(typ).Elem() 362 reflectx.Field(v2, 0).SetInt(-100) 363 reflectx.Field(v2, 1).SetInt(200) 364 if v1.Interface() != v2.Interface() { 365 t.Fatal("failed struct equal") 366 } 367 } 368 369 func TestNamedStructUncomparable(t *testing.T) { 370 fs := []reflect.StructField{ 371 reflect.StructField{Name: "_", PkgPath: "main", Type: reflect.TypeOf(0)}, 372 reflect.StructField{Name: "fn", PkgPath: "main", Type: reflect.TypeOf(func() {})}, 373 } 374 typ := reflectx.NamedStructOf("main", "funcStruct", fs) 375 v1 := reflect.New(typ).Elem() 376 v2 := reflect.New(typ).Elem() 377 defer func() { 378 if err := recover(); err == nil { 379 t.Fatal("must panic comparing uncomparable type") 380 } 381 }() 382 if v1.Interface() == v2.Interface() { 383 t.Fatal("must panic") 384 } 385 } 386 387 type point struct { 388 x int 389 y int 390 } 391 392 func (p *point) Set(x, y int) { 393 p.x, p.y = x, y 394 } 395 396 func (p *point) mset(x, y int) { 397 p.x, p.y = x, y 398 } 399 400 func (p *point) String() string { 401 return fmt.Sprintf("(%v,%v)", p.x, p.y) 402 } 403 404 func TestMethodX(t *testing.T) { 405 typ := reflect.TypeOf((*point)(nil)) 406 if n := reflectx.NumMethodX(typ); n != 3 { 407 t.Fatalf("all method got: %v, want 3", n) 408 } 409 if m, ok := reflectx.MethodByName(typ, "mset"); !ok || m.Name != "mset" { 410 t.Fatalf("failed lookup method mset %v\n", m) 411 } 412 }