shared_test.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. // Copyright (c) 2012-2018 Ugorji Nwoke. All rights reserved.
  2. // Use of this source code is governed by a MIT license found in the LICENSE file.
  3. package codec
  4. // This file sets up the variables used, including testInitFns.
  5. // Each file should add initialization that should be performed
  6. // after flags are parsed.
  7. //
  8. // init is a multi-step process:
  9. // - setup vars (handled by init functions in each file)
  10. // - parse flags
  11. // - setup derived vars (handled by pre-init registered functions - registered in init function)
  12. // - post init (handled by post-init registered functions - registered in init function)
  13. // This way, no one has to manage carefully control the initialization
  14. // using file names, etc.
  15. //
  16. // Tests which require external dependencies need the -tag=x parameter.
  17. // They should be run as:
  18. // go test -tags=x -run=. <other parameters ...>
  19. // Benchmarks should also take this parameter, to include the sereal, xdr, etc.
  20. // To run against codecgen, etc, make sure you pass extra parameters.
  21. // Example usage:
  22. // go test "-tags=x codecgen" -bench=. <other parameters ...>
  23. //
  24. // To fully test everything:
  25. // go test -tags=x -benchtime=100ms -tv -bg -bi -brw -bu -v -run=. -bench=.
  26. // Handling flags
  27. // codec_test.go will define a set of global flags for testing, including:
  28. // - Use Reset
  29. // - Use IO reader/writer (vs direct bytes)
  30. // - Set Canonical
  31. // - Set InternStrings
  32. // - Use Symbols
  33. //
  34. // This way, we can test them all by running same set of tests with a different
  35. // set of flags.
  36. //
  37. // Following this, all the benchmarks will utilize flags set by codec_test.go
  38. // and will not redefine these "global" flags.
  39. import (
  40. "bytes"
  41. "flag"
  42. "fmt"
  43. "io"
  44. "io/ioutil"
  45. "log"
  46. "sync"
  47. "testing"
  48. )
  49. // __DO_NOT_REMOVE__NEEDED_FOR_REPLACING__IMPORT_PATH__FOR_CODEC_BENCH__
  50. type testHED struct {
  51. H Handle
  52. E *Encoder
  53. D *Decoder
  54. }
  55. type ioReaderWrapper struct {
  56. r io.Reader
  57. }
  58. func (x ioReaderWrapper) Read(p []byte) (n int, err error) {
  59. return x.r.Read(p)
  60. }
  61. type ioWriterWrapper struct {
  62. w io.Writer
  63. }
  64. func (x ioWriterWrapper) Write(p []byte) (n int, err error) {
  65. return x.w.Write(p)
  66. }
  67. var (
  68. // testNoopH = NoopHandle(8)
  69. testMsgpackH = &MsgpackHandle{}
  70. testBincH = &BincHandle{}
  71. testSimpleH = &SimpleHandle{}
  72. testCborH = &CborHandle{}
  73. testJsonH = &JsonHandle{}
  74. testHandles []Handle
  75. testPreInitFns []func()
  76. testPostInitFns []func()
  77. testOnce sync.Once
  78. testHEDs []testHED
  79. )
  80. // flag variables used by tests (and bench)
  81. var (
  82. testDepth int
  83. testVerbose bool
  84. testInitDebug bool
  85. testStructToArray bool
  86. testCanonical bool
  87. testUseReset bool
  88. testSkipIntf bool
  89. testInternStr bool
  90. testUseMust bool
  91. testCheckCircRef bool
  92. testUseIoEncDec int
  93. testUseIoWrapper bool
  94. testMaxInitLen int
  95. testNumRepeatString int
  96. testRpcBufsize int
  97. )
  98. // variables that are not flags, but which can configure the handles
  99. var (
  100. testEncodeOptions EncodeOptions
  101. testDecodeOptions DecodeOptions
  102. )
  103. // flag variables used by bench
  104. var (
  105. benchDoInitBench bool
  106. benchVerify bool
  107. benchUnscientificRes bool = false
  108. benchMapStringKeyOnly bool
  109. //depth of 0 maps to ~400bytes json-encoded string, 1 maps to ~1400 bytes, etc
  110. //For depth>1, we likely trigger stack growth for encoders, making benchmarking unreliable.
  111. benchDepth int
  112. benchInitDebug bool
  113. )
  114. func init() {
  115. log.SetOutput(ioutil.Discard) // don't allow things log to standard out/err
  116. testHEDs = make([]testHED, 0, 32)
  117. testHandles = append(testHandles,
  118. // testNoopH,
  119. testMsgpackH, testBincH, testSimpleH, testCborH, testJsonH)
  120. // JSON should do HTMLCharsAsIs by default
  121. testJsonH.HTMLCharsAsIs = true
  122. // set ExplicitRelease on each handle
  123. testMsgpackH.ExplicitRelease = true
  124. testBincH.ExplicitRelease = true
  125. testSimpleH.ExplicitRelease = true
  126. testCborH.ExplicitRelease = true
  127. testJsonH.ExplicitRelease = true
  128. testInitFlags()
  129. benchInitFlags()
  130. }
  131. func testInitFlags() {
  132. // delete(testDecOpts.ExtFuncs, timeTyp)
  133. flag.IntVar(&testDepth, "tsd", 0, "Test Struc Depth")
  134. flag.BoolVar(&testVerbose, "tv", false, "Test Verbose (no longer used - here for compatibility)")
  135. flag.BoolVar(&testInitDebug, "tg", false, "Test Init Debug")
  136. flag.IntVar(&testUseIoEncDec, "ti", -1, "Use IO Reader/Writer for Marshal/Unmarshal ie >= 0")
  137. flag.BoolVar(&testUseIoWrapper, "tiw", false, "Wrap the IO Reader/Writer with a base pass-through reader/writer")
  138. flag.BoolVar(&testStructToArray, "ts", false, "Set StructToArray option")
  139. flag.BoolVar(&testCanonical, "tc", false, "Set Canonical option")
  140. flag.BoolVar(&testInternStr, "te", false, "Set InternStr option")
  141. flag.BoolVar(&testSkipIntf, "tf", false, "Skip Interfaces")
  142. flag.BoolVar(&testUseReset, "tr", false, "Use Reset")
  143. flag.IntVar(&testNumRepeatString, "trs", 8, "Create string variables by repeating a string N times")
  144. flag.IntVar(&testMaxInitLen, "tx", 0, "Max Init Len")
  145. flag.BoolVar(&testUseMust, "tm", true, "Use Must(En|De)code")
  146. flag.BoolVar(&testCheckCircRef, "tl", false, "Use Check Circular Ref")
  147. }
  148. func benchInitFlags() {
  149. flag.BoolVar(&benchMapStringKeyOnly, "bs", false, "Bench use maps with string keys only")
  150. flag.BoolVar(&benchInitDebug, "bg", false, "Bench Debug")
  151. flag.IntVar(&benchDepth, "bd", 1, "Bench Depth")
  152. flag.BoolVar(&benchDoInitBench, "bi", false, "Run Bench Init")
  153. flag.BoolVar(&benchVerify, "bv", false, "Verify Decoded Value during Benchmark")
  154. flag.BoolVar(&benchUnscientificRes, "bu", false, "Show Unscientific Results during Benchmark")
  155. }
  156. func testHEDGet(h Handle) *testHED {
  157. for i := range testHEDs {
  158. v := &testHEDs[i]
  159. if v.H == h {
  160. return v
  161. }
  162. }
  163. testHEDs = append(testHEDs, testHED{h, NewEncoder(nil, h), NewDecoder(nil, h)})
  164. return &testHEDs[len(testHEDs)-1]
  165. }
  166. func testReinit() {
  167. testOnce = sync.Once{}
  168. testHEDs = nil
  169. }
  170. func testInitAll() {
  171. // only parse it once.
  172. if !flag.Parsed() {
  173. flag.Parse()
  174. }
  175. for _, f := range testPreInitFns {
  176. f()
  177. }
  178. for _, f := range testPostInitFns {
  179. f()
  180. }
  181. }
  182. func sTestCodecEncode(ts interface{}, bsIn []byte, fn func([]byte) *bytes.Buffer,
  183. h Handle, bh *BasicHandle) (bs []byte, err error) {
  184. // bs = make([]byte, 0, approxSize)
  185. var e *Encoder
  186. var buf *bytes.Buffer
  187. if testUseReset {
  188. e = testHEDGet(h).E
  189. } else {
  190. e = NewEncoder(nil, h)
  191. }
  192. var oldWriteBufferSize int
  193. if testUseIoEncDec >= 0 {
  194. buf = fn(bsIn)
  195. // set the encode options for using a buffer
  196. oldWriteBufferSize = bh.WriterBufferSize
  197. bh.WriterBufferSize = testUseIoEncDec
  198. if testUseIoWrapper {
  199. e.Reset(ioWriterWrapper{buf})
  200. } else {
  201. e.Reset(buf)
  202. }
  203. } else {
  204. bs = bsIn
  205. e.ResetBytes(&bs)
  206. }
  207. if testUseMust {
  208. e.MustEncode(ts)
  209. } else {
  210. err = e.Encode(ts)
  211. }
  212. if testUseIoEncDec >= 0 {
  213. bs = buf.Bytes()
  214. bh.WriterBufferSize = oldWriteBufferSize
  215. }
  216. if !testUseReset {
  217. e.Release()
  218. }
  219. return
  220. }
  221. func sTestCodecDecode(bs []byte, ts interface{}, h Handle, bh *BasicHandle) (err error) {
  222. var d *Decoder
  223. // var buf *bytes.Reader
  224. if testUseReset {
  225. d = testHEDGet(h).D
  226. } else {
  227. d = NewDecoder(nil, h)
  228. }
  229. var oldReadBufferSize int
  230. if testUseIoEncDec >= 0 {
  231. buf := bytes.NewReader(bs)
  232. oldReadBufferSize = bh.ReaderBufferSize
  233. bh.ReaderBufferSize = testUseIoEncDec
  234. if testUseIoWrapper {
  235. d.Reset(ioReaderWrapper{buf})
  236. } else {
  237. d.Reset(buf)
  238. }
  239. } else {
  240. d.ResetBytes(bs)
  241. }
  242. if testUseMust {
  243. d.MustDecode(ts)
  244. } else {
  245. err = d.Decode(ts)
  246. }
  247. if testUseIoEncDec >= 0 {
  248. bh.ReaderBufferSize = oldReadBufferSize
  249. }
  250. if !testUseReset {
  251. d.Release()
  252. }
  253. return
  254. }
  255. // --- functions below are used by both benchmarks and tests
  256. func logT(x interface{}, format string, args ...interface{}) {
  257. if t, ok := x.(*testing.T); ok && t != nil {
  258. t.Logf(format, args...)
  259. } else if b, ok := x.(*testing.B); ok && b != nil {
  260. b.Logf(format, args...)
  261. } else { // if testing.Verbose() { // if testVerbose {
  262. if len(format) == 0 || format[len(format)-1] != '\n' {
  263. format = format + "\n"
  264. }
  265. fmt.Printf(format, args...)
  266. }
  267. }
  268. // --- functions below are used only by benchmarks alone
  269. func fnBenchmarkByteBuf(bsIn []byte) (buf *bytes.Buffer) {
  270. // var buf bytes.Buffer
  271. // buf.Grow(approxSize)
  272. buf = bytes.NewBuffer(bsIn)
  273. buf.Truncate(0)
  274. return
  275. }
  276. // func benchFnCodecEncode(ts interface{}, bsIn []byte, h Handle) (bs []byte, err error) {
  277. // return testCodecEncode(ts, bsIn, fnBenchmarkByteBuf, h)
  278. // }
  279. // func benchFnCodecDecode(bs []byte, ts interface{}, h Handle) (err error) {
  280. // return testCodecDecode(bs, ts, h)
  281. // }