jsoniter_int_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // +build go1.8
  2. package misc_tests
  3. import (
  4. "bytes"
  5. "encoding/json"
  6. "io"
  7. "io/ioutil"
  8. "math/rand"
  9. "strconv"
  10. "testing"
  11. "github.com/json-iterator/go"
  12. "github.com/stretchr/testify/require"
  13. )
  14. func Test_read_uint64_invalid(t *testing.T) {
  15. should := require.New(t)
  16. iter := jsoniter.ParseString(jsoniter.ConfigDefault, ",")
  17. iter.ReadUint64()
  18. should.NotNil(iter.Error)
  19. }
  20. func Test_read_int32_array(t *testing.T) {
  21. should := require.New(t)
  22. input := `[123,456,789]`
  23. val := make([]int32, 0)
  24. jsoniter.UnmarshalFromString(input, &val)
  25. should.Equal(3, len(val))
  26. }
  27. func Test_read_int64_array(t *testing.T) {
  28. should := require.New(t)
  29. input := `[123,456,789]`
  30. val := make([]int64, 0)
  31. jsoniter.UnmarshalFromString(input, &val)
  32. should.Equal(3, len(val))
  33. }
  34. func Test_wrap_int(t *testing.T) {
  35. should := require.New(t)
  36. str, err := jsoniter.MarshalToString(jsoniter.WrapInt64(100))
  37. should.Nil(err)
  38. should.Equal("100", str)
  39. }
  40. func Test_write_val_int(t *testing.T) {
  41. should := require.New(t)
  42. buf := &bytes.Buffer{}
  43. stream := jsoniter.NewStream(jsoniter.ConfigDefault, buf, 4096)
  44. stream.WriteVal(1001)
  45. stream.Flush()
  46. should.Nil(stream.Error)
  47. should.Equal("1001", buf.String())
  48. }
  49. func Test_write_val_int_ptr(t *testing.T) {
  50. should := require.New(t)
  51. buf := &bytes.Buffer{}
  52. stream := jsoniter.NewStream(jsoniter.ConfigDefault, buf, 4096)
  53. val := 1001
  54. stream.WriteVal(&val)
  55. stream.Flush()
  56. should.Nil(stream.Error)
  57. should.Equal("1001", buf.String())
  58. }
  59. func Test_float_as_int(t *testing.T) {
  60. should := require.New(t)
  61. var i int
  62. should.NotNil(jsoniter.Unmarshal([]byte(`1.1`), &i))
  63. }
  64. // chunkedData is io.Reader which returns random amount of data in range [1, chunkedData.chunkSize].
  65. // It simulates chunked data on from HTTP server, which is commonly used by net/http package.
  66. type chunkedData struct {
  67. chunkSize int
  68. data []byte
  69. head int
  70. }
  71. // Read is implementation of the io.Reader which returns random amount of data in range [1, chunkedData.chunkSize].
  72. func (c *chunkedData) Read(p []byte) (n int, err error) {
  73. to := c.head + int(rand.Int31n(int32(c.chunkSize))+1)
  74. // copy does not copy more data then p can consume
  75. n = copy(p, c.data[c.head:to])
  76. c.head = c.head + n
  77. if c.head >= len(c.data) {
  78. err = io.EOF
  79. }
  80. return n, err
  81. }
  82. // TestIterator_ReadInt_chunkedInput validates the behaviour of Iterator.ReadInt() method in where:
  83. // - it reads data from io.Reader,
  84. // - expected value is 0 (zero)
  85. // - Iterator.tail == Iterator.head
  86. // - Iterator.tail < len(Iterator.buf)
  87. // - value in buffer after Iterator.tail is presented from previous read and has '.' character.
  88. func TestIterator_ReadInt_chunkedInput(t *testing.T) {
  89. should := require.New(t)
  90. data := &chunkedData{
  91. data: jsonFloatIntArray(t, 10),
  92. }
  93. // because this test is rely on randomness of chunkedData, we are doing multiple iterations to
  94. // be sure, that we can hit a required case.
  95. for data.chunkSize = 3; data.chunkSize <= len(data.data); data.chunkSize++ {
  96. data.head = 0
  97. iter := jsoniter.Parse(jsoniter.ConfigDefault, data, data.chunkSize)
  98. i := 0
  99. for iter.ReadArray() {
  100. // every even item is float, let's just skip it.
  101. if i%2 == 0 {
  102. iter.Skip()
  103. i++
  104. continue
  105. }
  106. should.Zero(iter.ReadInt())
  107. should.NoError(iter.Error)
  108. i++
  109. }
  110. }
  111. }
  112. // jsonFloatIntArray generates JSON array where every
  113. // - even item is float 0.1
  114. // - odd item is integer 0
  115. //
  116. // [0.1, 0, 0.1, 0]
  117. func jsonFloatIntArray(t *testing.T, numberOfItems int) []byte {
  118. t.Helper()
  119. numbers := make([]jsoniter.Any, numberOfItems)
  120. for i := range numbers {
  121. switch i % 2 {
  122. case 0:
  123. numbers[i] = jsoniter.WrapFloat64(0.1)
  124. default:
  125. numbers[i] = jsoniter.WrapInt64(0)
  126. }
  127. }
  128. fixture, err := jsoniter.ConfigFastest.Marshal(numbers)
  129. if err != nil {
  130. panic(err)
  131. }
  132. b := &bytes.Buffer{}
  133. require.NoError(
  134. t,
  135. json.Compact(b, fixture),
  136. "json should be compactable",
  137. )
  138. return b.Bytes()
  139. }
  140. func Benchmark_jsoniter_encode_int(b *testing.B) {
  141. stream := jsoniter.NewStream(jsoniter.ConfigDefault, ioutil.Discard, 64)
  142. for n := 0; n < b.N; n++ {
  143. stream.Reset(nil)
  144. stream.WriteUint64(0xffffffff)
  145. }
  146. }
  147. func Benchmark_itoa(b *testing.B) {
  148. for n := 0; n < b.N; n++ {
  149. strconv.FormatInt(0xffffffff, 10)
  150. }
  151. }
  152. func Benchmark_jsoniter_int(b *testing.B) {
  153. iter := jsoniter.NewIterator(jsoniter.ConfigDefault)
  154. input := []byte(`100`)
  155. for n := 0; n < b.N; n++ {
  156. iter.ResetBytes(input)
  157. iter.ReadInt64()
  158. }
  159. }
  160. func Benchmark_json_int(b *testing.B) {
  161. for n := 0; n < b.N; n++ {
  162. result := int64(0)
  163. json.Unmarshal([]byte(`-100`), &result)
  164. }
  165. }