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