github.com/andeya/ameda@v1.5.3/value_test.go (about) 1 package ameda 2 3 import ( 4 "reflect" 5 "runtime" 6 "testing" 7 "time" 8 "unsafe" 9 10 "github.com/stretchr/testify/assert" 11 12 time2 "github.com/andeya/ameda/test/time" 13 ) 14 15 func TestCheckGoVersion(t *testing.T) { 16 defer func() { errValueUsable = nil }() 17 errValueUsable = checkGoVersion(runtime.Version()) 18 assert.NoError(t, errValueUsable) 19 20 errValueUsable = checkGoVersion("go1.15") 21 assert.NoError(t, errValueUsable) 22 23 errValueUsable = checkGoVersion("go1.15rc1") 24 assert.NoError(t, errValueUsable) 25 26 errValueUsable = checkGoVersion("devel go1.19-721e999423 Mon May 30 14:13:55 2022 +0800") 27 assert.NoError(t, errValueUsable) 28 29 errValueUsable = checkGoVersion("go2.15rc1") 30 assert.EqualError(t, errValueUsable, "ameda Value: required go<2.0, but current version is 'go2.15rc1'") 31 32 errValueUsable = checkGoVersion("devel go2.19-721e999423 Mon May 30 14:13:55 2022 +0800") 33 assert.EqualError(t, errValueUsable, "ameda Value: required go<2.0, but current version is 'devel go2.19-721e999423 Mon May 30 14:13:55 2022 +0800'") 34 } 35 36 func TestRuntimeTypeID(t *testing.T) { 37 arrayEqual(t, 38 RuntimeTypeIDOf(time.Time{}), RuntimeTypeID(reflect.TypeOf(time.Now())), ValueOf(time.Now()).RuntimeTypeID(), ValueFrom(reflect.ValueOf(time.Now())).RuntimeTypeID(), 39 ) 40 arrayEqual(t, 41 RuntimeTypeIDOf(&time.Time{}), RuntimeTypeID(reflect.TypeOf(&time.Time{})), ValueOf(&time.Time{}).RuntimeTypeID(), ValueFrom(reflect.ValueOf(&time.Time{})).RuntimeTypeID(), 42 ) 43 arrayEqual(t, 44 RuntimeTypeIDOf(time2.Time{}), RuntimeTypeID(reflect.TypeOf(time2.Time{S: 2})), ValueOf(time2.Time{S: 3}).RuntimeTypeID(), ValueFrom(reflect.ValueOf(time2.Time{S: 4})).RuntimeTypeID(), 45 ) 46 arrayEqual(t, 47 RuntimeTypeIDOf(&time2.Time{}), RuntimeTypeID(reflect.TypeOf(&time2.Time{S: 2})), ValueOf(&time2.Time{S: 3}).RuntimeTypeID(), ValueFrom(reflect.ValueOf(&time2.Time{S: 4})).RuntimeTypeID(), 48 ) 49 arrayNotEqual(t, RuntimeTypeIDOf(time.Time{}), RuntimeTypeIDOf(&time.Time{}), RuntimeTypeIDOf(time2.Time{}), RuntimeTypeIDOf(&time2.Time{})) 50 } 51 52 func arrayEqual(t assert.TestingT, expected interface{}, actual ...interface{}) { 53 if len(actual) == 0 { 54 actual = append(actual, nil) 55 } 56 for i, a := range actual { 57 assert.Equal(t, expected, a, i) 58 } 59 } 60 func arrayNotEqual(t assert.TestingT, values ...interface{}) { 61 if len(values) <= 1 { 62 return 63 } 64 for i, a := range values { 65 for ii, aa := range values[i+1:] { 66 assert.NotEqual(t, a, aa, []int{i, ii}) 67 } 68 } 69 } 70 71 func TestRuntimeTypeIDOf(t *testing.T) { 72 type T1 struct { 73 _ int 74 } 75 tid := RuntimeTypeIDOf(new(T1)) 76 t.Log(tid) 77 assert.Equal(t, RuntimeTypeID(reflect.TypeOf(new(T1))), tid) 78 tid2 := RuntimeTypeIDOf(T1{}) 79 assert.NotEqual(t, tid, tid2) 80 } 81 82 func TestKind(t *testing.T) { 83 type X struct { 84 A int16 85 B string 86 } 87 var x X 88 if ValueOf(&x).Kind() != reflect.Ptr { 89 t.FailNow() 90 } 91 92 if ValueOf(&x).UnderlyingElem().Kind() != reflect.Struct { 93 t.FailNow() 94 } 95 96 if ValueOf(x).Kind() != reflect.Struct { 97 t.FailNow() 98 } 99 if ValueOf(x).UnderlyingElem().Kind() != reflect.Struct { 100 t.FailNow() 101 } 102 103 f := func() {} 104 if ValueOf(f).Kind() != reflect.Func { 105 t.FailNow() 106 } 107 108 if ValueOf(t.Name).Kind() != reflect.Func { 109 t.FailNow() 110 } 111 if ValueOf(nil).Kind() != reflect.Invalid { 112 t.FailNow() 113 } 114 if ValueOf(nil).CanAddr() { 115 t.FailNow() 116 } 117 if ValueOf(x).CanAddr() { 118 t.FailNow() 119 } 120 if ValueOf(&x).CanAddr() { 121 t.FailNow() 122 } 123 assert.True(t, ValueOf(&x).Elem().Elem().CanAddr()) 124 assert.True(t, ValueFrom(reflect.ValueOf(&x)).Elem().CanAddr()) 125 assert.True(t, ValueFrom(reflect.ValueOf(&x).Elem()).CanAddr()) 126 } 127 128 func TestPointer(t *testing.T) { 129 type X struct { 130 A int16 131 B string 132 } 133 x := X{A: 12345, B: "test"} 134 if ValueOf(&x).Pointer() != reflect.ValueOf(&x).Pointer() { 135 t.FailNow() 136 } 137 elemPtr := ValueOf(x).Pointer() 138 a := *(*int16)(unsafe.Pointer(elemPtr)) 139 if a != x.A { 140 t.FailNow() 141 } 142 b := *(*string)(unsafe.Pointer(elemPtr + unsafe.Offsetof(x.B))) 143 if b != x.B { 144 t.FailNow() 145 } 146 147 s := []string{""} 148 if ValueOf(s).Pointer() != reflect.ValueOf(s).Pointer() { 149 t.FailNow() 150 } 151 152 f := func() bool { return true } 153 prt := ValueOf(f).Pointer() 154 f = *(*func() bool)(unsafe.Pointer(&prt)) 155 if !f() { 156 t.FailNow() 157 } 158 t.Log(ValueOf(f).FuncForPC().Name()) 159 prt = ValueOf(t.Name).Pointer() 160 tName := *(*func() string)(unsafe.Pointer(&prt)) 161 if tName() != "TestPointer" { 162 t.FailNow() 163 } 164 t.Log(ValueOf(t.Name).FuncForPC().Name()) 165 t.Log(ValueOf(s).FuncForPC() == nil) 166 167 } 168 169 func TestElem(t *testing.T) { 170 type I interface{} 171 var i I 172 u := ValueFrom(reflect.ValueOf(i)) 173 type X struct { 174 A int16 175 B string 176 } 177 x := &X{A: 12345, B: "test"} 178 xx := &x 179 var elemPtr uintptr 180 for _, v := range []interface{}{&xx, xx, x, *x} { 181 val := ValueOf(v).UnderlyingElem() 182 elemPtr = val.Pointer() 183 a := *(*int16)(unsafe.Pointer(elemPtr)) 184 if !assert.Equal(t, x.A, a) { 185 t.FailNow() 186 } 187 b := *(*string)(unsafe.Pointer(elemPtr + unsafe.Offsetof(x.B))) 188 if !assert.Equal(t, x.B, b) { 189 t.FailNow() 190 } 191 } 192 193 var y *X 194 u = ValueOf(&y) 195 if !assert.False(t, u.IsNil()) { 196 t.FailNow() 197 } 198 u = u.UnderlyingElem() 199 if !assert.Equal(t, reflect.Struct, u.Kind()) { 200 t.FailNow() 201 } 202 if !assert.True(t, u.IsNil()) { 203 t.FailNow() 204 } 205 } 206 207 func TestEmptyStruct(t *testing.T) { 208 type P1 struct { 209 A *int 210 } 211 u := ValueOf(P1{}) 212 if u.Pointer() != 0 { 213 t.FailNow() 214 } 215 if !u.IsNil() { 216 t.FailNow() 217 } 218 219 type P2 struct { 220 A *int 221 B *int 222 } 223 u = ValueOf(P2{}) 224 if u.Pointer() == 0 { 225 t.FailNow() 226 } 227 if u.IsNil() { 228 t.FailNow() 229 } 230 } 231 232 func TestValueFrom(t *testing.T) { 233 type X struct { 234 A int16 235 B string 236 } 237 x := &X{A: 12345, B: "test"} 238 v := reflect.ValueOf(&x) 239 u := ValueFrom2(&v).Elem() 240 v = v.Elem() 241 if u.RuntimeTypeID() != RuntimeTypeID(v.Type()) { 242 t.FailNow() 243 } 244 elemPtr := u.Pointer() 245 a := *(*int16)(unsafe.Pointer(elemPtr)) 246 if a != x.A { 247 t.FailNow() 248 } 249 b := *(*string)(unsafe.Pointer(elemPtr + unsafe.Offsetof(x.B))) 250 if b != x.B { 251 t.FailNow() 252 } 253 if u.Pointer() != reflect.ValueOf(x).Pointer() { 254 t.FailNow() 255 } 256 } 257 258 func Benchmark_ameda(b *testing.B) { 259 type T struct { 260 a int 261 } 262 t := new(T) 263 b.ReportAllocs() 264 b.ResetTimer() 265 u := ValueOf(t).Elem() 266 for i := 0; i < b.N; i++ { 267 _ = u.RuntimeTypeID() 268 } 269 } 270 271 func Benchmark_reflect(b *testing.B) { 272 type T struct { 273 a int 274 } 275 t := new(T) 276 b.ReportAllocs() 277 b.ResetTimer() 278 u := reflect.TypeOf(t).Elem() 279 for i := 0; i < b.N; i++ { 280 _ = u.String() 281 } 282 }