github.com/ugorji/go/codec@v1.2.13-0.20240307214044-07c54c229a5a/values_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 // This file contains values used by tests and benchmarks. 9 // The benchmarks will test performance against other libraries 10 // (encoding/json, json-iterator, bson, gob, etc). 11 // Consequently, we only use values that will parse well in all engines, 12 // and only leverage features that work across multiple libraries for a truer comparison. 13 // For example, 14 // - JSON/BSON do not like maps with keys that are not strings, 15 // so we only use maps with string keys here. 16 // - _struct options are not honored by other libraries, 17 // so we don't use them in this file. 18 19 import ( 20 "math" 21 "strconv" 22 "strings" 23 ) 24 25 // func init() { 26 // rt := reflect.TypeOf((*TestStruc)(nil)).Elem() 27 // defTypeInfos.get(rt2id(rt), rt) 28 // } 29 30 const numStrUi64T = 32 // use 8, prefer 32, test with 1024 31 32 type wrapSliceUint64 []uint64 33 type wrapSliceString []string 34 type wrapUint64 uint64 35 type wrapString string 36 type wrapUint64Slice []wrapUint64 37 type wrapStringSlice []wrapString 38 39 // some other types 40 41 type stringUint64T struct { 42 S string 43 U uint64 44 } 45 46 type AnonInTestStrucSlim struct { 47 S string 48 P *string 49 } 50 51 type AnonInTestStruc struct { 52 AS string 53 AI64 int64 54 AI16 int16 55 AUi64 uint64 56 ASslice []string 57 AI64slice []int64 58 AUi64slice []uint64 59 AF64slice []float64 60 AF32slice []float32 61 62 AMSS map[string]string 63 // AMI32U32 map[int32]uint32 64 // AMU32F64 map[uint32]float64 // json/bson do not like it 65 AMSU64 map[string]uint64 66 67 AI64arr8 [8]int64 68 69 // use these to test 0-len or nil slices/maps/arrays 70 AI64arr0 [0]int64 71 AI64slice0 []int64 72 AUi64sliceN []uint64 73 AMSU64N map[string]uint64 74 AMSU64E map[string]uint64 75 } 76 77 // testSimpleFields is a sub-set of TestStrucCommon 78 type testSimpleFields struct { 79 S string 80 81 I64 int64 82 I8 int8 83 84 Ui64 uint64 85 Ui8 uint8 86 87 F64 float64 88 F32 float32 89 90 B bool 91 92 Sslice []string 93 I32slice []int32 94 Ui64slice []uint64 95 Ui8slice []uint8 96 Bslice []bool 97 98 Iptrslice []*int64 99 100 WrapSliceInt64 wrapSliceUint64 101 WrapSliceString wrapSliceString 102 103 Msint map[string]int 104 } 105 106 type TestStrucCommon struct { 107 S string 108 109 I64 int64 110 I32 int32 111 I16 int16 112 I8 int8 113 114 I64n int64 115 I32n int32 116 I16n int16 117 I8n int8 118 119 Ui64 uint64 120 Ui32 uint32 121 Ui16 uint16 122 Ui8 uint8 123 124 F64 float64 125 F32 float32 126 127 B bool 128 By uint8 // byte: msgp doesn't like byte 129 130 Sslice []string 131 I64slice []int64 132 I32slice []int32 133 Ui64slice []uint64 134 Ui8slice []uint8 135 Bslice []bool 136 Byslice []byte 137 138 BytesSlice [][]byte 139 140 Iptrslice []*int64 141 142 WrapSliceInt64 wrapSliceUint64 143 WrapSliceString wrapSliceString 144 145 Msint map[string]int 146 147 Msbytes map[string][]byte 148 149 Simplef testSimpleFields 150 151 SstrUi64T []stringUint64T 152 MstrUi64T map[string]*stringUint64T 153 154 AnonInTestStruc 155 156 NotAnon AnonInTestStruc 157 158 *AnonInTestStrucSlim 159 NotAnonSlim *AnonInTestStrucSlim 160 161 // R Raw // Testing Raw must be explicitly turned on, so use standalone test 162 // Rext RawExt // Testing RawExt is tricky, so use standalone test 163 164 Nmap map[string]bool //don't set this, so we can test for nil 165 Nslice []byte //don't set this, so we can test for nil 166 Nint64 *int64 //don't set this, so we can test for nil 167 } 168 169 type TestStruc struct { 170 // _struct struct{} `json:",omitempty"` //set omitempty for every field 171 172 TestStrucCommon 173 174 Mtsptr map[string]*TestStruc 175 Mts map[string]TestStruc 176 Its []*TestStruc 177 Nteststruc *TestStruc 178 } 179 180 func populateTestStrucCommon(ts *TestStrucCommon, n int, bench, useInterface, useStringKeyOnly bool) { 181 var i64a, i64b, i64c, i64d int64 = 64, 6464, 646464, 64646464 182 183 // if bench, do not use uint64 values > math.MaxInt64, as bson, etc cannot decode them 184 185 var a = AnonInTestStruc{ 186 // There's more leeway in altering this. 187 AS: strRpt(n, "A-String"), 188 AI64: -64646464, 189 AI16: 1616, 190 AUi64: 64646464, 191 // (U+1D11E)G-clef character may be represented in json as "\uD834\uDD1E". 192 // single reverse solidus character may be represented in json as "\u005C". 193 // include these in ASslice below. 194 ASslice: []string{ 195 strRpt(n, "Aone"), 196 strRpt(n, "Atwo"), 197 strRpt(n, "Athree"), 198 strRpt(n, "Afour.reverse_solidus.\u005c"), 199 strRpt(n, "Afive.Gclef.\U0001d11E\"ugorji\"done.")}, 200 AI64slice: []int64{ 201 0, 1, -1, -22, 333, -4444, 55555, -666666, 202 // msgpack ones 203 -48, -32, -24, -8, 32, 127, 192, 255, 204 // standard ones 205 0, -1, 1, 206 math.MaxInt8, math.MaxInt8 + 4, math.MaxInt8 - 4, 207 math.MaxInt16, math.MaxInt16 + 4, math.MaxInt16 - 4, 208 math.MaxInt32, math.MaxInt32 + 4, math.MaxInt32 - 4, 209 math.MaxInt64, math.MaxInt64 - 4, 210 math.MinInt8, math.MinInt8 + 4, math.MinInt8 - 4, 211 math.MinInt16, math.MinInt16 + 4, math.MinInt16 - 4, 212 math.MinInt32, math.MinInt32 + 4, math.MinInt32 - 4, 213 math.MinInt64, math.MinInt64 + 4, 214 }, 215 AUi64slice: []uint64{ 216 0, 1, 22, 333, 4444, 55555, 666666, 217 // standard ones 218 math.MaxUint8, math.MaxUint8 + 4, math.MaxUint8 - 4, 219 math.MaxUint16, math.MaxUint16 + 4, math.MaxUint16 - 4, 220 math.MaxUint32, math.MaxUint32 + 4, math.MaxUint32 - 4, 221 }, 222 AMSU64: map[string]uint64{ 223 strRpt(n, "1"): 1, 224 strRpt(n, "22"): 2, 225 strRpt(n, "333"): 3, 226 strRpt(n, "4444"): 4, 227 }, 228 AMSS: map[string]string{ 229 strRpt(n, "1"): strRpt(n, "1"), 230 strRpt(n, "22"): strRpt(n, "22"), 231 strRpt(n, "333"): strRpt(n, "333"), 232 strRpt(n, "4444"): strRpt(n, "4444"), 233 }, 234 235 AI64arr8: [...]int64{1, 8, 2, 7, 3, 6, 4, 5}, 236 237 // Note: +/- inf, NaN, and other non-representable numbers should not be explicitly tested here 238 239 AF64slice: []float64{ 240 11.11e-11, -11.11e+11, 241 2.222e+12, -2.222e-12, 242 -555.55e-5, 555.55e+5, 243 666.66e-6, -666.66e+6, 244 7777.7777e-7, -7777.7777e-7, 245 -8888.8888e+8, 8888.8888e+8, 246 -99999.9999e+9, 99999.9999e+9, 247 // these below are hairy enough to need strconv.ParseFloat 248 33.33e-33, -33.33e+33, 249 44.44e+44, -44.44e-44, 250 // standard ones 251 0, -1, 1, 252 // math.Inf(1), math.Inf(-1), 253 math.Pi, math.Phi, math.E, 254 math.MaxFloat64, math.SmallestNonzeroFloat64, 255 }, 256 AF32slice: []float32{ 257 11.11e-1, -11.11e+1, 258 2.222e+2, -2.222e-2, 259 -55.55e-5, 55.55e+5, 260 66.66e-6, -66.66e+6, 261 777.777e-7, -777.777e-7, 262 -8.88e+8, 8.88e-8, 263 -99999.9999e+9, 99999.9999e+9, 264 // these below are hairy enough to need strconv.ParseFloat 265 33.33e-33, -33.33e+33, 266 // standard ones 267 0, -1, 1, 268 // math.Float32frombits(0x7FF00000), math.Float32frombits(0xFFF00000), //+inf and -inf 269 math.MaxFloat32, math.SmallestNonzeroFloat32, 270 }, 271 272 AI64slice0: []int64{}, 273 AUi64sliceN: nil, 274 AMSU64N: nil, 275 AMSU64E: map[string]uint64{}, 276 } 277 278 if !bench { 279 a.AUi64slice = append(a.AUi64slice, math.MaxUint64, math.MaxUint64-4) 280 } 281 *ts = TestStrucCommon{ 282 S: strRpt(n, `some really really cool names that are nigerian and american like "ugorji melody nwoke" - get it? `), 283 284 // set the numbers close to the limits 285 I8: math.MaxInt8 * 2 / 3, // 8, 286 I8n: math.MinInt8 * 2 / 3, // 8, 287 I16: math.MaxInt16 * 2 / 3, // 16, 288 I16n: math.MinInt16 * 2 / 3, // 16, 289 I32: math.MaxInt32 * 2 / 3, // 32, 290 I32n: math.MinInt32 * 2 / 3, // 32, 291 I64: math.MaxInt64 * 2 / 3, // 64, 292 I64n: math.MinInt64 * 2 / 3, // 64, 293 294 Ui64: math.MaxUint64 * 2 / 3, // 64 295 Ui32: math.MaxUint32 * 2 / 3, // 32 296 Ui16: math.MaxUint16 * 2 / 3, // 16 297 Ui8: math.MaxUint8 * 2 / 3, // 8 298 299 F32: 3.402823e+38, // max representable float32 without losing precision 300 F64: 3.40281991833838838338e+53, 301 302 B: true, 303 By: 5, 304 305 Sslice: []string{strRpt(n, "one"), strRpt(n, "two"), strRpt(n, "three")}, 306 I64slice: []int64{1111, 2222, 3333}, 307 I32slice: []int32{44, 55, 66}, 308 Ui64slice: []uint64{12121212, 34343434, 56565656}, 309 Ui8slice: []uint8{210, 211, 212}, 310 Bslice: []bool{true, false, true, false}, 311 Byslice: []byte{13, 14, 15}, 312 BytesSlice: [][]byte{ 313 []byte(strRpt(n, "one")), 314 []byte(strRpt(n, "two")), 315 []byte(strRpt(n, "\"three\"")), 316 }, 317 Msint: map[string]int{ 318 strRpt(n, "one"): 1, 319 strRpt(n, "two"): 2, 320 strRpt(n, "\"three\""): 3, 321 }, 322 Msbytes: map[string][]byte{ 323 strRpt(n, "one"): []byte(strRpt(n, "one")), 324 strRpt(n, "two"): []byte(strRpt(n, "two")), 325 strRpt(n, "\"three\""): []byte(strRpt(n, "\"three\"")), 326 }, 327 WrapSliceInt64: []uint64{4, 16, 64, 256}, 328 WrapSliceString: []string{strRpt(n, "4"), strRpt(n, "16"), strRpt(n, "64"), strRpt(n, "256")}, 329 330 // R: Raw([]byte("goodbye")), 331 // Rext: RawExt{ 120, []byte("hello"), }, // MARKER: don't set this - it's hard to test 332 333 // make Simplef same as top-level 334 // MARKER: should this have slightly different values??? 335 Simplef: testSimpleFields{ 336 S: strRpt(n, `some really really cool names that are nigerian and american like "ugorji melody nwoke" - get it? `), 337 338 // set the numbers close to the limits 339 I8: math.MaxInt8 * 2 / 3, // 8, 340 I64: math.MaxInt64 * 2 / 3, // 64, 341 342 Ui64: math.MaxUint64 * 2 / 3, // 64 343 Ui8: math.MaxUint8 * 2 / 3, // 8 344 345 F32: 3.402823e+38, // max representable float32 without losing precision 346 F64: 3.40281991833838838338e+53, 347 348 B: true, 349 350 Sslice: []string{strRpt(n, "one"), strRpt(n, "two"), strRpt(n, "three")}, 351 I32slice: []int32{44, 55, 66}, 352 Ui64slice: []uint64{12121212, 34343434, 56565656}, 353 Ui8slice: []uint8{210, 211, 212}, 354 Bslice: []bool{true, false, true, false}, 355 356 Msint: map[string]int{ 357 strRpt(n, "one"): 1, 358 strRpt(n, "two"): 2, 359 strRpt(n, "\"three\""): 3, 360 }, 361 362 WrapSliceInt64: []uint64{4, 16, 64, 256}, 363 WrapSliceString: []string{strRpt(n, "4"), strRpt(n, "16"), strRpt(n, "64"), strRpt(n, "256")}, 364 }, 365 366 SstrUi64T: make([]stringUint64T, numStrUi64T), // {{"1", 1}, {"2", 2}, {"3", 3}, {"4", 4}}, 367 MstrUi64T: make(map[string]*stringUint64T, numStrUi64T), 368 AnonInTestStruc: a, 369 NotAnon: a, 370 } 371 372 for i := uint64(0); i < numStrUi64T; i++ { 373 ss := strings.Repeat(strconv.FormatUint(i, 10), int(i)) // 4) 374 ts.SstrUi64T[i] = stringUint64T{S: ss, U: i} 375 ts.MstrUi64T[ss] = &ts.SstrUi64T[i] 376 } 377 378 if bench { 379 ts.Ui64 = math.MaxInt64 * 2 / 3 380 ts.Simplef.Ui64 = ts.Ui64 381 } 382 383 //For benchmarks, some things will not work. 384 if !bench { 385 //json and bson require string keys in maps 386 //ts.M = map[interface{}]interface{}{ 387 // true: "true", 388 // int8(9): false, 389 //} 390 //gob cannot encode nil in element in array (encodeArray: nil element) 391 ts.Iptrslice = []*int64{nil, &i64a, nil, &i64b, nil, &i64c, nil, &i64d, nil} 392 // ts.Iptrslice = nil 393 } 394 if !useStringKeyOnly { 395 var _ byte = 0 // so this empty branch doesn't flag a warning 396 // ts.AnonInTestStruc.AMU32F64 = map[uint32]float64{1: 1, 2: 2, 3: 3} // Json/Bson barf 397 } 398 } 399 400 func newTestStruc(depth, n int, bench, useInterface, useStringKeyOnly bool) (ts *TestStruc) { 401 ts = &TestStruc{} 402 populateTestStrucCommon(&ts.TestStrucCommon, n, bench, useInterface, useStringKeyOnly) 403 if depth > 0 { 404 depth-- 405 if ts.Mtsptr == nil { 406 ts.Mtsptr = make(map[string]*TestStruc) 407 } 408 if ts.Mts == nil { 409 ts.Mts = make(map[string]TestStruc) 410 } 411 ts.Mtsptr[strRpt(n, "0")] = newTestStruc(depth, n, bench, useInterface, useStringKeyOnly) 412 ts.Mts[strRpt(n, "0")] = *(ts.Mtsptr[strRpt(n, "0")]) 413 ts.Its = append(ts.Its, ts.Mtsptr[strRpt(n, "0")]) 414 } 415 return 416 } 417 418 var testStrRptMap = make(map[int]map[string]string) 419 420 func strRpt(n int, s string) string { 421 if false { 422 // fmt.Printf(">>>> calling strings.Repeat on n: %d, key: %s\n", n, s) 423 return strings.Repeat(s, n) 424 } 425 m1, ok := testStrRptMap[n] 426 if !ok { 427 // fmt.Printf(">>>> making new map for n: %v\n", n) 428 m1 = make(map[string]string) 429 testStrRptMap[n] = m1 430 } 431 v1, ok := m1[s] 432 if !ok { 433 // fmt.Printf(">>>> creating new entry for key: %s\n", s) 434 v1 = strings.Repeat(s, n) 435 m1[s] = v1 436 } 437 return v1 438 } 439 440 // func wstrRpt(n int, s string) wrapBytes { 441 // return wrapBytes(bytes.Repeat([]byte(s), n)) 442 // }