jsoniter_string_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // +build go1.8
  2. package jsoniter
  3. import (
  4. "bytes"
  5. "encoding/json"
  6. "fmt"
  7. "testing"
  8. "unicode/utf8"
  9. "github.com/stretchr/testify/require"
  10. )
  11. func Test_read_string(t *testing.T) {
  12. badInputs := []string{
  13. ``,
  14. `"`,
  15. `"\"`,
  16. `"\\\"`,
  17. "\"\n\"",
  18. }
  19. for i :=0; i < 32; i++ {
  20. // control characters are invalid
  21. badInputs = append(badInputs, string([]byte{'"', byte(i), '"'}))
  22. }
  23. for _, input := range badInputs {
  24. testReadString(t, input, "", true, "json.Unmarshal", json.Unmarshal)
  25. testReadString(t, input, "", true, "jsoniter.Unmarshal", Unmarshal)
  26. testReadString(t, input, "", true, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", ConfigCompatibleWithStandardLibrary.Unmarshal)
  27. }
  28. goodInputs := []struct {
  29. input string
  30. expectValue string
  31. }{
  32. {`""`, ""},
  33. {`"a"`, "a"},
  34. {`null`, ""},
  35. {`"Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"`, "Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"},
  36. }
  37. for _, tc := range goodInputs {
  38. testReadString(t, tc.input, tc.expectValue, false, "json.Unmarshal", json.Unmarshal)
  39. testReadString(t, tc.input, tc.expectValue, false, "jsoniter.Unmarshal", Unmarshal)
  40. testReadString(t, tc.input, tc.expectValue, false, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", ConfigCompatibleWithStandardLibrary.Unmarshal)
  41. }
  42. }
  43. func testReadString(t *testing.T, input string, expectValue string, expectError bool, marshalerName string, marshaler func([]byte, interface{}) error) {
  44. var value string
  45. err := marshaler([]byte(input), &value)
  46. if expectError != (err != nil) {
  47. t.Errorf("%q: %s: expected error %v, got %v", input, marshalerName, expectError, err)
  48. return
  49. }
  50. if value != expectValue {
  51. t.Errorf("%q: %s: expected %q, got %q", input, marshalerName, expectValue, value)
  52. return
  53. }
  54. }
  55. func Test_read_normal_string(t *testing.T) {
  56. cases := map[string]string{
  57. `"0123456789012345678901234567890123456789"`: `0123456789012345678901234567890123456789`,
  58. `""`: ``,
  59. `"hello"`: `hello`,
  60. }
  61. for input, output := range cases {
  62. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  63. should := require.New(t)
  64. iter := ParseString(ConfigDefault, input)
  65. should.Equal(output, iter.ReadString())
  66. })
  67. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  68. should := require.New(t)
  69. iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
  70. should.Equal(output, iter.ReadString())
  71. })
  72. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  73. should := require.New(t)
  74. iter := ParseString(ConfigDefault, input)
  75. should.Equal(output, string(iter.ReadStringAsSlice()))
  76. })
  77. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  78. should := require.New(t)
  79. iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
  80. should.Equal(output, string(iter.ReadStringAsSlice()))
  81. })
  82. }
  83. }
  84. func Test_read_exotic_string(t *testing.T) {
  85. cases := map[string]string{
  86. `"hel\"lo"`: `hel"lo`,
  87. `"hel\nlo"`: "hel\nlo",
  88. `"\u4e2d\u6587"`: "中文",
  89. `"\ud83d\udc4a"`: "\xf0\x9f\x91\x8a", // surrogate
  90. }
  91. for input, output := range cases {
  92. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  93. should := require.New(t)
  94. iter := ParseString(ConfigDefault, input)
  95. should.Equal(output, iter.ReadString())
  96. })
  97. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  98. should := require.New(t)
  99. iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
  100. should.Equal(output, iter.ReadString())
  101. })
  102. }
  103. }
  104. func Test_read_string_as_interface(t *testing.T) {
  105. should := require.New(t)
  106. iter := ParseString(ConfigDefault, `"hello"`)
  107. should.Equal("hello", iter.Read())
  108. }
  109. func Test_write_string(t *testing.T) {
  110. should := require.New(t)
  111. str, err := MarshalToString("hello")
  112. should.Equal(`"hello"`, str)
  113. should.Nil(err)
  114. str, err = MarshalToString(`hel"lo`)
  115. should.Equal(`"hel\"lo"`, str)
  116. should.Nil(err)
  117. }
  118. func Test_write_val_string(t *testing.T) {
  119. should := require.New(t)
  120. buf := &bytes.Buffer{}
  121. stream := NewStream(ConfigDefault, buf, 4096)
  122. stream.WriteVal("hello")
  123. stream.Flush()
  124. should.Nil(stream.Error)
  125. should.Equal(`"hello"`, buf.String())
  126. }
  127. func Test_decode_slash(t *testing.T) {
  128. should := require.New(t)
  129. var obj interface{}
  130. should.NotNil(json.Unmarshal([]byte("\\"), &obj))
  131. should.NotNil(UnmarshalFromString("\\", &obj))
  132. }
  133. func Test_html_escape(t *testing.T) {
  134. should := require.New(t)
  135. output, err := json.Marshal(`>`)
  136. should.Nil(err)
  137. should.Equal(`"\u003e"`, string(output))
  138. output, err = ConfigCompatibleWithStandardLibrary.Marshal(`>`)
  139. should.Nil(err)
  140. should.Equal(`"\u003e"`, string(output))
  141. type MyString string
  142. output, err = ConfigCompatibleWithStandardLibrary.Marshal(MyString(`>`))
  143. should.Nil(err)
  144. should.Equal(`"\u003e"`, string(output))
  145. }
  146. func Test_string_encode_with_std(t *testing.T) {
  147. should := require.New(t)
  148. for i := 0; i < utf8.RuneSelf; i++ {
  149. input := string([]byte{byte(i)})
  150. stdOutputBytes, err := json.Marshal(input)
  151. should.Nil(err)
  152. stdOutput := string(stdOutputBytes)
  153. jsoniterOutputBytes, err := ConfigCompatibleWithStandardLibrary.Marshal(input)
  154. should.Nil(err)
  155. jsoniterOutput := string(jsoniterOutputBytes)
  156. should.Equal(stdOutput, jsoniterOutput)
  157. }
  158. }
  159. func Test_unicode(t *testing.T) {
  160. should := require.New(t)
  161. output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"})
  162. should.Equal(`{"a":"数字山谷"}`, output)
  163. output, _ = Config{EscapeHTML: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"})
  164. should.Equal(`{"a":"数字山谷"}`, output)
  165. }
  166. func Test_unicode_and_escape(t *testing.T) {
  167. should := require.New(t)
  168. output, err := MarshalToString(`"数字山谷"`)
  169. should.Nil(err)
  170. should.Equal(`"\"数字山谷\""`, output)
  171. output, err = ConfigFastest.MarshalToString(`"数字山谷"`)
  172. should.Nil(err)
  173. should.Equal(`"\"数字山谷\""`, output)
  174. }
  175. func Test_unsafe_unicode(t *testing.T) {
  176. ConfigDefault.(*frozenConfig).cleanEncoders()
  177. should := require.New(t)
  178. output, err := ConfigDefault.MarshalToString("he\u2029\u2028he")
  179. should.Nil(err)
  180. should.Equal(`"he\u2029\u2028he"`, output)
  181. output, err = ConfigFastest.MarshalToString("he\u2029\u2028he")
  182. should.Nil(err)
  183. should.Equal("\"he\u2029\u2028he\"", output)
  184. }
  185. func Benchmark_jsoniter_unicode(b *testing.B) {
  186. for n := 0; n < b.N; n++ {
  187. iter := ParseString(ConfigDefault, `"\ud83d\udc4a"`)
  188. iter.ReadString()
  189. }
  190. }
  191. func Benchmark_jsoniter_ascii(b *testing.B) {
  192. iter := NewIterator(ConfigDefault)
  193. input := []byte(`"hello, world! hello, world!"`)
  194. b.ResetTimer()
  195. for n := 0; n < b.N; n++ {
  196. iter.ResetBytes(input)
  197. iter.ReadString()
  198. }
  199. }
  200. func Benchmark_jsoniter_string_as_bytes(b *testing.B) {
  201. iter := ParseString(ConfigDefault, `"hello, world!"`)
  202. b.ResetTimer()
  203. for n := 0; n < b.N; n++ {
  204. iter.ResetBytes(iter.buf)
  205. iter.ReadStringAsSlice()
  206. }
  207. }
  208. func Benchmark_json_unicode(b *testing.B) {
  209. for n := 0; n < b.N; n++ {
  210. result := ""
  211. json.Unmarshal([]byte(`"\ud83d\udc4a"`), &result)
  212. }
  213. }
  214. func Benchmark_json_ascii(b *testing.B) {
  215. for n := 0; n < b.N; n++ {
  216. result := ""
  217. json.Unmarshal([]byte(`"hello"`), &result)
  218. }
  219. }