values_test.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /* // +build testing */
  2. // Copyright (c) 2012-2015 Ugorji Nwoke. All rights reserved.
  3. // Use of this source code is governed by a MIT license found in the LICENSE file.
  4. package codec
  5. // This file contains values used by tests and benchmarks.
  6. // JSON/BSON do not like maps with keys that are not strings,
  7. // so we only use maps with string keys here.
  8. import (
  9. "math"
  10. "time"
  11. )
  12. type wrapSliceUint64 []uint64
  13. type wrapSliceString []string
  14. type wrapUint64 uint64
  15. type wrapString string
  16. type wrapUint64Slice []wrapUint64
  17. type wrapStringSlice []wrapString
  18. type stringUint64T struct {
  19. S string
  20. U uint64
  21. }
  22. type AnonInTestStruc struct {
  23. AS string
  24. AI64 int64
  25. AI16 int16
  26. AUi64 uint64
  27. ASslice []string
  28. AI64slice []int64
  29. AF64slice []float64
  30. // AMI32U32 map[int32]uint32
  31. // AMU32F64 map[uint32]float64 // json/bson do not like it
  32. AMSU16 map[string]uint16
  33. }
  34. type AnonInTestStrucIntf struct {
  35. Islice []interface{}
  36. Ms map[string]interface{}
  37. Nintf interface{} //don't set this, so we can test for nil
  38. T time.Time
  39. }
  40. type testSimpleFields struct {
  41. S string
  42. I64 int64
  43. I32 int32
  44. I16 int16
  45. I8 int8
  46. I64n int64
  47. I32n int32
  48. I16n int16
  49. I8n int8
  50. Ui64 uint64
  51. Ui32 uint32
  52. Ui16 uint16
  53. Ui8 uint8
  54. F64 float64
  55. F32 float32
  56. B bool
  57. By uint8 // byte: msgp doesn't like byte
  58. Sslice []string
  59. I64slice []int64
  60. I16slice []int16
  61. Ui64slice []uint64
  62. Ui8slice []uint8
  63. Bslice []bool
  64. Byslice []byte
  65. Iptrslice []*int64
  66. // TODO: test these separately, specifically for reflection and codecgen.
  67. // Unfortunately, ffjson doesn't support these. Its compilation even fails.
  68. Ui64array [4]uint64
  69. Ui64slicearray []*[4]uint64
  70. WrapSliceInt64 wrapSliceUint64
  71. WrapSliceString wrapSliceString
  72. Msi64 map[string]int64
  73. }
  74. type testStrucCommon struct {
  75. S string
  76. I64 int64
  77. I32 int32
  78. I16 int16
  79. I8 int8
  80. I64n int64
  81. I32n int32
  82. I16n int16
  83. I8n int8
  84. Ui64 uint64
  85. Ui32 uint32
  86. Ui16 uint16
  87. Ui8 uint8
  88. F64 float64
  89. F32 float32
  90. B bool
  91. By uint8 // byte: msgp doesn't like byte
  92. Sslice []string
  93. I64slice []int64
  94. I16slice []int16
  95. Ui64slice []uint64
  96. Ui8slice []uint8
  97. Bslice []bool
  98. Byslice []byte
  99. Iptrslice []*int64
  100. // TODO: test these separately, specifically for reflection and codecgen.
  101. // Unfortunately, ffjson doesn't support these. Its compilation even fails.
  102. Ui64array [4]uint64
  103. Ui64slicearray []*[4]uint64
  104. WrapSliceInt64 wrapSliceUint64
  105. WrapSliceString wrapSliceString
  106. Msi64 map[string]int64
  107. Simplef testSimpleFields
  108. AnonInTestStruc
  109. NotAnon AnonInTestStruc
  110. // make this a ptr, so that it could be set or not.
  111. // for comparison (e.g. with msgp), give it a struct tag (so it is not inlined),
  112. // make this one omitempty (so it is excluded if nil).
  113. *AnonInTestStrucIntf `codec:",omitempty"`
  114. Nmap map[string]bool //don't set this, so we can test for nil
  115. Nslice []byte //don't set this, so we can test for nil
  116. Nint64 *int64 //don't set this, so we can test for nil
  117. }
  118. type TestStruc struct {
  119. _struct struct{} `codec:",omitempty"` //set omitempty for every field
  120. testStrucCommon
  121. Mtsptr map[string]*TestStruc
  122. Mts map[string]TestStruc
  123. Its []*TestStruc
  124. Nteststruc *TestStruc
  125. }
  126. // small struct for testing that codecgen works for unexported types
  127. type tLowerFirstLetter struct {
  128. I int
  129. u uint64
  130. S string
  131. b []byte
  132. }
  133. // Some other types
  134. type Sstring string
  135. type Bbool bool
  136. type Sstructsmall struct {
  137. A int
  138. }
  139. type Sstructbig struct {
  140. A int
  141. B bool
  142. c string
  143. // Sval Sstruct
  144. Ssmallptr *Sstructsmall
  145. Ssmall *Sstructsmall
  146. Sptr *Sstructbig
  147. }
  148. type SstructbigMapBySlice struct {
  149. _struct struct{} `codec:",toarray"`
  150. A int
  151. B bool
  152. c string
  153. // Sval Sstruct
  154. Ssmallptr *Sstructsmall
  155. Ssmall *Sstructsmall
  156. Sptr *Sstructbig
  157. }
  158. type Sinterface interface {
  159. Noop()
  160. }
  161. var testStrucTime = time.Date(2012, 2, 2, 2, 2, 2, 2000, time.UTC).UTC()
  162. func populateTestStrucCommon(ts *testStrucCommon, bench, useInterface, useStringKeyOnly bool) {
  163. var i64a, i64b, i64c, i64d int64 = 64, 6464, 646464, 64646464
  164. var a = AnonInTestStruc{
  165. // There's more leeway in altering this.
  166. AS: "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{"Aone", "Atwo", "Athree",
  174. "Afour.reverse_solidus.\u005c", "Afive.Gclef.\U0001d11E"},
  175. AI64slice: []int64{1, -22, 333, -4444, 55555, -666666},
  176. AMSU16: map[string]uint16{"1": 1, "22": 2, "333": 3, "4444": 4},
  177. AF64slice: []float64{
  178. 11.11e-11, -11.11e+11,
  179. 2.222E+12, -2.222E-12,
  180. -555.55E-5, 555.55E+5,
  181. 666.66E-6, -666.66E+6,
  182. 7777.7777E-7, -7777.7777E-7,
  183. -8888.8888E+8, 8888.8888E+8,
  184. -99999.9999E+9, 99999.9999E+9,
  185. // these below are hairy enough to need strconv.ParseFloat
  186. 33.33E-33, -33.33E+33,
  187. 44.44e+44, -44.44e-44,
  188. },
  189. }
  190. *ts = testStrucCommon{
  191. S: "some string",
  192. // set the numbers close to the limits
  193. I8: math.MaxInt8 * 2 / 3, // 8,
  194. I8n: math.MinInt8 * 2 / 3, // 8,
  195. I16: math.MaxInt16 * 2 / 3, // 16,
  196. I16n: math.MinInt16 * 2 / 3, // 16,
  197. I32: math.MaxInt32 * 2 / 3, // 32,
  198. I32n: math.MinInt32 * 2 / 3, // 32,
  199. I64: math.MaxInt64 * 2 / 3, // 64,
  200. I64n: math.MinInt64 * 2 / 3, // 64,
  201. Ui64: math.MaxUint64 * 2 / 3, // 64
  202. Ui32: math.MaxUint32 * 2 / 3, // 32
  203. Ui16: math.MaxUint16 * 2 / 3, // 16
  204. Ui8: math.MaxUint8 * 2 / 3, // 8
  205. F32: 3.402823e+38, // max representable float32 without losing precision
  206. F64: 3.40281991833838838338e+53,
  207. B: true,
  208. By: 5,
  209. Sslice: []string{"one", "two", "three"},
  210. I64slice: []int64{1111, 2222, 3333},
  211. I16slice: []int16{44, 55, 66},
  212. Ui64slice: []uint64{12121212, 34343434, 56565656},
  213. Ui8slice: []uint8{210, 211, 212},
  214. Bslice: []bool{true, false, true, false},
  215. Byslice: []byte{13, 14, 15},
  216. Msi64: map[string]int64{
  217. "one": 1,
  218. "two": 2,
  219. },
  220. Ui64array: [4]uint64{4, 16, 64, 256},
  221. WrapSliceInt64: []uint64{4, 16, 64, 256},
  222. WrapSliceString: []string{"4", "16", "64", "256"},
  223. // DecodeNaked bombs here, because the stringUint64T is decoded as a map,
  224. // and a map cannot be the key type of a map.
  225. // Thus, don't initialize this here.
  226. // Msu2wss: map[stringUint64T]wrapStringSlice{
  227. // {"5", 5}: []wrapString{"1", "2", "3", "4", "5"},
  228. // {"3", 3}: []wrapString{"1", "2", "3"},
  229. // },
  230. // make Simplef same as top-level
  231. Simplef: testSimpleFields{
  232. S: "some string",
  233. // set the numbers close to the limits
  234. I8: math.MaxInt8 * 2 / 3, // 8,
  235. I8n: math.MinInt8 * 2 / 3, // 8,
  236. I16: math.MaxInt16 * 2 / 3, // 16,
  237. I16n: math.MinInt16 * 2 / 3, // 16,
  238. I32: math.MaxInt32 * 2 / 3, // 32,
  239. I32n: math.MinInt32 * 2 / 3, // 32,
  240. I64: math.MaxInt64 * 2 / 3, // 64,
  241. I64n: math.MinInt64 * 2 / 3, // 64,
  242. Ui64: math.MaxUint64 * 2 / 3, // 64
  243. Ui32: math.MaxUint32 * 2 / 3, // 32
  244. Ui16: math.MaxUint16 * 2 / 3, // 16
  245. Ui8: math.MaxUint8 * 2 / 3, // 8
  246. F32: 3.402823e+38, // max representable float32 without losing precision
  247. F64: 3.40281991833838838338e+53,
  248. B: true,
  249. By: 5,
  250. Sslice: []string{"one", "two", "three"},
  251. I64slice: []int64{1111, 2222, 3333},
  252. I16slice: []int16{44, 55, 66},
  253. Ui64slice: []uint64{12121212, 34343434, 56565656},
  254. Ui8slice: []uint8{210, 211, 212},
  255. Bslice: []bool{true, false, true, false},
  256. Byslice: []byte{13, 14, 15},
  257. Msi64: map[string]int64{
  258. "one": 1,
  259. "two": 2,
  260. },
  261. Ui64array: [4]uint64{4, 16, 64, 256},
  262. WrapSliceInt64: []uint64{4, 16, 64, 256},
  263. WrapSliceString: []string{"4", "16", "64", "256"},
  264. },
  265. AnonInTestStruc: a,
  266. NotAnon: a,
  267. }
  268. ts.Ui64slicearray = []*[4]uint64{&ts.Ui64array, &ts.Ui64array}
  269. if useInterface {
  270. ts.AnonInTestStrucIntf = &AnonInTestStrucIntf{
  271. Islice: []interface{}{"true", true, "no", false, uint64(288), float64(0.4)},
  272. Ms: map[string]interface{}{
  273. "true": "true",
  274. "int64(9)": false,
  275. },
  276. T: testStrucTime,
  277. }
  278. }
  279. //For benchmarks, some things will not work.
  280. if !bench {
  281. //json and bson require string keys in maps
  282. //ts.M = map[interface{}]interface{}{
  283. // true: "true",
  284. // int8(9): false,
  285. //}
  286. //gob cannot encode nil in element in array (encodeArray: nil element)
  287. ts.Iptrslice = []*int64{nil, &i64a, nil, &i64b, nil, &i64c, nil, &i64d, nil}
  288. // ts.Iptrslice = nil
  289. }
  290. if !useStringKeyOnly {
  291. // ts.AnonInTestStruc.AMU32F64 = map[uint32]float64{1: 1, 2: 2, 3: 3} // Json/Bson barf
  292. }
  293. }
  294. func newTestStruc(depth int, bench, useInterface, useStringKeyOnly bool) (ts *TestStruc) {
  295. ts = &TestStruc{}
  296. populateTestStrucCommon(&ts.testStrucCommon, bench, useInterface, useStringKeyOnly)
  297. if depth > 0 {
  298. depth--
  299. if ts.Mtsptr == nil {
  300. ts.Mtsptr = make(map[string]*TestStruc)
  301. }
  302. if ts.Mts == nil {
  303. ts.Mts = make(map[string]TestStruc)
  304. }
  305. ts.Mtsptr["0"] = newTestStruc(depth, bench, useInterface, useStringKeyOnly)
  306. ts.Mts["0"] = *(ts.Mtsptr["0"])
  307. ts.Its = append(ts.Its, ts.Mtsptr["0"])
  308. }
  309. return
  310. }