github.com/lingyao2333/mo-zero@v1.4.1/core/mapping/utils_test.go (about) 1 package mapping 2 3 import ( 4 "reflect" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 ) 9 10 const testTagName = "key" 11 12 type Foo struct { 13 Str string 14 StrWithTag string `key:"stringwithtag"` 15 StrWithTagAndOption string `key:"stringwithtag,string"` 16 } 17 18 func TestDerefInt(t *testing.T) { 19 i := 1 20 s := "hello" 21 number := struct { 22 f float64 23 }{ 24 f: 6.4, 25 } 26 cases := []struct { 27 t reflect.Type 28 expect reflect.Kind 29 }{ 30 { 31 t: reflect.TypeOf(i), 32 expect: reflect.Int, 33 }, 34 { 35 t: reflect.TypeOf(&i), 36 expect: reflect.Int, 37 }, 38 { 39 t: reflect.TypeOf(s), 40 expect: reflect.String, 41 }, 42 { 43 t: reflect.TypeOf(&s), 44 expect: reflect.String, 45 }, 46 { 47 t: reflect.TypeOf(number.f), 48 expect: reflect.Float64, 49 }, 50 { 51 t: reflect.TypeOf(&number.f), 52 expect: reflect.Float64, 53 }, 54 } 55 56 for _, each := range cases { 57 t.Run(each.t.String(), func(t *testing.T) { 58 assert.Equal(t, each.expect, Deref(each.t).Kind()) 59 }) 60 } 61 } 62 63 func TestDerefValInt(t *testing.T) { 64 i := 1 65 s := "hello" 66 number := struct { 67 f float64 68 }{ 69 f: 6.4, 70 } 71 cases := []struct { 72 t reflect.Value 73 expect reflect.Kind 74 }{ 75 { 76 t: reflect.ValueOf(i), 77 expect: reflect.Int, 78 }, 79 { 80 t: reflect.ValueOf(&i), 81 expect: reflect.Int, 82 }, 83 { 84 t: reflect.ValueOf(s), 85 expect: reflect.String, 86 }, 87 { 88 t: reflect.ValueOf(&s), 89 expect: reflect.String, 90 }, 91 { 92 t: reflect.ValueOf(number.f), 93 expect: reflect.Float64, 94 }, 95 { 96 t: reflect.ValueOf(&number.f), 97 expect: reflect.Float64, 98 }, 99 } 100 101 for _, each := range cases { 102 t.Run(each.t.String(), func(t *testing.T) { 103 assert.Equal(t, each.expect, ensureValue(each.t).Kind()) 104 }) 105 } 106 } 107 108 func TestParseKeyAndOptionWithoutTag(t *testing.T) { 109 var foo Foo 110 rte := reflect.TypeOf(&foo).Elem() 111 field, _ := rte.FieldByName("Str") 112 key, options, err := parseKeyAndOptions(testTagName, field) 113 assert.Nil(t, err) 114 assert.Equal(t, "Str", key) 115 assert.Nil(t, options) 116 } 117 118 func TestParseKeyAndOptionWithTagWithoutOption(t *testing.T) { 119 var foo Foo 120 rte := reflect.TypeOf(&foo).Elem() 121 field, _ := rte.FieldByName("StrWithTag") 122 key, options, err := parseKeyAndOptions(testTagName, field) 123 assert.Nil(t, err) 124 assert.Equal(t, "stringwithtag", key) 125 assert.Nil(t, options) 126 } 127 128 func TestParseKeyAndOptionWithTagAndOption(t *testing.T) { 129 var foo Foo 130 rte := reflect.TypeOf(&foo).Elem() 131 field, _ := rte.FieldByName("StrWithTagAndOption") 132 key, options, err := parseKeyAndOptions(testTagName, field) 133 assert.Nil(t, err) 134 assert.Equal(t, "stringwithtag", key) 135 assert.True(t, options.FromString) 136 } 137 138 func TestParseSegments(t *testing.T) { 139 tests := []struct { 140 input string 141 expect []string 142 }{ 143 { 144 input: "", 145 expect: []string{}, 146 }, 147 { 148 input: ",", 149 expect: []string{""}, 150 }, 151 { 152 input: "foo,", 153 expect: []string{"foo"}, 154 }, 155 { 156 input: ",foo", 157 // the first empty string cannot be ignored, it's the key. 158 expect: []string{"", "foo"}, 159 }, 160 { 161 input: "foo", 162 expect: []string{"foo"}, 163 }, 164 { 165 input: "foo,bar", 166 expect: []string{"foo", "bar"}, 167 }, 168 { 169 input: "foo,bar,baz", 170 expect: []string{"foo", "bar", "baz"}, 171 }, 172 { 173 input: "foo,options=a|b", 174 expect: []string{"foo", "options=a|b"}, 175 }, 176 { 177 input: "foo,bar,default=[baz,qux]", 178 expect: []string{"foo", "bar", "default=[baz,qux]"}, 179 }, 180 { 181 input: "foo,bar,options=[baz,qux]", 182 expect: []string{"foo", "bar", "options=[baz,qux]"}, 183 }, 184 { 185 input: `foo\,bar,options=[baz,qux]`, 186 expect: []string{`foo,bar`, "options=[baz,qux]"}, 187 }, 188 { 189 input: `foo,bar,options=\[baz,qux]`, 190 expect: []string{"foo", "bar", "options=[baz", "qux]"}, 191 }, 192 { 193 input: `foo,bar,options=[baz\,qux]`, 194 expect: []string{"foo", "bar", `options=[baz\,qux]`}, 195 }, 196 { 197 input: `foo\,bar,options=[baz,qux],default=baz`, 198 expect: []string{`foo,bar`, "options=[baz,qux]", "default=baz"}, 199 }, 200 { 201 input: `foo\,bar,options=[baz,qux, quux],default=[qux, baz]`, 202 expect: []string{`foo,bar`, "options=[baz,qux, quux]", "default=[qux, baz]"}, 203 }, 204 } 205 206 for _, test := range tests { 207 test := test 208 t.Run(test.input, func(t *testing.T) { 209 assert.ElementsMatch(t, test.expect, parseSegments(test.input)) 210 }) 211 } 212 } 213 214 func TestValidatePtrWithNonPtr(t *testing.T) { 215 var foo string 216 rve := reflect.ValueOf(foo) 217 assert.NotNil(t, ValidatePtr(&rve)) 218 } 219 220 func TestValidatePtrWithPtr(t *testing.T) { 221 var foo string 222 rve := reflect.ValueOf(&foo) 223 assert.Nil(t, ValidatePtr(&rve)) 224 } 225 226 func TestValidatePtrWithNilPtr(t *testing.T) { 227 var foo *string 228 rve := reflect.ValueOf(foo) 229 assert.NotNil(t, ValidatePtr(&rve)) 230 } 231 232 func TestValidatePtrWithZeroValue(t *testing.T) { 233 var s string 234 e := reflect.Zero(reflect.TypeOf(s)) 235 assert.NotNil(t, ValidatePtr(&e)) 236 } 237 238 func TestSetValueNotSettable(t *testing.T) { 239 var i int 240 assert.NotNil(t, setValue(reflect.Int, reflect.ValueOf(i), "1")) 241 } 242 243 func TestParseKeyAndOptionsErrors(t *testing.T) { 244 type Bar struct { 245 OptionsValue string `key:",options=a=b"` 246 DefaultValue string `key:",default=a=b"` 247 } 248 249 var bar Bar 250 _, _, err := parseKeyAndOptions("key", reflect.TypeOf(&bar).Elem().Field(0)) 251 assert.NotNil(t, err) 252 _, _, err = parseKeyAndOptions("key", reflect.TypeOf(&bar).Elem().Field(1)) 253 assert.NotNil(t, err) 254 } 255 256 func TestSetValueFormatErrors(t *testing.T) { 257 type Bar struct { 258 IntValue int 259 UintValue uint 260 FloatValue float32 261 MapValue map[string]interface{} 262 } 263 264 var bar Bar 265 tests := []struct { 266 kind reflect.Kind 267 target reflect.Value 268 value string 269 }{ 270 { 271 kind: reflect.Int, 272 target: reflect.ValueOf(&bar.IntValue).Elem(), 273 value: "a", 274 }, 275 { 276 kind: reflect.Uint, 277 target: reflect.ValueOf(&bar.UintValue).Elem(), 278 value: "a", 279 }, 280 { 281 kind: reflect.Float32, 282 target: reflect.ValueOf(&bar.FloatValue).Elem(), 283 value: "a", 284 }, 285 { 286 kind: reflect.Map, 287 target: reflect.ValueOf(&bar.MapValue).Elem(), 288 }, 289 } 290 291 for _, test := range tests { 292 t.Run(test.kind.String(), func(t *testing.T) { 293 err := setValue(test.kind, test.target, test.value) 294 assert.NotEqual(t, errValueNotSettable, err) 295 assert.NotNil(t, err) 296 }) 297 } 298 } 299 300 func TestRepr(t *testing.T) { 301 var ( 302 f32 float32 = 1.1 303 f64 = 2.2 304 i8 int8 = 1 305 i16 int16 = 2 306 i32 int32 = 3 307 i64 int64 = 4 308 u8 uint8 = 5 309 u16 uint16 = 6 310 u32 uint32 = 7 311 u64 uint64 = 8 312 ) 313 tests := []struct { 314 v interface{} 315 expect string 316 }{ 317 { 318 nil, 319 "", 320 }, 321 { 322 mockStringable{}, 323 "mocked", 324 }, 325 { 326 new(mockStringable), 327 "mocked", 328 }, 329 { 330 newMockPtr(), 331 "mockptr", 332 }, 333 { 334 &mockOpacity{ 335 val: 1, 336 }, 337 "{1}", 338 }, 339 { 340 true, 341 "true", 342 }, 343 { 344 false, 345 "false", 346 }, 347 { 348 f32, 349 "1.1", 350 }, 351 { 352 f64, 353 "2.2", 354 }, 355 { 356 i8, 357 "1", 358 }, 359 { 360 i16, 361 "2", 362 }, 363 { 364 i32, 365 "3", 366 }, 367 { 368 i64, 369 "4", 370 }, 371 { 372 u8, 373 "5", 374 }, 375 { 376 u16, 377 "6", 378 }, 379 { 380 u32, 381 "7", 382 }, 383 { 384 u64, 385 "8", 386 }, 387 { 388 []byte(`abcd`), 389 "abcd", 390 }, 391 { 392 mockOpacity{val: 1}, 393 "{1}", 394 }, 395 } 396 397 for _, test := range tests { 398 t.Run(test.expect, func(t *testing.T) { 399 assert.Equal(t, test.expect, Repr(test.v)) 400 }) 401 } 402 } 403 404 type mockStringable struct{} 405 406 func (m mockStringable) String() string { 407 return "mocked" 408 } 409 410 type mockPtr struct{} 411 412 func newMockPtr() *mockPtr { 413 return new(mockPtr) 414 } 415 416 func (m *mockPtr) String() string { 417 return "mockptr" 418 } 419 420 type mockOpacity struct { 421 val int 422 }