jsoniter_string_test.go 7.6 KB

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