github.com/Aoi-hosizora/ahlib@v1.5.1-0.20230404072829-241b93cf91c7/xreflect/xreflect_test.go (about) 1 package xreflect 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path" 8 "reflect" 9 "runtime" 10 _ "runtime" 11 "strings" 12 "testing" 13 "unsafe" 14 ) 15 16 func TestKindChecker(t *testing.T) { 17 for _, tc := range []struct { 18 giveKind reflect.Kind 19 wantIsInt bool 20 wantIsUint bool 21 wantIsFloat bool 22 wantIsComplex bool 23 wantIsNumeric bool 24 wantIsCollection bool 25 wantIsNillable bool 26 wantIsSlicable bool 27 wantIsPointerable bool 28 }{ 29 {reflect.Invalid, false, false, false, false, false, false, false, false, false}, 30 {reflect.Bool, false, false, false, false, false, false, false, false, false}, 31 {reflect.Int, true, false, false, false, true, false, false, false, false}, 32 {reflect.Int8, true, false, false, false, true, false, false, false, false}, 33 {reflect.Int16, true, false, false, false, true, false, false, false, false}, 34 {reflect.Int32, true, false, false, false, true, false, false, false, false}, 35 {reflect.Int64, true, false, false, false, true, false, false, false, false}, 36 {reflect.Uint, false, true, false, false, true, false, false, false, false}, 37 {reflect.Uint8, false, true, false, false, true, false, false, false, false}, 38 {reflect.Uint16, false, true, false, false, true, false, false, false, false}, 39 {reflect.Uint32, false, true, false, false, true, false, false, false, false}, 40 {reflect.Uint64, false, true, false, false, true, false, false, false, false}, 41 {reflect.Uintptr, false, true, false, false, true, false, false, false, false}, 42 {reflect.Float32, false, false, true, false, true, false, false, false, false}, 43 {reflect.Float64, false, false, true, false, true, false, false, false, false}, 44 {reflect.Complex64, false, false, false, true, true, false, false, false, false}, 45 {reflect.Complex128, false, false, false, true, true, false, false, false, false}, 46 {reflect.Array, false, false, false, false, false, true, false, true, false}, 47 {reflect.Chan, false, false, false, false, false, true, true, false, true}, 48 {reflect.Func, false, false, false, false, false, false, true, false, true}, 49 {reflect.Interface, false, false, false, false, false, false, true, false, false}, 50 {reflect.Map, false, false, false, false, false, true, true, false, true}, 51 {reflect.Ptr, false, false, false, false, false, false, true, false, true}, 52 {reflect.Slice, false, false, false, false, false, true, true, true, true}, 53 {reflect.String, false, false, false, false, false, true, false, true, false}, 54 {reflect.Struct, false, false, false, false, false, false, false, false, false}, 55 {reflect.UnsafePointer, false, false, false, false, false, false, true, false, true}, 56 } { 57 t.Run(tc.giveKind.String(), func(t *testing.T) { 58 xtestingEqual(t, IsIntKind(tc.giveKind), tc.wantIsInt) 59 xtestingEqual(t, IsUintKind(tc.giveKind), tc.wantIsUint) 60 xtestingEqual(t, IsFloatKind(tc.giveKind), tc.wantIsFloat) 61 xtestingEqual(t, IsComplexKind(tc.giveKind), tc.wantIsComplex) 62 xtestingEqual(t, IsNumericKind(tc.giveKind), tc.wantIsNumeric) 63 xtestingEqual(t, IsCollectionKind(tc.giveKind), tc.wantIsCollection) 64 xtestingEqual(t, IsNillableKind(tc.giveKind), tc.wantIsNillable) 65 xtestingEqual(t, IsSlicableKind(tc.giveKind), tc.wantIsSlicable) 66 xtestingEqual(t, IsPointerableKind(tc.giveKind), tc.wantIsPointerable) 67 }) 68 } 69 } 70 71 func TestValueChecker(t *testing.T) { 72 nonEmptyCh := make(chan int, 1) 73 nonEmptyCh <- 1 74 zeroIntPtr := (*int)(nil) 75 type t1 struct{ I int } 76 type t2 struct{ S string } 77 type t3 struct{ S t2 } 78 79 for _, tc := range []struct { 80 give interface{} 81 wantIsNil bool 82 wantIsZero bool 83 wantIsEmptyColl bool 84 wantIsEmpty bool 85 }{ 86 {0, false, true, false, true}, 87 {int8(0), false, true, false, true}, 88 {int16(0), false, true, false, true}, 89 {int32(0), false, true, false, true}, 90 {int64(0), false, true, false, true}, 91 {1, false, false, false, false}, 92 {int8(1), false, false, false, false}, 93 {int16(1), false, false, false, false}, 94 {int32(1), false, false, false, false}, 95 {int64(1), false, false, false, false}, 96 97 {uint(0), false, true, false, true}, 98 {uint8(0), false, true, false, true}, 99 {uint16(0), false, true, false, true}, 100 {uint32(0), false, true, false, true}, 101 {uint64(0), false, true, false, true}, 102 {uint(1), false, false, false, false}, 103 {uint8(1), false, false, false, false}, 104 {uint16(1), false, false, false, false}, 105 {uint32(1), false, false, false, false}, 106 {uint64(1), false, false, false, false}, 107 108 {0.0, false, true, false, true}, 109 {float32(0.0), false, true, false, true}, 110 {0.1, false, false, false, false}, 111 {float32(0.1), false, false, false, false}, 112 {0 + 0i, false, true, false, true}, 113 {complex64(0 + 0i), false, true, false, true}, 114 {0 + 1i, false, false, false, false}, 115 {complex64(0 + 1i), false, false, false, false}, 116 117 {false, false, true, false, true}, 118 {true, false, false, false, false}, 119 {"", false, true, true, true}, 120 {"x", false, false, false, false}, 121 {[]byte{}, false, false, true, true}, 122 {[]byte{'x'}, false, false, false, false}, 123 {[]rune{}, false, false, true, true}, 124 {[]rune{'x'}, false, false, false, false}, 125 126 {[0]int{}, false, true, true, true}, 127 {[1]int{}, false, true, false, false}, 128 {[]int(nil), true, true, true, true}, 129 {[]int{}, false, false, true, true}, 130 {[]int{0}, false, false, false, false}, 131 {map[int]int(nil), true, true, true, true}, 132 {map[int]int{}, false, false, true, true}, 133 {map[int]int{0: 0}, false, false, false, false}, 134 {(chan int)(nil), true, true, true, true}, 135 {make(chan int), false, false, true, true}, 136 {make(chan int, 1), false, false, true, true}, 137 {nonEmptyCh, false, false, false, false}, 138 {(chan<- int)(nil), true, true, true, true}, 139 {make(chan<- int), false, false, true, true}, 140 {make(chan<- int, 1), false, false, true, true}, 141 {(chan<- int)(nonEmptyCh), false, false, false, false}, 142 {(<-chan int)(nil), true, true, true, true}, 143 {make(<-chan int), false, false, true, true}, 144 {make(<-chan int, 1), false, false, true, true}, 145 {(<-chan int)(nonEmptyCh), false, false, false, false}, 146 147 {nil, true, true, false, true}, 148 {interface{}(nil), true, true, false, true}, 149 {fmt.Stringer(nil), true, true, false, true}, 150 {interface{}(fmt.Stringer(nil)), true, true, false, true}, 151 {(*int)(nil), true, true, false, true}, 152 {&zeroIntPtr, false, false, false, false}, 153 {(**int)(nil), true, true, false, true}, 154 {(*[1]int)(nil), true, true, false, true}, 155 {(*[]int)(nil), true, true, false, true}, 156 {(*map[int]int)(nil), true, true, false, true}, 157 {(*strings.Builder)(nil), true, true, false, true}, 158 {&strings.Builder{}, false, false, false, false}, 159 {fmt.Stringer(&strings.Builder{}), false, false, false, false}, 160 {strings.Builder{}, false, true, false, false}, 161 {unsafe.Pointer(nil), true, true, false, true}, 162 {uintptr(unsafe.Pointer(nil)), false, true, false, true}, 163 {unsafe.Pointer(new(int)), false, false, false, false}, 164 {uintptr(unsafe.Pointer(new(int))), false, false, false, false}, 165 {unsafe.Pointer((*strings.Builder)(nil)), true, true, false, true}, 166 {unsafe.Pointer(&strings.Builder{}), false, false, false, false}, 167 {uintptr(unsafe.Pointer(&strings.Builder{})), false, false, false, false}, 168 169 {(func())(nil), true, true, false, true}, 170 {(func() int)(nil), true, true, false, true}, 171 {func() {}, false, false, false, false}, 172 {func() int { return 0 }, false, false, false, false}, 173 {struct{}{}, false, true, false, true}, 174 {t1{}, false, true, false, false}, 175 {t1{0}, false, true, false, false}, 176 {t1{1}, false, false, false, false}, 177 {struct{ _ struct{} }{}, false, true, false, false}, 178 {t3{}, false, true, false, false}, 179 {t3{t2{""}}, false, true, false, false}, 180 {t3{t2{"x"}}, false, false, false, false}, 181 } { 182 t.Run(fmt.Sprintf("%#v", tc.give), func(t *testing.T) { 183 xtestingEqual(t, IsNilValue(tc.give), tc.wantIsNil) 184 xtestingEqual(t, IsZeroValue(tc.give), tc.wantIsZero) 185 xtestingEqual(t, IsEmptyCollection(tc.give), tc.wantIsEmptyColl) 186 xtestingEqual(t, IsEmptyValue(tc.give), tc.wantIsEmpty) 187 }) 188 } 189 } 190 191 func TestNumericValue(t *testing.T) { 192 for _, tc := range []struct { 193 give interface{} 194 wantF float64 195 wantU uint64 196 wantOk bool 197 }{ 198 {1, 1, 1, true}, 199 {int8(1), 1, 1, true}, 200 {int16(1), 1, 1, true}, 201 {int32(1), 1, 1, true}, 202 {int64(1), 1, 1, true}, 203 {uint(1), 1, 1, true}, 204 {uint8(1), 1, 1, true}, 205 {uint16(1), 1, 1, true}, 206 {uint32(1), 1, 1, true}, 207 {uint64(1), 1, 1, true}, 208 {uintptr(1), 1, 1, true}, 209 {float32(1.5), 1.5, 1, true}, 210 {1.5, 1.5, 1, true}, 211 212 {1 + 1i, 0, 0, false}, 213 {complex64(1 + 1i), 0, 0, false}, 214 {nil, 0, 0, false}, 215 {"", 0, 0, false}, 216 {[1]int{}, 0, 0, false}, 217 {[]uint{}, 0, 0, false}, 218 {map[string]int{}, 0, 0, false}, 219 {make(chan float64), 0, 0, false}, 220 {(*int)(nil), 0, 0, false}, 221 {fmt.Stringer(nil), 0, 0, false}, 222 {func() {}, 0, 0, false}, 223 } { 224 t.Run(fmt.Sprintf("%#v", tc.give), func(t *testing.T) { 225 f, fok := Float64Value(tc.give) 226 u, uok := Uint64Value(tc.give) 227 xtestingEqual(t, fok, tc.wantOk) 228 xtestingEqual(t, uok, tc.wantOk) 229 if tc.wantOk { 230 xtestingEqual(t, f, tc.wantF) 231 xtestingEqual(t, u, tc.wantU) 232 } 233 }) 234 } 235 } 236 237 func TestUnexportedField(t *testing.T) { 238 t.Run("trying", func(t *testing.T) { 239 type testStruct struct { 240 unexportedField int 241 } 242 aaa := &testStruct{unexportedField: 2} 243 244 // get or set on field's reflect.Value directly 245 fieldValue := reflect.ValueOf(aaa).Elem().FieldByName("unexportedField") 246 xtestingPanic(t, true, func() { _ = fieldValue.Interface() }) // reflect.Value.Interface: cannot return value obtained from unexported field or method 247 xtestingPanic(t, true, func() { fieldValue.Set(reflect.ValueOf(3)) }) // reflect: reflect.Value.Set using value obtained using unexported field 248 xtestingEqual(t, aaa.unexportedField, 2) 249 250 // get or set on field's new reflect.Value (use NewAt and Elem to get the right reflect.Value) 251 newFieldValue := reflect.NewAt(fieldValue.Type(), unsafe.Pointer(fieldValue.UnsafeAddr())).Elem() 252 xtestingPanic(t, false, func() { _ = newFieldValue.Interface() }) 253 xtestingPanic(t, false, func() { newFieldValue.Set(reflect.ValueOf(3)) }) 254 xtestingEqual(t, aaa.unexportedField, 3) 255 }) 256 257 type testStruct struct { 258 a string 259 b int64 260 c uint64 261 d float64 262 m map[int]int 263 s struct{ I int } 264 } 265 ts := &testStruct{} 266 val := reflect.ValueOf(ts).Elem() 267 268 t.Run("get/set directly", func(t *testing.T) { 269 // get 270 xtestingEqual(t, GetUnexportedField(val.FieldByName("a")).Interface(), "") 271 xtestingEqual(t, GetUnexportedField(val.FieldByName("b")).Interface(), int64(0)) 272 xtestingEqual(t, GetUnexportedField(val.FieldByName("c")).Interface(), uint64(0)) 273 xtestingEqual(t, GetUnexportedField(val.FieldByName("d")).Interface(), 0.0) 274 xtestingEqual(t, GetUnexportedField(val.FieldByName("m")).Interface(), map[int]int(nil)) 275 xtestingEqual(t, GetUnexportedField(val.FieldByName("s")).Interface(), struct{ I int }{}) 276 277 // set 278 xtestingPanic(t, false, func() { SetUnexportedField(val.FieldByName("a"), reflect.ValueOf("string")) }) 279 xtestingPanic(t, false, func() { SetUnexportedField(val.FieldByName("b"), reflect.ValueOf(int64(9223372036854775807))) }) 280 xtestingPanic(t, false, func() { SetUnexportedField(val.FieldByName("c"), reflect.ValueOf(uint64(18446744073709551615))) }) 281 xtestingPanic(t, false, func() { SetUnexportedField(val.FieldByName("d"), reflect.ValueOf(0.333)) }) 282 xtestingPanic(t, false, func() { SetUnexportedField(val.FieldByName("m"), reflect.ValueOf(map[int]int{0: 0, 1: 1})) }) 283 xtestingPanic(t, false, func() { SetUnexportedField(val.FieldByName("s"), reflect.ValueOf(struct{ I int }{2})) }) 284 285 // get again 286 xtestingEqual(t, ts.a, "string") 287 xtestingEqual(t, ts.b, int64(9223372036854775807)) 288 xtestingEqual(t, ts.c, uint64(18446744073709551615)) 289 xtestingEqual(t, ts.d, 0.333) 290 xtestingEqual(t, ts.m, map[int]int{0: 0, 1: 1}) 291 xtestingEqual(t, ts.s, struct{ I int }{2}) 292 xtestingEqual(t, GetUnexportedField(val.FieldByName("a")).Interface(), "string") 293 xtestingEqual(t, GetUnexportedField(val.FieldByName("b")).Interface(), int64(9223372036854775807)) 294 xtestingEqual(t, GetUnexportedField(val.FieldByName("c")).Interface(), uint64(18446744073709551615)) 295 xtestingEqual(t, GetUnexportedField(val.FieldByName("d")).Interface(), 0.333) 296 xtestingEqual(t, GetUnexportedField(val.FieldByName("m")).Interface(), map[int]int{0: 0, 1: 1}) 297 xtestingEqual(t, GetUnexportedField(val.FieldByName("m")).Len(), 2) 298 xtestingEqual(t, GetUnexportedField(val.FieldByName("m")).MapIndex(reflect.ValueOf(1)).Interface(), 1) 299 xtestingEqual(t, GetUnexportedField(val.FieldByName("s")).Interface(), struct{ I int }{2}) 300 xtestingEqual(t, GetUnexportedField(val.FieldByName("s")).NumField(), 1) 301 xtestingEqual(t, GetUnexportedField(val.FieldByName("s")).FieldByName("I").Interface(), 2) 302 }) 303 304 t.Run("get/set with FieldValueOf", func(t *testing.T) { 305 // set 306 xtestingPanic(t, false, func() { SetUnexportedField(FieldValueOf(ts, "a"), reflect.ValueOf("sss")) }) 307 xtestingPanic(t, false, func() { SetUnexportedField(FieldValueOf(ts, "b"), reflect.ValueOf(int64(-9223372036854775808))) }) 308 xtestingPanic(t, false, func() { SetUnexportedField(FieldValueOf(ts, "c"), reflect.ValueOf(uint64(999))) }) 309 xtestingPanic(t, false, func() { SetUnexportedField(FieldValueOf(ts, "d"), reflect.ValueOf(5.5)) }) 310 xtestingPanic(t, false, func() { SetUnexportedField(FieldValueOf(ts, "m"), reflect.ValueOf(map[int]int{0: -1, -3: 2})) }) 311 xtestingPanic(t, false, func() { SetUnexportedField(FieldValueOf(ts, "s"), reflect.ValueOf(struct{ I int }{3})) }) 312 313 // get 314 xtestingEqual(t, ts.a, "sss") 315 xtestingEqual(t, ts.b, int64(-9223372036854775808)) 316 xtestingEqual(t, ts.c, uint64(999)) 317 xtestingEqual(t, ts.d, 5.5) 318 xtestingEqual(t, ts.m, map[int]int{0: -1, -3: 2}) 319 xtestingEqual(t, ts.s, struct{ I int }{3}) 320 xtestingEqual(t, GetUnexportedField(FieldValueOf(ts, "a")).Interface(), "sss") 321 xtestingEqual(t, GetUnexportedField(FieldValueOf(ts, "b")).Interface(), int64(-9223372036854775808)) 322 xtestingEqual(t, GetUnexportedField(FieldValueOf(ts, "c")).Interface(), uint64(999)) 323 xtestingEqual(t, GetUnexportedField(FieldValueOf(ts, "d")).Interface(), 5.5) 324 xtestingEqual(t, GetUnexportedField(FieldValueOf(ts, "m")).Interface(), map[int]int{0: -1, -3: 2}) 325 xtestingEqual(t, GetUnexportedField(FieldValueOf(ts, "m")).Len(), 2) 326 xtestingEqual(t, GetUnexportedField(FieldValueOf(ts, "m")).MapIndex(reflect.ValueOf(-3)).Interface(), 2) 327 xtestingEqual(t, GetUnexportedField(val.FieldByName("s")).Interface(), struct{ I int }{3}) 328 xtestingEqual(t, GetUnexportedField(val.FieldByName("s")).NumField(), 1) 329 xtestingEqual(t, GetUnexportedField(val.FieldByName("s")).FieldByName("I").Interface(), 3) 330 }) 331 } 332 333 func TestFieldValueOf(t *testing.T) { 334 type testStruct struct { 335 A string 336 B int64 337 C uint64 338 D float64 339 M map[int]int 340 S struct{ I int } 341 } 342 sa := testStruct{A: "a"} 343 psb := &testStruct{B: -999} 344 psc := &testStruct{C: 1999} 345 ppsc := &psc 346 psd := &testStruct{D: 3.0} 347 ppsd := &psd 348 pppsd := &ppsd 349 pse := &testStruct{M: map[int]int{0: 0}} 350 ppse := &pse 351 pppse := &ppse 352 ppppse := &pppse 353 354 for _, tc := range []struct { 355 give interface{} 356 giveField string 357 wantPanic bool 358 wantValue interface{} 359 }{ 360 {nil, "", true, nil}, 361 {1, "", true, nil}, 362 {new(string), "", true, nil}, 363 {new(*int), "", true, nil}, 364 {new(**struct{}), "", true, nil}, 365 {struct{}{}, "", true, nil}, 366 367 {struct{ i int }{0}, "i", false, nil}, 368 {struct{ i uint32 }{1}, "i", false, nil}, 369 {struct{ I int }{1}, "I", false, 1}, 370 {struct{ I uint32 }{333}, "I", false, uint32(333)}, 371 {struct{ S string }{}, "a", true, nil}, // non-existence field 372 {struct { 373 _ string 374 }{}, "_", false, reflect.String}, 375 {struct { 376 _ int 377 _ uint 378 }{}, "_", false, reflect.Int}, 379 {struct { 380 _ [1]int 381 _ []int 382 _ map[int]int 383 }{}, "_", false, reflect.Array}, 384 385 {sa, "A", false, "a"}, 386 {psb, "B", false, int64(-999)}, 387 {ppsc, "C", false, uint64(1999)}, 388 {pppsd, "D", false, 3.0}, 389 {ppppse, "M", false, map[int]int{0: 0}}, 390 {testStruct{}, "S", false, struct{ I int }{}}, 391 {testStruct{}, "_", true, nil}, 392 } { 393 t.Run(fmt.Sprintf("%#v", tc.give), func(t *testing.T) { 394 if tc.wantPanic { 395 xtestingPanic(t, true, func() { FieldValueOf(tc.give, tc.giveField) }) 396 } else { 397 val := FieldValueOf(tc.give, tc.giveField) 398 if k, ok := tc.wantValue.(reflect.Kind); ok { 399 xtestingEqual(t, val.Kind(), k) 400 } else if tc.wantValue != nil { 401 xtestingEqual(t, val.Interface(), tc.wantValue) 402 } 403 } 404 }) 405 } 406 } 407 408 func TestHasZeroEface(t *testing.T) { 409 for _, tc := range []struct { 410 give interface{} 411 wantIsNil bool 412 wantIsZero bool 413 }{ 414 {nil, true, true}, // eface{_type:0x0, data:(unsafe.Pointer)(nil)} 415 {fmt.Stringer(nil), true, true}, // eface{_type:0x0, data:(unsafe.Pointer)(nil)} 416 {0, false, false}, 417 {"", false, false}, 418 {(*int)(nil), false, true}, // eface{_type:0x10d18c0, data:(unsafe.Pointer)(nil)} 419 {(func())(nil), false, true}, // eface{_type:0x10d5c00, data:(unsafe.Pointer)(nil)} 420 {unsafe.Pointer(nil), false, true}, // eface{_type:0x10d7540, data:(unsafe.Pointer)(nil)} 421 {new(fmt.Stringer), false, false}, // eface{_type:0x10d1380, data:(unsafe.Pointer)(0xc0000885e0)} 422 {new(*int), false, false}, // eface{_type:0x10d0980, data:(unsafe.Pointer)(0xc0000c4028)} 423 {new(func()), false, false}, // eface{_type:0x10d1400, data:(unsafe.Pointer)(0xc0000c4030)} 424 {new(unsafe.Pointer), false, false}, // eface{_type:0x10d4140, data:(unsafe.Pointer)(0xc0000c4038)} 425 {[]int(nil), false, false}, // eface{_type:0x10d4c80, data:(unsafe.Pointer)(0x125cd80)} 426 {map[int]int(nil), false, true}, // eface{_type:0x10dd920, data:(unsafe.Pointer)(nil)} 427 {(chan int)(nil), false, true}, // eface{_type:0x10d5ec0, data:(unsafe.Pointer)(nil)} 428 {new([]int), false, false}, // eface{_type:0x10d0c80, data:(unsafe.Pointer)(0xc00009c0d8)} 429 {new(map[int]int), false, false}, // eface{_type:0x10d1e40, data:(unsafe.Pointer)(0xc0000c4040)} 430 {new(chan int), false, false}, // eface{_type:0x10d0e40, data:(unsafe.Pointer)(0xc0000c4048)} 431 {make([]int, 0), false, false}, // eface{_type:0x10d4c80, data:(unsafe.Pointer)(0xc00009c0f0)} 432 {make(map[int]int), false, false}, // eface{_type:0x10dd920, data:(unsafe.Pointer)(0xc0000b8750)} 433 {make(chan int), false, false}, // eface{_type:0x10d5ec0, data:(unsafe.Pointer)(0xc0000862a0)} 434 } { 435 t.Run(fmt.Sprintf("%#v", tc.give), func(t *testing.T) { 436 // log.Printf("%#v", (*eface)(unsafe.Pointer(&tc.give))) 437 xtestingEqual(t, tc.give == nil, tc.wantIsNil) 438 xtestingEqual(t, HasZeroEface(tc.give), tc.wantIsZero) 439 }) 440 } 441 } 442 443 func TestDeepEqualWithoutType(t *testing.T) { 444 intOne := 1 445 pIntOne := &intOne 446 sb := strings.Builder{} 447 sb.WriteString("x") 448 449 for _, tc := range []struct { 450 give1 interface{} 451 give2 interface{} 452 want bool 453 }{ 454 {nil, nil, true}, 455 {nil, interface{}(nil), true}, 456 {fmt.Stringer(nil), nil, true}, 457 {(*int)(nil), nil, false}, 458 {(*int)(nil), (*uint64)(nil), false}, 459 {(*uint32)(nil), unsafe.Pointer((*uint32)(nil)), false}, // inconvertible ??? 460 {pIntOne, unsafe.Pointer(pIntOne), false}, // inconvertible ??? 461 {unsafe.Pointer(pIntOne), uintptr(unsafe.Pointer(pIntOne)), false}, // inconvertible ??? 462 {new(int), new(int), true}, 463 {pIntOne, (*int8)(unsafe.Pointer(uintptr(unsafe.Pointer(pIntOne)) + 1)), false}, 464 465 {10, uint32(10), true}, 466 {int32(100), uint64(100), true}, 467 {uint16(65535), int64(65535), true}, 468 {1.0, 1, true}, 469 {float32(0.5), 0.5, true}, 470 {uint8(3), float32(3.0), true}, 471 {"hello world", []byte("hello world"), true}, 472 {[]byte("hello golang"), "hello golang", true}, 473 {"测试 テスト", []rune("测试 テスト"), true}, 474 {[]rune("テスト 测试"), "テスト 测试", true}, 475 {[2]int{}, [2]int{0, 0}, true}, 476 {[1]float64{0}, [1]float64{}, true}, 477 {[]uint8{1, 2, 3}, []uint8{1, 2, 3}, true}, 478 {map[int]int{0: 1, 1: 0}, map[int]int{1: 0, 0: 1}, true}, 479 480 {10, uint32(11), false}, 481 {int32(101), uint64(100), false}, 482 {uint16(65535), int64(65536), false}, 483 {1.1, 1, true}, // <<< 484 {float32(0.5), 0.6, false}, 485 {uint8(4), float32(3.9), false}, 486 {"hello world", []byte("hello"), false}, 487 {[]byte("hello golang"), "golang", false}, 488 {"测试テスト", []rune("测试 テスト"), false}, 489 {[]rune("テスト测试"), "テスト 测试", false}, 490 {[2]int{}, [2]int{0, 1}, false}, 491 {[]float64{1}, [1]float64{}, false}, 492 {[]uint8{1, 2, 3}, []uint8{2, 1, 3}, false}, 493 {map[int]int{0: 1, 1: 0}, map[int]int{1: 1, 0: 0}, false}, 494 495 {10, nil, false}, 496 {pIntOne, 0, false}, 497 {"2", uint8(2), false}, 498 {int32(101), "101", false}, 499 {1.1, "1.1", false}, 500 {[]byte("hello world"), []rune("hello world"), false}, 501 {0.5, [1]float64{0.5}, false}, 502 {[2]int{}, []int{0, 0}, false}, 503 {[]float64{0}, [1]float64{}, false}, 504 {[]byte("abc"), []int{'a', 'b', 'c'}, false}, 505 {map[int]int{0: 1, 1: 0}, map[int]uint{1: 1, 0: 0}, false}, 506 507 {sb, sb, true}, 508 {&sb, sb, false}, 509 {fmt.Stringer(&sb), &sb, true}, 510 {&sb, fmt.Stringer(&sb), true}, 511 {fmt.Stringer(&sb), sb, false}, 512 {fmt.Stringer(&sb), fmt.Stringer(&sb), true}, 513 {&strings.Builder{}, &strings.Builder{}, true}, 514 {fmt.Stringer(&strings.Builder{}), &strings.Builder{}, true}, 515 {strings.Builder{}, "x", false}, 516 {errors.New("x"), fmt.Stringer(&sb), false}, 517 {fmt.Stringer(&sb), errors.New("x"), false}, 518 {func() {}, 1, false}, 519 {func() {}, func() {}, false}, 520 } { 521 t.Run(fmt.Sprintf("%v<->%v", tc.give1, tc.give2), func(t *testing.T) { 522 xtestingEqual(t, DeepEqualInValue(tc.give1, tc.give2), tc.want) 523 }) 524 } 525 } 526 527 func TestSameUnderlyingPointer(t *testing.T) { 528 p := new(int) 529 f := func() {} 530 u := unsafe.Pointer(new(bool)) 531 s := make([]string, 0) 532 m := map[string]interface{}{} 533 c := make(chan struct{}) 534 535 p2 := (*uint64)(unsafe.Pointer(p)) 536 p3 := (*int)((*struct{ data unsafe.Pointer })(unsafe.Pointer(&s)).data) 537 u2 := unsafe.Pointer(p) 538 u3 := (*struct{ data unsafe.Pointer })(unsafe.Pointer(&s)).data 539 s3 := *(*[]int)(unsafe.Pointer(&reflect.SliceHeader{Data: (*reflect.SliceHeader)(unsafe.Pointer(&s)).Data})) 540 f3 := *(*func() int)(unsafe.Pointer(&f)) 541 542 f2 := func() {} 543 s2 := make([]string, 1) 544 m2 := map[string]interface{}{"": nil} 545 c2 := make(chan struct{}) 546 547 for _, tc := range []struct { 548 give1 interface{} 549 give2 interface{} 550 giveKind reflect.Kind 551 wantSamePtr bool 552 wantSamePtrType bool 553 wantSamePtrTypeKind bool 554 }{ 555 {p, p, reflect.Ptr, true, true, true}, 556 {f, f, reflect.Func, true, true, true}, 557 {u, u, reflect.UnsafePointer, true, true, true}, 558 {s, s, reflect.Slice, true, true, true}, 559 {m, m, reflect.Map, true, true, true}, 560 {c, c, reflect.Chan, true, true, true}, 561 562 {1, 2, reflect.Int, false, false, false}, 563 {"1", 3.4, reflect.String, false, false, false}, 564 {nil, []string{}, reflect.Slice, false, false, false}, 565 {map[string]interface{}{}, nil, reflect.Map, false, false, false}, 566 {f, f2, reflect.Func, false, false, false}, 567 {s, s2, reflect.Slice, false, false, false}, 568 {m, m2, reflect.Map, false, false, false}, 569 {c, c2, reflect.Chan, false, false, false}, 570 571 {p, p, reflect.Int, true, true, false}, 572 {f, f, reflect.Ptr, true, true, false}, 573 {m, m, reflect.Slice, true, true, false}, 574 {c, c, reflect.Func, true, true, false}, 575 576 {p, p2, reflect.Ptr, true, false, false}, 577 {s, p3, reflect.Slice, true, false, false}, 578 {p, u2, reflect.Ptr, true, false, false}, 579 {s, u3, reflect.Slice, true, false, false}, 580 {s3, s, reflect.Slice, true, false, false}, 581 {f3, f, reflect.Func, true, false, false}, 582 } { 583 t.Run(fmt.Sprintf("%v<->%v", tc.give1, tc.give2), func(t *testing.T) { 584 xtestingEqual(t, SameUnderlyingPointer(tc.give1, tc.give2), tc.wantSamePtr) 585 xtestingEqual(t, SameUnderlyingPointerWithType(tc.give1, tc.give2), tc.wantSamePtrType) 586 xtestingEqual(t, SameUnderlyingPointerWithTypeAndKind(tc.give1, tc.give2, tc.giveKind), tc.wantSamePtrTypeKind) 587 }) 588 } 589 } 590 591 func TestGetMapBuckets(t *testing.T) { 592 b := GetMapB(map[int]int{}) 593 xtestingEqual(t, b, uint8(0)) 594 595 b, bt := GetMapBuckets(map[string]interface{}{}) 596 xtestingEqual(t, b, uint8(0)) 597 xtestingEqual(t, bt, uint64(1)) 598 599 xtestingPanic(t, true, func() { GetMapB(nil) }) 600 xtestingPanic(t, true, func() { GetMapB(0) }) 601 xtestingPanic(t, true, func() { GetMapBuckets(nil) }) 602 xtestingPanic(t, true, func() { GetMapBuckets(0) }) 603 604 xtestingPanic(t, false, func() { 605 for i := 0; i < 212; i++ { 606 b, bt = GetMapBuckets(make(map[string]int, i)) 607 // log.Println(i, b, bt) 608 } 609 }) 610 } 611 612 // ============================= 613 // simplified xtesting functions 614 // ============================= 615 616 func failTest(t testing.TB, failureMessage string) bool { 617 _, file, line, _ := runtime.Caller(2) 618 _, _ = fmt.Fprintf(os.Stderr, "%s:%d %s\n", path.Base(file), line, failureMessage) 619 t.Fail() 620 return false 621 } 622 623 func xtestingEqual(t testing.TB, give, want interface{}) bool { 624 if give != nil && want != nil && (reflect.TypeOf(give).Kind() == reflect.Func || reflect.TypeOf(want).Kind() == reflect.Func) { 625 return failTest(t, fmt.Sprintf("Equal: invalid operation `%#v` == `%#v` (cannot take func type as argument)", give, want)) 626 } 627 if !reflect.DeepEqual(give, want) { 628 return failTest(t, fmt.Sprintf("Equal: expect to be `%#v`, but actually was `%#v`", want, give)) 629 } 630 return true 631 } 632 633 func xtestingPanic(t *testing.T, want bool, f func(), v ...interface{}) bool { 634 isPanic, value := false, interface{}(nil) 635 func() { defer func() { value = recover(); isPanic = value != nil }(); f() }() 636 if want && !isPanic { 637 return failTest(t, fmt.Sprintf("Panic: expect function `%#v` to panic, but actually did not panic", interface{}(f))) 638 } 639 if want && isPanic && len(v) > 0 && v[0] != nil && !reflect.DeepEqual(value, v[0]) { 640 return failTest(t, fmt.Sprintf("PanicWithValue: expect function `%#v` to panic with `%#v`, but actually with `%#v`", interface{}(f), want, value)) 641 } 642 if !want && isPanic { 643 return failTest(t, fmt.Sprintf("NotPanic: expect function `%#v` not to panic, but actually panicked with `%v`", interface{}(f), value)) 644 } 645 return true 646 }