1 /* // +build testing */
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.
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.
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.
25 // rt := reflect.TypeOf((*TestStruc)(nil)).Elem()
26 // defTypeInfos.get(rt2id(rt), rt)
29 type wrapSliceUint64 []uint64
30 type wrapSliceString []string
31 type wrapUint64 uint64
32 type wrapString string
33 type wrapUint64Slice []wrapUint64
34 type wrapStringSlice []wrapString
36 type stringUint64T struct {
41 type missingFielderT1 struct {
48 func (t *missingFielderT1) CodecMissingField(field []byte, value interface{}) bool {
49 switch string(field) {
60 func (t *missingFielderT1) CodecMissingFields() map[string]interface{} {
61 return map[string]interface{}{"F": t.f, "I": t.i}
64 type missingFielderT2 struct {
71 type AnonInTestStruc struct {
82 // AMI32U32 map[int32]uint32
83 // AMU32F64 map[uint32]float64 // json/bson do not like it
84 AMSU16 map[string]uint16
86 // use these to test 0-len or nil slices/maps/arrays
90 AMSU16N map[string]uint16
91 AMSU16E map[string]uint16
94 // testSimpleFields is a sub-set of TestStrucCommon
95 type testSimpleFields struct {
117 WrapSliceInt64 wrapSliceUint64
118 WrapSliceString wrapSliceString
120 Msi64 map[string]int64
123 type TestStrucCommon struct {
145 By uint8 // byte: msgp doesn't like byte
157 WrapSliceInt64 wrapSliceUint64
158 WrapSliceString wrapSliceString
160 Msi64 map[string]int64
162 Simplef testSimpleFields
164 SstrUi64T []stringUint64T
168 NotAnon AnonInTestStruc
170 // R Raw // Testing Raw must be explicitly turned on, so use standalone test
171 // Rext RawExt // Testing RawExt is tricky, so use standalone test
173 Nmap map[string]bool //don't set this, so we can test for nil
174 Nslice []byte //don't set this, so we can test for nil
175 Nint64 *int64 //don't set this, so we can test for nil
178 type TestStruc struct {
179 // _struct struct{} `json:",omitempty"` //set omitempty for every field
183 Mtsptr map[string]*TestStruc
184 Mts map[string]TestStruc
186 Nteststruc *TestStruc
189 func populateTestStrucCommon(ts *TestStrucCommon, n int, bench, useInterface, useStringKeyOnly bool) {
190 var i64a, i64b, i64c, i64d int64 = 64, 6464, 646464, 64646464
192 // if bench, do not use uint64 values > math.MaxInt64, as bson, etc cannot decode them
194 var a = AnonInTestStruc{
195 // There's more leeway in altering this.
196 AS: strRpt(n, "A-String"),
200 // (U+1D11E)G-clef character may be represented in json as "\uD834\uDD1E".
201 // single reverse solidus character may be represented in json as "\u005C".
202 // include these in ASslice below.
207 strRpt(n, "Afour.reverse_solidus.\u005c"),
208 strRpt(n, "Afive.Gclef.\U0001d11E\"ugorji\"done.")},
210 0, 1, -1, -22, 333, -4444, 55555, -666666,
212 -48, -32, -24, -8, 32, 127, 192, 255,
215 math.MaxInt8, math.MaxInt8 + 4, math.MaxInt8 - 4,
216 math.MaxInt16, math.MaxInt16 + 4, math.MaxInt16 - 4,
217 math.MaxInt32, math.MaxInt32 + 4, math.MaxInt32 - 4,
218 math.MaxInt64, math.MaxInt64 - 4,
219 math.MinInt8, math.MinInt8 + 4, math.MinInt8 - 4,
220 math.MinInt16, math.MinInt16 + 4, math.MinInt16 - 4,
221 math.MinInt32, math.MinInt32 + 4, math.MinInt32 - 4,
222 math.MinInt64, math.MinInt64 + 4,
224 AUi64slice: []uint64{
225 0, 1, 22, 333, 4444, 55555, 666666,
227 math.MaxUint8, math.MaxUint8 + 4, math.MaxUint8 - 4,
228 math.MaxUint16, math.MaxUint16 + 4, math.MaxUint16 - 4,
229 math.MaxUint32, math.MaxUint32 + 4, math.MaxUint32 - 4,
231 AMSU16: map[string]uint16{strRpt(n, "1"): 1, strRpt(n, "22"): 2, strRpt(n, "333"): 3, strRpt(n, "4444"): 4},
233 // Note: +/- inf, NaN, and other non-representable numbers should not be explicitly tested here
235 AF64slice: []float64{
236 11.11e-11, -11.11e+11,
237 2.222E+12, -2.222E-12,
238 -555.55E-5, 555.55E+5,
239 666.66E-6, -666.66E+6,
240 7777.7777E-7, -7777.7777E-7,
241 -8888.8888E+8, 8888.8888E+8,
242 -99999.9999E+9, 99999.9999E+9,
243 // these below are hairy enough to need strconv.ParseFloat
244 33.33E-33, -33.33E+33,
245 44.44e+44, -44.44e-44,
248 // math.Inf(1), math.Inf(-1),
249 math.Pi, math.Phi, math.E,
250 math.MaxFloat64, math.SmallestNonzeroFloat64,
252 AF32slice: []float32{
253 11.11e-11, -11.11e+11,
254 2.222E+12, -2.222E-12,
255 -555.55E-5, 555.55E+5,
256 666.66E-6, -666.66E+6,
257 7777.7777E-7, -7777.7777E-7,
258 -8888.8888E+8, 8888.8888E+8,
259 -99999.9999E+9, 99999.9999E+9,
260 // these below are hairy enough to need strconv.ParseFloat
261 33.33E-33, -33.33E+33,
264 // math.Float32frombits(0x7FF00000), math.Float32frombits(0xFFF00000), //+inf and -inf
265 math.MaxFloat32, math.SmallestNonzeroFloat32,
268 A164slice0: []int64{},
271 AMSU16E: map[string]uint16{},
275 a.AUi64slice = append(a.AUi64slice, math.MaxUint64, math.MaxUint64-4)
277 *ts = TestStrucCommon{
278 S: strRpt(n, `some really really cool names that are nigerian and american like "ugorji melody nwoke" - get it? `),
280 // set the numbers close to the limits
281 I8: math.MaxInt8 * 2 / 3, // 8,
282 I8n: math.MinInt8 * 2 / 3, // 8,
283 I16: math.MaxInt16 * 2 / 3, // 16,
284 I16n: math.MinInt16 * 2 / 3, // 16,
285 I32: math.MaxInt32 * 2 / 3, // 32,
286 I32n: math.MinInt32 * 2 / 3, // 32,
287 I64: math.MaxInt64 * 2 / 3, // 64,
288 I64n: math.MinInt64 * 2 / 3, // 64,
290 Ui64: math.MaxUint64 * 2 / 3, // 64
291 Ui32: math.MaxUint32 * 2 / 3, // 32
292 Ui16: math.MaxUint16 * 2 / 3, // 16
293 Ui8: math.MaxUint8 * 2 / 3, // 8
295 F32: 3.402823e+38, // max representable float32 without losing precision
296 F64: 3.40281991833838838338e+53,
301 Sslice: []string{strRpt(n, "one"), strRpt(n, "two"), strRpt(n, "three")},
302 I64slice: []int64{1111, 2222, 3333},
303 I16slice: []int16{44, 55, 66},
304 Ui64slice: []uint64{12121212, 34343434, 56565656},
305 Ui8slice: []uint8{210, 211, 212},
306 Bslice: []bool{true, false, true, false},
307 Byslice: []byte{13, 14, 15},
309 Msi64: map[string]int64{
312 strRpt(n, "\"three\""): 3,
315 WrapSliceInt64: []uint64{4, 16, 64, 256},
316 WrapSliceString: []string{strRpt(n, "4"), strRpt(n, "16"), strRpt(n, "64"), strRpt(n, "256")},
318 // R: Raw([]byte("goodbye")),
319 // Rext: RawExt{ 120, []byte("hello"), }, // TODO: don't set this - it's hard to test
321 // DecodeNaked bombs here, because the stringUint64T is decoded as a map,
322 // and a map cannot be the key type of a map.
323 // Thus, don't initialize this here.
324 // Msu2wss: map[stringUint64T]wrapStringSlice{
325 // {"5", 5}: []wrapString{"1", "2", "3", "4", "5"},
326 // {"3", 3}: []wrapString{"1", "2", "3"},
329 // make Simplef same as top-level
330 // TODO: should this have slightly different values???
331 Simplef: testSimpleFields{
332 S: strRpt(n, `some really really cool names that are nigerian and american like "ugorji melody nwoke" - get it? `),
334 // set the numbers close to the limits
335 I8: math.MaxInt8 * 2 / 3, // 8,
336 I64: math.MaxInt64 * 2 / 3, // 64,
338 Ui64: math.MaxUint64 * 2 / 3, // 64
339 Ui8: math.MaxUint8 * 2 / 3, // 8
341 F32: 3.402823e+38, // max representable float32 without losing precision
342 F64: 3.40281991833838838338e+53,
346 Sslice: []string{strRpt(n, "one"), strRpt(n, "two"), strRpt(n, "three")},
347 I16slice: []int16{44, 55, 66},
348 Ui64slice: []uint64{12121212, 34343434, 56565656},
349 Ui8slice: []uint8{210, 211, 212},
350 Bslice: []bool{true, false, true, false},
352 Msi64: map[string]int64{
355 strRpt(n, "\"three\""): 3,
358 WrapSliceInt64: []uint64{4, 16, 64, 256},
359 WrapSliceString: []string{strRpt(n, "4"), strRpt(n, "16"), strRpt(n, "64"), strRpt(n, "256")},
362 SstrUi64T: []stringUint64T{{"1", 1}, {"2", 2}, {"3", 3}, {"4", 4}},
368 ts.Ui64 = math.MaxInt64 * 2 / 3
369 ts.Simplef.Ui64 = ts.Ui64
372 //For benchmarks, some things will not work.
374 //json and bson require string keys in maps
375 //ts.M = map[interface{}]interface{}{
379 //gob cannot encode nil in element in array (encodeArray: nil element)
380 ts.Iptrslice = []*int64{nil, &i64a, nil, &i64b, nil, &i64c, nil, &i64d, nil}
381 // ts.Iptrslice = nil
383 if !useStringKeyOnly {
384 // ts.AnonInTestStruc.AMU32F64 = map[uint32]float64{1: 1, 2: 2, 3: 3} // Json/Bson barf
388 func newTestStruc(depth, n int, bench, useInterface, useStringKeyOnly bool) (ts *TestStruc) {
390 populateTestStrucCommon(&ts.TestStrucCommon, n, bench, useInterface, useStringKeyOnly)
393 if ts.Mtsptr == nil {
394 ts.Mtsptr = make(map[string]*TestStruc)
397 ts.Mts = make(map[string]TestStruc)
399 ts.Mtsptr[strRpt(n, "0")] = newTestStruc(depth, n, bench, useInterface, useStringKeyOnly)
400 ts.Mts[strRpt(n, "0")] = *(ts.Mtsptr[strRpt(n, "0")])
401 ts.Its = append(ts.Its, ts.Mtsptr[strRpt(n, "0")])
406 var testStrRptMap = make(map[int]map[string]string)
408 func strRpt(n int, s string) string {
410 // fmt.Printf(">>>> calling strings.Repeat on n: %d, key: %s\n", n, s)
411 return strings.Repeat(s, n)
413 m1, ok := testStrRptMap[n]
415 // fmt.Printf(">>>> making new map for n: %v\n", n)
416 m1 = make(map[string]string)
417 testStrRptMap[n] = m1
421 // fmt.Printf(">>>> creating new entry for key: %s\n", s)
422 v1 = strings.Repeat(s, n)
428 // func wstrRpt(n int, s string) wrapBytes {
429 // return wrapBytes(bytes.Repeat([]byte(s), n))