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