1
0
mirror of https://github.com/json-iterator/go.git synced 2024-11-27 08:30:57 +02:00
json-iterator/jsoniter_string_test.go

262 lines
7.6 KiB
Go
Raw Normal View History

2017-07-02 09:20:18 +02:00
// +build go1.8
2016-11-30 18:56:25 +02:00
package jsoniter
import (
"bytes"
"encoding/json"
"fmt"
2017-06-06 17:27:00 +02:00
"testing"
2017-06-15 17:54:43 +02:00
"unicode/utf8"
2017-07-10 08:41:59 +02:00
"github.com/stretchr/testify/require"
2016-11-30 18:56:25 +02:00
)
2017-07-10 08:41:59 +02:00
func Test_read_string(t *testing.T) {
badInputs := []string{
``,
`"`,
`"\"`,
`"\\\"`,
"\"\n\"",
`"\U0001f64f"`,
`"\uD83D\u00"`,
2017-07-10 09:13:31 +02:00
}
for i := 0; i < 32; i++ {
2017-07-10 09:13:31 +02:00
// control characters are invalid
badInputs = append(badInputs, string([]byte{'"', byte(i), '"'}))
2017-07-10 08:41:59 +02:00
}
for _, input := range badInputs {
testReadString(t, input, "", true, "json.Unmarshal", json.Unmarshal)
testReadString(t, input, "", true, "jsoniter.Unmarshal", Unmarshal)
testReadString(t, input, "", true, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", ConfigCompatibleWithStandardLibrary.Unmarshal)
}
goodInputs := []struct {
input string
expectValue string
}{
{`""`, ""},
{`"a"`, "a"},
{`null`, ""},
{`"Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"`, "Iñtërnâtiônàlizætiøn,💝🐹🌇⛔"},
{`"\uD83D"`, string([]byte{239, 191, 189})},
{`"\uD83D\\"`, string([]byte{239, 191, 189, '\\'})},
{`"\uD83D\ub000"`, string([]byte{239, 191, 189, 235, 128, 128})},
{`"\uD83D\ude04"`, "😄"},
{`"\uDEADBEEF"`, string([]byte{239, 191, 189, 66, 69, 69, 70})},
2017-07-10 08:41:59 +02:00
}
for _, tc := range goodInputs {
testReadString(t, tc.input, tc.expectValue, false, "json.Unmarshal", json.Unmarshal)
testReadString(t, tc.input, tc.expectValue, false, "jsoniter.Unmarshal", Unmarshal)
testReadString(t, tc.input, tc.expectValue, false, "jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal", ConfigCompatibleWithStandardLibrary.Unmarshal)
}
}
func testReadString(t *testing.T, input string, expectValue string, expectError bool, marshalerName string, marshaler func([]byte, interface{}) error) {
var value string
err := marshaler([]byte(input), &value)
if expectError != (err != nil) {
t.Errorf("%q: %s: expected error %v, got %v", input, marshalerName, expectError, err)
return
}
if value != expectValue {
t.Errorf("%q: %s: expected %q, got %q", input, marshalerName, expectValue, value)
return
}
}
func Test_read_normal_string(t *testing.T) {
cases := map[string]string{
`"0123456789012345678901234567890123456789"`: `0123456789012345678901234567890123456789`,
2017-06-06 17:27:00 +02:00
`""`: ``,
`"hello"`: `hello`,
}
for input, output := range cases {
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
2017-06-17 04:21:37 +02:00
iter := ParseString(ConfigDefault, input)
should.Equal(output, iter.ReadString())
})
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
2017-06-17 04:21:37 +02:00
iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
should.Equal(output, iter.ReadString())
})
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
2017-06-17 04:21:37 +02:00
iter := ParseString(ConfigDefault, input)
should.Equal(output, string(iter.ReadStringAsSlice()))
})
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
2017-06-17 04:21:37 +02:00
iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
should.Equal(output, string(iter.ReadStringAsSlice()))
})
2016-11-30 18:56:25 +02:00
}
}
func Test_read_exotic_string(t *testing.T) {
cases := map[string]string{
2017-06-06 17:27:00 +02:00
`"hel\"lo"`: `hel"lo`,
2017-07-13 09:32:26 +02:00
`"hel\\\/lo"`: `hel\/lo`,
`"hel\\blo"`: `hel\blo`,
`"hel\\\blo"`: "hel\\\blo",
`"hel\\nlo"`: `hel\nlo`,
`"hel\\\nlo"`: "hel\\\nlo",
`"hel\\tlo"`: `hel\tlo`,
`"hel\\flo"`: `hel\flo`,
`"hel\\\flo"`: "hel\\\flo",
`"hel\\\rlo"`: "hel\\\rlo",
`"hel\\\tlo"`: "hel\\\tlo",
`"\u4e2d\u6587"`: "中文",
`"\ud83d\udc4a"`: "\xf0\x9f\x91\x8a", // surrogate
}
for input, output := range cases {
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
2017-06-17 04:21:37 +02:00
iter := ParseString(ConfigDefault, input)
var v string
should.Nil(json.Unmarshal([]byte(input), &v))
should.Equal(v, iter.ReadString())
})
t.Run(fmt.Sprintf("%v:%v", input, output), func(t *testing.T) {
should := require.New(t)
2017-06-17 04:21:37 +02:00
iter := Parse(ConfigDefault, bytes.NewBufferString(input), 2)
should.Equal(output, iter.ReadString())
})
2016-12-06 08:23:59 +02:00
}
}
2017-01-23 02:33:43 +02:00
func Test_read_string_as_interface(t *testing.T) {
2017-01-21 10:09:38 +02:00
should := require.New(t)
2017-06-17 04:21:37 +02:00
iter := ParseString(ConfigDefault, `"hello"`)
2017-01-21 10:09:38 +02:00
should.Equal("hello", iter.Read())
}
2017-01-07 06:28:16 +02:00
func Test_write_string(t *testing.T) {
should := require.New(t)
2017-01-21 18:04:08 +02:00
str, err := MarshalToString("hello")
should.Equal(`"hello"`, str)
should.Nil(err)
str, err = MarshalToString(`hel"lo`)
should.Equal(`"hel\"lo"`, str)
should.Nil(err)
2017-01-09 11:47:21 +02:00
}
func Test_write_val_string(t *testing.T) {
should := require.New(t)
buf := &bytes.Buffer{}
2017-06-17 04:21:37 +02:00
stream := NewStream(ConfigDefault, buf, 4096)
2017-01-09 11:47:21 +02:00
stream.WriteVal("hello")
stream.Flush()
should.Nil(stream.Error)
should.Equal(`"hello"`, buf.String())
2017-01-07 06:28:16 +02:00
}
2017-06-08 03:46:19 +02:00
func Test_decode_slash(t *testing.T) {
should := require.New(t)
var obj interface{}
should.NotNil(json.Unmarshal([]byte("\\"), &obj))
should.NotNil(UnmarshalFromString("\\", &obj))
2017-06-08 03:46:19 +02:00
}
2017-06-15 17:54:43 +02:00
func Test_html_escape(t *testing.T) {
should := require.New(t)
output, err := json.Marshal(`>`)
should.Nil(err)
should.Equal(`"\u003e"`, string(output))
output, err = ConfigCompatibleWithStandardLibrary.Marshal(`>`)
should.Nil(err)
should.Equal(`"\u003e"`, string(output))
2017-06-26 03:57:45 +02:00
type MyString string
output, err = ConfigCompatibleWithStandardLibrary.Marshal(MyString(`>`))
should.Nil(err)
should.Equal(`"\u003e"`, string(output))
2017-06-15 17:54:43 +02:00
}
func Test_string_encode_with_std(t *testing.T) {
should := require.New(t)
for i := 0; i < utf8.RuneSelf; i++ {
input := string([]byte{byte(i)})
stdOutputBytes, err := json.Marshal(input)
should.Nil(err)
stdOutput := string(stdOutputBytes)
jsoniterOutputBytes, err := ConfigCompatibleWithStandardLibrary.Marshal(input)
should.Nil(err)
jsoniterOutput := string(jsoniterOutputBytes)
should.Equal(stdOutput, jsoniterOutput)
}
}
2017-06-21 12:25:37 +02:00
func Test_unicode(t *testing.T) {
should := require.New(t)
2017-06-23 02:21:02 +02:00
output, _ := MarshalToString(map[string]interface{}{"a": "数字山谷"})
2017-06-21 12:25:37 +02:00
should.Equal(`{"a":"数字山谷"}`, output)
2017-07-09 10:09:23 +02:00
output, _ = Config{EscapeHTML: false}.Froze().MarshalToString(map[string]interface{}{"a": "数字山谷"})
2017-06-21 12:25:37 +02:00
should.Equal(`{"a":"数字山谷"}`, output)
}
2017-06-22 10:00:47 +02:00
func Test_unicode_and_escape(t *testing.T) {
should := require.New(t)
2017-06-23 02:21:02 +02:00
output, err := MarshalToString(`"数字山谷"`)
2017-06-22 10:00:47 +02:00
should.Nil(err)
should.Equal(`"\"数字山谷\""`, output)
2017-06-23 02:21:02 +02:00
output, err = ConfigFastest.MarshalToString(`"数字山谷"`)
2017-06-22 10:00:47 +02:00
should.Nil(err)
should.Equal(`"\"数字山谷\""`, output)
}
func Test_unsafe_unicode(t *testing.T) {
2017-07-09 10:09:23 +02:00
ConfigDefault.(*frozenConfig).cleanEncoders()
2017-06-22 10:00:47 +02:00
should := require.New(t)
2017-06-23 02:21:02 +02:00
output, err := ConfigDefault.MarshalToString("he\u2029\u2028he")
2017-06-22 10:00:47 +02:00
should.Nil(err)
should.Equal(`"he\u2029\u2028he"`, output)
2017-06-23 02:21:02 +02:00
output, err = ConfigFastest.MarshalToString("he\u2029\u2028he")
2017-06-22 10:00:47 +02:00
should.Nil(err)
should.Equal("\"he\u2029\u2028he\"", output)
}
2016-11-30 18:56:25 +02:00
func Benchmark_jsoniter_unicode(b *testing.B) {
for n := 0; n < b.N; n++ {
2017-06-17 04:21:37 +02:00
iter := ParseString(ConfigDefault, `"\ud83d\udc4a"`)
2016-12-01 04:35:38 +02:00
iter.ReadString()
2016-11-30 18:56:25 +02:00
}
}
func Benchmark_jsoniter_ascii(b *testing.B) {
2017-06-17 04:21:37 +02:00
iter := NewIterator(ConfigDefault)
2017-01-16 17:43:20 +02:00
input := []byte(`"hello, world! hello, world!"`)
2016-12-06 08:23:59 +02:00
b.ResetTimer()
2016-11-30 18:56:25 +02:00
for n := 0; n < b.N; n++ {
2017-01-16 17:43:20 +02:00
iter.ResetBytes(input)
2016-12-01 04:35:38 +02:00
iter.ReadString()
2016-11-30 18:56:25 +02:00
}
}
2016-12-06 08:23:59 +02:00
func Benchmark_jsoniter_string_as_bytes(b *testing.B) {
2017-06-17 04:21:37 +02:00
iter := ParseString(ConfigDefault, `"hello, world!"`)
2016-12-06 08:23:59 +02:00
b.ResetTimer()
for n := 0; n < b.N; n++ {
2016-12-10 08:34:36 +02:00
iter.ResetBytes(iter.buf)
iter.ReadStringAsSlice()
2016-12-06 08:23:59 +02:00
}
}
2016-11-30 18:56:25 +02:00
func Benchmark_json_unicode(b *testing.B) {
for n := 0; n < b.N; n++ {
result := ""
json.Unmarshal([]byte(`"\ud83d\udc4a"`), &result)
}
}
func Benchmark_json_ascii(b *testing.B) {
for n := 0; n < b.N; n++ {
result := ""
json.Unmarshal([]byte(`"hello"`), &result)
}
}