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