github.com/ugorji/go/codec@v1.2.13-0.20240307214044-07c54c229a5a/values_flex_test.go (about) 1 // comment this out // // + build testing 2 3 // Copyright (c) 2012-2020 Ugorji Nwoke. All rights reserved. 4 // Use of this source code is governed by a MIT license found in the LICENSE file. 5 6 package codec 7 8 import ( 9 "fmt" 10 "strconv" 11 "strings" 12 "time" 13 ) 14 15 const teststrucflexChanCap = 64 16 17 // This file contains values used by tests alone. 18 // This is where we may try out different things, 19 // that other engines may not support or may barf upon 20 // e.g. custom extensions for wrapped types, maps with non-string keys, etc. 21 22 // some funky types to test codecgen 23 24 type codecgenA struct { 25 ZZ []byte 26 } 27 type codecgenB struct { 28 AA codecgenA 29 } 30 type codecgenC struct { 31 _struct struct{} `codec:",omitempty"` 32 BB codecgenB 33 } 34 35 type TestCodecgenG struct { 36 TestCodecgenG int 37 } 38 type codecgenH struct { 39 TestCodecgenG 40 } 41 type codecgenI struct { 42 codecgenH 43 } 44 45 type codecgenK struct { 46 X int 47 Y string 48 } 49 type codecgenL struct { 50 X int 51 Y uint32 52 } 53 type codecgenM struct { 54 codecgenK 55 codecgenL 56 } 57 58 // some types to test struct keytype 59 60 type testStrucKeyTypeT0 struct { 61 _struct struct{} 62 F int 63 } 64 type testStrucKeyTypeT1 struct { 65 _struct struct{} `codec:",string"` 66 F int `codec:"FFFF"` 67 } 68 type testStrucKeyTypeT2 struct { 69 _struct struct{} `codec:",int"` 70 F int `codec:"-1"` 71 } 72 type testStrucKeyTypeT3 struct { 73 _struct struct{} `codec:",uint"` 74 F int `codec:"1"` 75 } 76 type testStrucKeyTypeT4 struct { 77 _struct struct{} `codec:",float"` 78 F int `codec:"2.5"` 79 } 80 81 // Some unused types just stored here 82 83 type Bbool bool 84 type Aarray [1]string 85 type Sstring string 86 type Sstructsmall struct { 87 A int 88 } 89 90 type Sstructbig struct { 91 _struct struct{} 92 A int 93 B bool 94 c string 95 // Sval Sstruct 96 Ssmallptr *Sstructsmall 97 Ssmall Sstructsmall 98 Sptr *Sstructbig 99 } 100 101 type SstructbigToArray struct { 102 _struct struct{} `codec:",toarray"` 103 A int 104 B bool 105 c string 106 // Sval Sstruct 107 Ssmallptr *Sstructsmall 108 Ssmall Sstructsmall 109 Sptr *Sstructbig 110 } 111 112 // small struct for testing that codecgen works for unexported types 113 type tLowerFirstLetter struct { 114 I int 115 u uint64 116 S string 117 b []byte 118 } 119 120 // Some wrapped types which are used as extensions 121 type wrapInt64 int64 122 type wrapUint8 uint8 123 type wrapBytes []byte 124 125 // some types that define how to marshal themselves 126 type testMarshalAsJSON bool 127 type testMarshalAsBinary []byte 128 type testMarshalAsText string 129 130 // some types used for extensions 131 type testUintToBytes uint32 132 133 func (x testMarshalAsJSON) MarshalJSON() (data []byte, err error) { 134 if x { 135 data = []byte("true") 136 } else { 137 data = []byte("false") 138 } 139 return 140 } 141 func (x *testMarshalAsJSON) UnmarshalJSON(data []byte) (err error) { 142 switch string(data) { 143 case "true": 144 *x = true 145 case "false": 146 *x = false 147 default: 148 err = fmt.Errorf("testMarshalAsJSON failed to decode as bool: %s", data) 149 } 150 return 151 } 152 153 func (x testMarshalAsBinary) MarshalBinary() (data []byte, err error) { 154 data = []byte(x) 155 return 156 } 157 func (x *testMarshalAsBinary) UnmarshalBinary(data []byte) (err error) { 158 *x = data 159 return 160 } 161 162 func (x testMarshalAsText) MarshalText() (text []byte, err error) { 163 text = []byte(x) 164 return 165 } 166 func (x *testMarshalAsText) UnmarshalText(text []byte) (err error) { 167 *x = testMarshalAsText(string(text)) 168 return 169 } 170 171 type AnonInTestStrucIntf struct { 172 Islice []interface{} 173 Ms map[string]interface{} 174 Nintf interface{} //don't set this, so we can test for nil 175 T time.Time 176 Tptr *time.Time 177 } 178 179 type missingFielderT1 struct { 180 S string 181 B bool 182 f float64 183 i int64 184 } 185 186 func (t *missingFielderT1) CodecMissingField(field []byte, value interface{}) bool { 187 switch string(field) { 188 case "F": 189 t.f = value.(float64) 190 case "I": 191 t.i = value.(int64) 192 default: 193 return false 194 } 195 return true 196 } 197 198 func (t *missingFielderT1) CodecMissingFields() map[string]interface{} { 199 return map[string]interface{}{"F": t.f, "I": t.i} 200 } 201 202 type missingFielderT11 struct { 203 s1 string 204 S2 string 205 } 206 207 func (t *missingFielderT11) CodecMissingField(field []byte, value interface{}) bool { 208 if "s1" == string(field) { 209 t.s1 = value.(string) 210 return true 211 } 212 return false 213 } 214 215 // missingFielderT11 implements CodecMissingFields on the value (not pointer) 216 func (t missingFielderT11) CodecMissingFields() map[string]interface{} { 217 return map[string]interface{}{"s1": t.s1} 218 } 219 220 type missingFielderT2 struct { 221 S string 222 B bool 223 F float64 224 I int64 225 } 226 227 type testSelfExtHelper struct { 228 S string 229 I int64 230 B bool 231 } 232 233 type TestSelfExtImpl struct { 234 testSelfExtHelper 235 } 236 237 type TestSelfExtImpl2 struct { 238 M string 239 O bool 240 } 241 242 type TestTwoNakedInterfaces struct { 243 A interface{} 244 B interface{} 245 } 246 247 var testWRepeated512 wrapBytes 248 var testStrucTime = time.Date(2012, 2, 2, 2, 2, 2, 2000, time.UTC).UTC() 249 250 func init() { 251 var testARepeated512 [512]byte 252 for i := range testARepeated512 { 253 testARepeated512[i] = 'A' 254 } 255 testWRepeated512 = wrapBytes(testARepeated512[:]) 256 } 257 258 type TestStrucFlex struct { 259 _struct struct{} `codec:",omitempty"` //set omitempty for every field 260 TestStrucCommon 261 262 Chstr chan string 263 264 Mis map[int]string 265 Mbu64 map[bool]struct{} 266 Mu8e map[byte]struct{} 267 Mu8u64 map[byte]stringUint64T 268 Msp2ss map[*string][]string 269 Mip2ss map[*uint64][]string 270 Ms2misu map[string]map[uint64]stringUint64T 271 Miwu64s map[int]wrapUint64Slice 272 Mfwss map[float64]wrapStringSlice 273 Mf32wss map[float32]wrapStringSlice 274 Mui2wss map[uint64]wrapStringSlice 275 276 // DecodeNaked bombs because stringUint64T is decoded as a map, 277 // and a map cannot be the key type of a map. 278 // Ensure this is set to nil if decoding into a nil interface{}. 279 Msu2wss map[stringUint64T]wrapStringSlice 280 281 Ci64 wrapInt64 282 Swrapbytes []wrapBytes 283 Swrapuint8 []wrapUint8 284 285 ArrStrUi64T [4]stringUint64T 286 287 Ui64array [4]uint64 288 Ui64slicearray []*[4]uint64 289 290 SintfAarray []interface{} 291 292 // Ensure this is set to nil if decoding into a nil interface{}. 293 MstrUi64TSelf map[stringUint64T]*stringUint64T 294 295 Ttime time.Time 296 Ttimeptr *time.Time 297 298 // make this a ptr, so that it could be set or not. 299 // for comparison (e.g. with msgp), give it a struct tag (so it is not inlined), 300 // make this one omitempty (so it is excluded if nil). 301 *AnonInTestStrucIntf `json:",omitempty"` 302 303 M map[interface{}]interface{} `json:"-"` 304 Msu map[wrapString]interface{} 305 Mtsptr map[string]*TestStrucFlex 306 Mts map[string]TestStrucFlex 307 Its []*TestStrucFlex 308 Nteststruc *TestStrucFlex 309 310 MarJ testMarshalAsJSON 311 MarT testMarshalAsText 312 MarB testMarshalAsBinary 313 314 XuintToBytes testUintToBytes 315 316 Ffunc func() error // expect this to be skipped/ignored 317 Bboolignore bool `codec:"-"` // expect this to be skipped/ignored 318 319 Cmplx64 complex64 320 Cmplx128 complex128 321 } 322 323 func newTestStrucFlex(depth, n int, bench, useInterface, useStringKeyOnly bool) (ts *TestStrucFlex) { 324 ts = &TestStrucFlex{ 325 Chstr: make(chan string, teststrucflexChanCap), 326 327 Miwu64s: map[int]wrapUint64Slice{ 328 5: []wrapUint64{1, 2, 3, 4, 5}, 329 3: []wrapUint64{1, 2, 3}, 330 }, 331 332 Mf32wss: map[float32]wrapStringSlice{ 333 5.0: []wrapString{"1.0", "2.0", "3.0", "4.0", "5.0"}, 334 3.0: []wrapString{"1.0", "2.0", "3.0"}, 335 }, 336 337 Mui2wss: map[uint64]wrapStringSlice{ 338 5: []wrapString{"1.0", "2.0", "3.0", "4.0", "5.0"}, 339 3: []wrapString{"1.0", "2.0", "3.0"}, 340 }, 341 342 Mfwss: map[float64]wrapStringSlice{ 343 5.0: []wrapString{"1.0", "2.0", "3.0", "4.0", "5.0"}, 344 3.0: []wrapString{"1.0", "2.0", "3.0"}, 345 }, 346 347 // DecodeNaked bombs here, because the stringUint64T is decoded as a map, 348 // and a map cannot be the key type of a map. 349 // Ensure this is set to nil if decoding into a nil interface{}. 350 Msu2wss: map[stringUint64T]wrapStringSlice{ 351 stringUint64T{"5", 5}: []wrapString{"1", "2", "3", "4", "5"}, 352 stringUint64T{"3", 3}: []wrapString{"1", "2", "3"}, 353 }, 354 355 Mis: map[int]string{ 356 1: "one", 357 22: "twenty two", 358 -44: "minus forty four", 359 }, 360 361 Ms2misu: map[string]map[uint64]stringUint64T{ 362 "1": {1: {"11", 11}}, 363 "22": {1: {"2222", 2222}}, 364 "333": {1: {"333333", 333333}}, 365 }, 366 367 Mbu64: map[bool]struct{}{false: {}, true: {}}, 368 Mu8e: map[byte]struct{}{1: {}, 2: {}, 3: {}, 4: {}}, 369 Mu8u64: make(map[byte]stringUint64T), 370 Mip2ss: make(map[*uint64][]string), 371 Msp2ss: make(map[*string][]string), 372 M: make(map[interface{}]interface{}), 373 Msu: make(map[wrapString]interface{}), 374 375 Ci64: -22, 376 Swrapbytes: []wrapBytes{ // lengths of 1, 2, 4, 8, 16, 32, 64, 128, 256, 377 testWRepeated512[:1], 378 testWRepeated512[:2], 379 testWRepeated512[:4], 380 testWRepeated512[:8], 381 testWRepeated512[:16], 382 testWRepeated512[:32], 383 testWRepeated512[:64], 384 testWRepeated512[:128], 385 testWRepeated512[:256], 386 testWRepeated512[:512], 387 }, 388 Swrapuint8: []wrapUint8{ 389 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 390 }, 391 Ui64array: [4]uint64{4, 16, 64, 256}, 392 ArrStrUi64T: [4]stringUint64T{{"4", 4}, {"3", 3}, {"2", 2}, {"1", 1}}, 393 SintfAarray: []interface{}{Aarray{"s"}}, 394 MstrUi64TSelf: make(map[stringUint64T]*stringUint64T, numStrUi64T), 395 396 Ttime: testStrucTime, 397 Ttimeptr: &testStrucTime, 398 399 MarJ: true, 400 MarT: "hello string", 401 MarB: []byte("hello bytes"), 402 403 XuintToBytes: 16, 404 405 Cmplx64: complex(16, 0), 406 Cmplx128: complex(1616, 0), 407 } 408 409 var strslice []string 410 for i := uint64(0); i < numStrUi64T; i++ { 411 s := strings.Repeat(strconv.FormatUint(i, 10), 4) 412 ss := stringUint64T{S: s, U: i} 413 strslice = append(strslice, s) 414 // Ensure this is set to nil if decoding into a nil interface{}. 415 ts.MstrUi64TSelf[ss] = &ss 416 ts.Mu8u64[s[0]] = ss 417 ts.Mip2ss[&i] = strslice 418 ts.Msp2ss[&s] = strslice 419 // add some other values of maps and pointers into M 420 ts.M[s] = strslice 421 // cannot use this, as converting stringUint64T to interface{} returns map, 422 // DecodeNaked does this, causing "hash of unhashable value" as some maps cannot be map keys 423 // ts.M[ss] = &ss 424 ts.Msu[wrapString(s)] = &ss 425 s = s + "-map" 426 ss.S = s 427 ts.M[s] = map[string]string{s: s} 428 ts.Msu[wrapString(s)] = map[string]string{s: s} 429 } 430 431 numChanSend := cap(ts.Chstr) / 4 // 8 432 for i := 0; i < numChanSend; i++ { 433 ts.Chstr <- strings.Repeat("A", i+1) 434 } 435 436 ts.Ui64slicearray = []*[4]uint64{&ts.Ui64array, &ts.Ui64array} 437 438 if useInterface { 439 ts.AnonInTestStrucIntf = &AnonInTestStrucIntf{ 440 Islice: []interface{}{strRpt(n, "true"), true, strRpt(n, "no"), false, uint64(288), float64(0.4)}, 441 Ms: map[string]interface{}{ 442 strRpt(n, "true"): strRpt(n, "true"), 443 strRpt(n, "int64(9)"): false, 444 }, 445 T: testStrucTime, 446 Tptr: &testStrucTime, 447 } 448 } 449 450 populateTestStrucCommon(&ts.TestStrucCommon, n, bench, useInterface, useStringKeyOnly) 451 if depth > 0 { 452 depth-- 453 if ts.Mtsptr == nil { 454 ts.Mtsptr = make(map[string]*TestStrucFlex) 455 } 456 if ts.Mts == nil { 457 ts.Mts = make(map[string]TestStrucFlex) 458 } 459 ts.Mtsptr["0"] = newTestStrucFlex(depth, n, bench, useInterface, useStringKeyOnly) 460 ts.Mts["0"] = *(ts.Mtsptr["0"]) 461 ts.Its = append(ts.Its, ts.Mtsptr["0"]) 462 } 463 return 464 }