values_flex_test.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. // comment this out // // + build testing
  2. // Copyright (c) 2012-2018 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. import (
  6. "strconv"
  7. "strings"
  8. "time"
  9. )
  10. const teststrucflexChanCap = 64
  11. // This file contains values used by tests alone.
  12. // This is where we may try out different things,
  13. // that other engines may not support or may barf upon
  14. // e.g. custom extensions for wrapped types, maps with non-string keys, etc.
  15. // some funky types to test codecgen
  16. type codecgenA struct {
  17. ZZ []byte
  18. }
  19. type codecgenB struct {
  20. AA codecgenA
  21. }
  22. type codecgenC struct {
  23. _struct struct{} `codec:",omitempty"`
  24. BB codecgenB
  25. }
  26. type TestCodecgenG struct {
  27. TestCodecgenG int
  28. }
  29. type codecgenH struct {
  30. TestCodecgenG
  31. }
  32. type codecgenI struct {
  33. codecgenH
  34. }
  35. type codecgenK struct {
  36. X int
  37. Y string
  38. }
  39. type codecgenL struct {
  40. X int
  41. Y uint32
  42. }
  43. type codecgenM struct {
  44. codecgenK
  45. codecgenL
  46. }
  47. // some types to test struct keytype
  48. type testStrucKeyTypeT0 struct {
  49. _struct struct{}
  50. F int
  51. }
  52. type testStrucKeyTypeT1 struct {
  53. _struct struct{} `codec:",string"`
  54. F int `codec:"FFFF"`
  55. }
  56. type testStrucKeyTypeT2 struct {
  57. _struct struct{} `codec:",int"`
  58. F int `codec:"-1"`
  59. }
  60. type testStrucKeyTypeT3 struct {
  61. _struct struct{} `codec:",uint"`
  62. F int `codec:"1"`
  63. }
  64. type testStrucKeyTypeT4 struct {
  65. _struct struct{} `codec:",float"`
  66. F int `codec:"2.5"`
  67. }
  68. // Some unused types just stored here
  69. type Bbool bool
  70. type Aarray [1]string
  71. type Sstring string
  72. type Sstructsmall struct {
  73. A int
  74. }
  75. type Sstructbig struct {
  76. A int
  77. B bool
  78. c string
  79. // Sval Sstruct
  80. Ssmallptr *Sstructsmall
  81. Ssmall *Sstructsmall
  82. Sptr *Sstructbig
  83. }
  84. type SstructbigMapBySlice struct {
  85. _struct struct{} `codec:",toarray"`
  86. A int
  87. B bool
  88. c string
  89. // Sval Sstruct
  90. Ssmallptr *Sstructsmall
  91. Ssmall *Sstructsmall
  92. Sptr *Sstructbig
  93. }
  94. // small struct for testing that codecgen works for unexported types
  95. type tLowerFirstLetter struct {
  96. I int
  97. u uint64
  98. S string
  99. b []byte
  100. }
  101. // Some used types
  102. type wrapInt64 int64
  103. type wrapUint8 uint8
  104. type wrapBytes []uint8
  105. type AnonInTestStrucIntf struct {
  106. Islice []interface{}
  107. Ms map[string]interface{}
  108. Nintf interface{} //don't set this, so we can test for nil
  109. T time.Time
  110. Tptr *time.Time
  111. }
  112. type missingFielderT1 struct {
  113. S string
  114. B bool
  115. f float64
  116. i int64
  117. }
  118. func (t *missingFielderT1) CodecMissingField(field []byte, value interface{}) bool {
  119. switch string(field) {
  120. case "F":
  121. t.f = value.(float64)
  122. case "I":
  123. t.i = value.(int64)
  124. default:
  125. return false
  126. }
  127. return true
  128. }
  129. func (t *missingFielderT1) CodecMissingFields() map[string]interface{} {
  130. return map[string]interface{}{"F": t.f, "I": t.i}
  131. }
  132. type missingFielderT2 struct {
  133. S string
  134. B bool
  135. F float64
  136. I int64
  137. }
  138. type testSelfExtHelper struct {
  139. S string
  140. I int64
  141. B bool
  142. }
  143. type TestSelfExtImpl struct {
  144. testSelfExtHelper
  145. }
  146. type TestSelfExtImpl2 struct {
  147. M string
  148. O bool
  149. }
  150. type TestTwoNakedInterfaces struct {
  151. A interface{}
  152. B interface{}
  153. }
  154. var testWRepeated512 wrapBytes
  155. var testStrucTime = time.Date(2012, 2, 2, 2, 2, 2, 2000, time.UTC).UTC()
  156. func init() {
  157. var testARepeated512 [512]byte
  158. for i := range testARepeated512 {
  159. testARepeated512[i] = 'A'
  160. }
  161. testWRepeated512 = wrapBytes(testARepeated512[:])
  162. }
  163. type TestStrucFlex struct {
  164. _struct struct{} `codec:",omitempty"` //set omitempty for every field
  165. TestStrucCommon
  166. Chstr chan string
  167. Mis map[int]string
  168. Mbu64 map[bool]struct{}
  169. Miwu64s map[int]wrapUint64Slice
  170. Mfwss map[float64]wrapStringSlice
  171. Mf32wss map[float32]wrapStringSlice
  172. Mui2wss map[uint64]wrapStringSlice
  173. // DecodeNaked bombs because stringUint64T is decoded as a map,
  174. // and a map cannot be the key type of a map.
  175. // Ensure this is set to nil if decoding into a nil interface{}.
  176. Msu2wss map[stringUint64T]wrapStringSlice
  177. Ci64 wrapInt64
  178. Swrapbytes []wrapBytes
  179. Swrapuint8 []wrapUint8
  180. ArrStrUi64T [4]stringUint64T
  181. Ui64array [4]uint64
  182. Ui64slicearray []*[4]uint64
  183. SintfAarray []interface{}
  184. // Ensure this is set to nil if decoding into a nil interface{}.
  185. MstrUi64TSelf map[stringUint64T]*stringUint64T
  186. // make this a ptr, so that it could be set or not.
  187. // for comparison (e.g. with msgp), give it a struct tag (so it is not inlined),
  188. // make this one omitempty (so it is excluded if nil).
  189. *AnonInTestStrucIntf `json:",omitempty"`
  190. //M map[interface{}]interface{} `json:"-",bson:"-"`
  191. Mtsptr map[string]*TestStrucFlex
  192. Mts map[string]TestStrucFlex
  193. Its []*TestStrucFlex
  194. Nteststruc *TestStrucFlex
  195. }
  196. func emptyTestStrucFlex() *TestStrucFlex {
  197. var ts TestStrucFlex
  198. // we initialize and start draining the chan, so that we can decode into it without it blocking due to no consumer
  199. ts.Chstr = make(chan string, teststrucflexChanCap)
  200. go func() {
  201. for range ts.Chstr {
  202. }
  203. }() // drain it
  204. return &ts
  205. }
  206. func newTestStrucFlex(depth, n int, bench, useInterface, useStringKeyOnly bool) (ts *TestStrucFlex) {
  207. ts = &TestStrucFlex{
  208. Chstr: make(chan string, teststrucflexChanCap),
  209. Miwu64s: map[int]wrapUint64Slice{
  210. 5: []wrapUint64{1, 2, 3, 4, 5},
  211. 3: []wrapUint64{1, 2, 3},
  212. },
  213. Mf32wss: map[float32]wrapStringSlice{
  214. 5.0: []wrapString{"1.0", "2.0", "3.0", "4.0", "5.0"},
  215. 3.0: []wrapString{"1.0", "2.0", "3.0"},
  216. },
  217. Mui2wss: map[uint64]wrapStringSlice{
  218. 5: []wrapString{"1.0", "2.0", "3.0", "4.0", "5.0"},
  219. 3: []wrapString{"1.0", "2.0", "3.0"},
  220. },
  221. Mfwss: map[float64]wrapStringSlice{
  222. 5.0: []wrapString{"1.0", "2.0", "3.0", "4.0", "5.0"},
  223. 3.0: []wrapString{"1.0", "2.0", "3.0"},
  224. },
  225. // DecodeNaked bombs here, because the stringUint64T is decoded as a map,
  226. // and a map cannot be the key type of a map.
  227. // Ensure this is set to nil if decoding into a nil interface{}.
  228. Msu2wss: map[stringUint64T]wrapStringSlice{
  229. stringUint64T{"5", 5}: []wrapString{"1", "2", "3", "4", "5"},
  230. stringUint64T{"3", 3}: []wrapString{"1", "2", "3"},
  231. },
  232. Mis: map[int]string{
  233. 1: "one",
  234. 22: "twenty two",
  235. -44: "minus forty four",
  236. },
  237. Mbu64: map[bool]struct{}{false: {}, true: {}},
  238. Ci64: -22,
  239. Swrapbytes: []wrapBytes{ // lengths of 1, 2, 4, 8, 16, 32, 64, 128, 256,
  240. testWRepeated512[:1],
  241. testWRepeated512[:2],
  242. testWRepeated512[:4],
  243. testWRepeated512[:8],
  244. testWRepeated512[:16],
  245. testWRepeated512[:32],
  246. testWRepeated512[:64],
  247. testWRepeated512[:128],
  248. testWRepeated512[:256],
  249. testWRepeated512[:512],
  250. },
  251. Swrapuint8: []wrapUint8{
  252. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
  253. },
  254. Ui64array: [4]uint64{4, 16, 64, 256},
  255. ArrStrUi64T: [4]stringUint64T{{"4", 4}, {"3", 3}, {"2", 2}, {"1", 1}},
  256. SintfAarray: []interface{}{Aarray{"s"}},
  257. MstrUi64TSelf: make(map[stringUint64T]*stringUint64T, numStrUi64T),
  258. }
  259. for i := uint64(0); i < numStrUi64T; i++ {
  260. ss := stringUint64T{S: strings.Repeat(strconv.FormatUint(i, 10), 4), U: i}
  261. // Ensure this is set to nil if decoding into a nil interface{}.
  262. ts.MstrUi64TSelf[ss] = &ss
  263. }
  264. numChanSend := cap(ts.Chstr) / 4 // 8
  265. for i := 0; i < numChanSend; i++ {
  266. ts.Chstr <- strings.Repeat("A", i+1)
  267. }
  268. ts.Ui64slicearray = []*[4]uint64{&ts.Ui64array, &ts.Ui64array}
  269. if useInterface {
  270. ts.AnonInTestStrucIntf = &AnonInTestStrucIntf{
  271. Islice: []interface{}{strRpt(n, "true"), true, strRpt(n, "no"), false, uint64(288), float64(0.4)},
  272. Ms: map[string]interface{}{
  273. strRpt(n, "true"): strRpt(n, "true"),
  274. strRpt(n, "int64(9)"): false,
  275. },
  276. T: testStrucTime,
  277. }
  278. }
  279. populateTestStrucCommon(&ts.TestStrucCommon, n, bench, useInterface, useStringKeyOnly)
  280. if depth > 0 {
  281. depth--
  282. if ts.Mtsptr == nil {
  283. ts.Mtsptr = make(map[string]*TestStrucFlex)
  284. }
  285. if ts.Mts == nil {
  286. ts.Mts = make(map[string]TestStrucFlex)
  287. }
  288. ts.Mtsptr["0"] = newTestStrucFlex(depth, n, bench, useInterface, useStringKeyOnly)
  289. ts.Mts["0"] = *(ts.Mtsptr["0"])
  290. ts.Its = append(ts.Its, ts.Mtsptr["0"])
  291. }
  292. return
  293. }