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  }