jsoniter_string_test.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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\\\/lo"`: `hel\/lo`,
  88. `"hel\\blo"`: `hel\blo`,
  89. `"hel\\\blo"`: "hel\\\blo",
  90. `"hel\\nlo"`: `hel\nlo`,
  91. `"hel\\\nlo"`: "hel\\\nlo",
  92. `"hel\\tlo"`: `hel\tlo`,
  93. `"hel\\flo"`: `hel\flo`,
  94. `"hel\\\flo"`: "hel\\\flo",
  95. `"hel\\\rlo"`: "hel\\\rlo",
  96. `"hel\\\tlo"`: "hel\\\tlo",
  97. `"\u4e2d\u6587"`: "中文",
  98. `"\ud83d\udc4a"`: "\xf0\x9f\x91\x8a", // surrogate
  99. }
  100. for input, output := range cases {
  101. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  102. should := require.New(t)
  103. iter := ParseString(ConfigDefault, input)
  104. should.Equal(output, iter.ReadString())
  105. })
  106. t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
  107. should := require.New(t)
  108. iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
  109. should.Equal(output, iter.ReadString())
  110. })
  111. }
  112. }
  113. func Test_read_string_as_interface(t *testing.T) {
  114. should := require.New(t)
  115. iter := ParseString(ConfigDefault, `"hello"`)
  116. should.Equal("hello", iter.Read())
  117. }
  118. func Test_write_string(t *testing.T) {
  119. should := require.New(t)
  120. str, err := MarshalToString("hello")
  121. should.Equal(`"hello"`, str)
  122. should.Nil(err)
  123. str, err = MarshalToString(`hel"lo`)
  124. should.Equal(`"hel\"lo"`, str)
  125. should.Nil(err)
  126. }
  127. func Test_write_val_string(t *testing.T) {
  128. should := require.New(t)
  129. buf := &bytes.Buffer{}
  130. stream := NewStream(ConfigDefault, buf, 4096)
  131. stream.WriteVal("hello")
  132. stream.Flush()
  133. should.Nil(stream.Error)
  134. should.Equal(`"hello"`, buf.String())
  135. }
  136. func Test_decode_slash(t *testing.T) {
  137. should := require.New(t)
  138. var obj interface{}
  139. should.NotNil(json.Unmarshal([]byte("\\"), &obj))
  140. should.NotNil(UnmarshalFromString("\\", &obj))
  141. }
  142. func Test_html_escape(t *testing.T) {
  143. should := require.New(t)
  144. output, err := json.Marshal(`>`)
  145. should.Nil(err)
  146. should.Equal(`"\u003e"`, string(output))
  147. output, err = ConfigCompatibleWithStandardLibrary.Marshal(`>`)
  148. should.Nil(err)
  149. should.Equal(`"\u003e"`, string(output))
  150. type MyString string
  151. output, err = ConfigCompatibleWithStandardLibrary.Marshal(MyString(`>`))
  152. should.Nil(err)
  153. should.Equal(`"\u003e"`, string(output))
  154. }
  155. func Test_string_encode_with_std(t *testing.T) {
  156. should := require.New(t)
  157. for i := 0; i < utf8.RuneSelf; i++ {
  158. input := string([]byte{byte(i)})
  159. stdOutputBytes, err := json.Marshal(input)
  160. should.Nil(err)
  161. stdOutput := string(stdOutputBytes)
  162. jsoniterOutputBytes, err := ConfigCompatibleWithStandardLibrary.Marshal(input)
  163. should.Nil(err)
  164. jsoniterOutput := string(jsoniterOutputBytes)
  165. should.Equal(stdOutput, jsoniterOutput)
  166. }
  167. }
  168. func Test_unicode(t *testing.T) {
  169. should := require.New(t)
  170. output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"})
  171. should.Equal(`{"a":"数字山谷"}`, output)
  172. output, _ = Config{EscapeHTML: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"})
  173. should.Equal(`{"a":"数字山谷"}`, output)
  174. }
  175. func Test_unicode_and_escape(t *testing.T) {
  176. should := require.New(t)
  177. output, err := MarshalToString(`"数字山谷"`)
  178. should.Nil(err)
  179. should.Equal(`"\"数字山谷\""`, output)
  180. output, err = ConfigFastest.MarshalToString(`"数字山谷"`)
  181. should.Nil(err)
  182. should.Equal(`"\"数字山谷\""`, output)
  183. }
  184. func Test_unsafe_unicode(t *testing.T) {
  185. ConfigDefault.(*frozenConfig).cleanEncoders()
  186. should := require.New(t)
  187. output, err := ConfigDefault.MarshalToString("he\u2029\u2028he")
  188. should.Nil(err)
  189. should.Equal(`"he\u2029\u2028he"`, output)
  190. output, err = ConfigFastest.MarshalToString("he\u2029\u2028he")
  191. should.Nil(err)
  192. should.Equal("\"he\u2029\u2028he\"", output)
  193. }
  194. func Benchmark_jsoniter_unicode(b *testing.B) {
  195. for n := 0; n < b.N; n++ {
  196. iter := ParseString(ConfigDefault, `"\ud83d\udc4a"`)
  197. iter.ReadString()
  198. }
  199. }
  200. func Benchmark_jsoniter_ascii(b *testing.B) {
  201. iter := NewIterator(ConfigDefault)
  202. input := []byte(`"hello, world! hello, world!"`)
  203. b.ResetTimer()
  204. for n := 0; n < b.N; n++ {
  205. iter.ResetBytes(input)
  206. iter.ReadString()
  207. }
  208. }
  209. func Benchmark_jsoniter_string_as_bytes(b *testing.B) {
  210. iter := ParseString(ConfigDefault, `"hello, world!"`)
  211. b.ResetTimer()
  212. for n := 0; n < b.N; n++ {
  213. iter.ResetBytes(iter.buf)
  214. iter.ReadStringAsSlice()
  215. }
  216. }
  217. func Benchmark_json_unicode(b *testing.B) {
  218. for n := 0; n < b.N; n++ {
  219. result := ""
  220. json.Unmarshal([]byte(`"\ud83d\udc4a"`), &result)
  221. }
  222. }
  223. func Benchmark_json_ascii(b *testing.B) {
  224. for n := 0; n < b.N; n++ {
  225. result := ""
  226. json.Unmarshal([]byte(`"hello"`), &result)
  227. }
  228. }