| package jsoniter |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "fmt" |
| "github.com/json-iterator/go/require" |
| "io" |
| "io/ioutil" |
| "strconv" |
| "testing" |
| ) |
| |
| func Test_read_uint64_invalid(t *testing.T) { |
| should := require.New(t) |
| iter := ParseString(",") |
| iter.ReadUint64() |
| should.NotNil(iter.Error) |
| } |
| |
| func Test_read_int8(t *testing.T) { |
| inputs := []string{`127`, `-128`} |
| for _, input := range inputs { |
| t.Run(fmt.Sprintf("%v", input), func(t *testing.T) { |
| should := require.New(t) |
| iter := ParseString(input) |
| expected, err := strconv.ParseInt(input, 10, 8) |
| should.Nil(err) |
| should.Equal(int8(expected), iter.ReadInt8()) |
| }) |
| } |
| } |
| |
| func Test_read_int16(t *testing.T) { |
| inputs := []string{`32767`, `-32768`} |
| for _, input := range inputs { |
| t.Run(fmt.Sprintf("%v", input), func(t *testing.T) { |
| should := require.New(t) |
| iter := ParseString(input) |
| expected, err := strconv.ParseInt(input, 10, 16) |
| should.Nil(err) |
| should.Equal(int16(expected), iter.ReadInt16()) |
| }) |
| } |
| } |
| |
| func Test_read_int32(t *testing.T) { |
| inputs := []string{`1`, `12`, `123`, `1234`, `12345`, `123456`, `2147483647`, `-2147483648`} |
| for _, input := range inputs { |
| t.Run(fmt.Sprintf("%v", input), func(t *testing.T) { |
| should := require.New(t) |
| iter := ParseString(input) |
| expected, err := strconv.ParseInt(input, 10, 32) |
| should.Nil(err) |
| should.Equal(int32(expected), iter.ReadInt32()) |
| }) |
| t.Run(fmt.Sprintf("%v", input), func(t *testing.T) { |
| should := require.New(t) |
| iter := Parse(bytes.NewBufferString(input), 2) |
| expected, err := strconv.ParseInt(input, 10, 32) |
| should.Nil(err) |
| should.Equal(int32(expected), iter.ReadInt32()) |
| }) |
| } |
| } |
| |
| func Test_read_int32_array(t *testing.T) { |
| should := require.New(t) |
| input := `[123,456,789]` |
| val := make([]int32, 0) |
| UnmarshalFromString(input, &val) |
| should.Equal(3, len(val)) |
| } |
| |
| func Test_read_int64_array(t *testing.T) { |
| should := require.New(t) |
| input := `[123,456,789]` |
| val := make([]int64, 0) |
| UnmarshalFromString(input, &val) |
| should.Equal(3, len(val)) |
| } |
| |
| func Test_read_int32_overflow(t *testing.T) { |
| should := require.New(t) |
| input := "123456789123456789," |
| iter := ParseString(input) |
| iter.ReadInt32() |
| should.NotNil(iter.Error) |
| } |
| |
| func Test_read_int64(t *testing.T) { |
| inputs := []string{`1`, `12`, `123`, `1234`, `12345`, `123456`, `9223372036854775807`, `-9223372036854775808`} |
| for _, input := range inputs { |
| t.Run(fmt.Sprintf("%v", input), func(t *testing.T) { |
| should := require.New(t) |
| iter := ParseString(input) |
| expected, err := strconv.ParseInt(input, 10, 64) |
| should.Nil(err) |
| should.Equal(expected, iter.ReadInt64()) |
| }) |
| t.Run(fmt.Sprintf("%v", input), func(t *testing.T) { |
| should := require.New(t) |
| iter := Parse(bytes.NewBufferString(input), 2) |
| expected, err := strconv.ParseInt(input, 10, 64) |
| should.Nil(err) |
| should.Equal(expected, iter.ReadInt64()) |
| }) |
| } |
| } |
| |
| func Test_read_int64_overflow(t *testing.T) { |
| should := require.New(t) |
| input := "123456789123456789123456789123456789," |
| iter := ParseString(input) |
| iter.ReadInt64() |
| should.NotNil(iter.Error) |
| } |
| |
| func Test_read_int64_as_any(t *testing.T) { |
| should := require.New(t) |
| any, err := UnmarshalAnyFromString("1234") |
| should.Nil(err) |
| should.Equal(1234, any.ToInt()) |
| should.Equal(io.EOF, any.LastError()) |
| should.Equal("1234", any.ToString()) |
| should.True(any.ToBool()) |
| } |
| |
| func Test_int_lazy_any_get(t *testing.T) { |
| should := require.New(t) |
| any, err := UnmarshalAnyFromString("1234") |
| should.Nil(err) |
| should.Equal(Invalid, any.Get(1, "2").ValueType()) |
| } |
| |
| func Test_wrap_int(t *testing.T) { |
| should := require.New(t) |
| str, err := MarshalToString(WrapInt64(100)) |
| should.Nil(err) |
| should.Equal("100", str) |
| } |
| |
| func Test_write_uint8(t *testing.T) { |
| vals := []uint8{0, 1, 11, 111, 255} |
| for _, val := range vals { |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteUint8(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatUint(uint64(val), 10), buf.String()) |
| }) |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteVal(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatUint(uint64(val), 10), buf.String()) |
| }) |
| } |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 3) |
| stream.WriteRaw("a") |
| stream.WriteUint8(100) // should clear buffer |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("a100", buf.String()) |
| } |
| |
| func Test_write_int8(t *testing.T) { |
| vals := []int8{0, 1, -1, 99, 0x7f, -0x80} |
| for _, val := range vals { |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteInt8(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatInt(int64(val), 10), buf.String()) |
| }) |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteVal(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatInt(int64(val), 10), buf.String()) |
| }) |
| } |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4) |
| stream.WriteRaw("a") |
| stream.WriteInt8(-100) // should clear buffer |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("a-100", buf.String()) |
| } |
| |
| func Test_write_uint16(t *testing.T) { |
| vals := []uint16{0, 1, 11, 111, 255, 0xfff, 0xffff} |
| for _, val := range vals { |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteUint16(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatUint(uint64(val), 10), buf.String()) |
| }) |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteVal(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatUint(uint64(val), 10), buf.String()) |
| }) |
| } |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 5) |
| stream.WriteRaw("a") |
| stream.WriteUint16(10000) // should clear buffer |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("a10000", buf.String()) |
| } |
| |
| func Test_write_int16(t *testing.T) { |
| vals := []int16{0, 1, 11, 111, 255, 0xfff, 0x7fff, -0x8000} |
| for _, val := range vals { |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteInt16(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatInt(int64(val), 10), buf.String()) |
| }) |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteVal(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatInt(int64(val), 10), buf.String()) |
| }) |
| } |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 6) |
| stream.WriteRaw("a") |
| stream.WriteInt16(-10000) // should clear buffer |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("a-10000", buf.String()) |
| } |
| |
| func Test_write_uint32(t *testing.T) { |
| vals := []uint32{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0xffffffff} |
| for _, val := range vals { |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteUint32(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatUint(uint64(val), 10), buf.String()) |
| }) |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteVal(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatUint(uint64(val), 10), buf.String()) |
| }) |
| } |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 10) |
| stream.WriteRaw("a") |
| stream.WriteUint32(0xffffffff) // should clear buffer |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("a4294967295", buf.String()) |
| } |
| |
| func Test_write_int32(t *testing.T) { |
| vals := []int32{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0x7fffffff, -0x80000000} |
| for _, val := range vals { |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteInt32(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatInt(int64(val), 10), buf.String()) |
| }) |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteVal(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatInt(int64(val), 10), buf.String()) |
| }) |
| } |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 11) |
| stream.WriteRaw("a") |
| stream.WriteInt32(-0x7fffffff) // should clear buffer |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("a-2147483647", buf.String()) |
| } |
| |
| func Test_write_uint64(t *testing.T) { |
| vals := []uint64{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0xffffffff, |
| 0xfffffffff, 0xffffffffff, 0xfffffffffff, 0xffffffffffff, 0xfffffffffffff, 0xffffffffffffff, |
| 0xfffffffffffffff, 0xffffffffffffffff} |
| for _, val := range vals { |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteUint64(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatUint(uint64(val), 10), buf.String()) |
| }) |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteVal(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatUint(uint64(val), 10), buf.String()) |
| }) |
| } |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 10) |
| stream.WriteRaw("a") |
| stream.WriteUint64(0xffffffff) // should clear buffer |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("a4294967295", buf.String()) |
| } |
| |
| func Test_write_int64(t *testing.T) { |
| vals := []int64{0, 1, 11, 111, 255, 999999, 0xfff, 0xffff, 0xfffff, 0xffffff, 0xfffffff, 0xffffffff, |
| 0xfffffffff, 0xffffffffff, 0xfffffffffff, 0xffffffffffff, 0xfffffffffffff, 0xffffffffffffff, |
| 0xfffffffffffffff, 0x7fffffffffffffff, -0x8000000000000000} |
| for _, val := range vals { |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteInt64(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatInt(val, 10), buf.String()) |
| }) |
| t.Run(fmt.Sprintf("%v", val), func(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteVal(val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal(strconv.FormatInt(val, 10), buf.String()) |
| }) |
| } |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 10) |
| stream.WriteRaw("a") |
| stream.WriteInt64(0xffffffff) // should clear buffer |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("a4294967295", buf.String()) |
| } |
| |
| func Test_write_val_int(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| stream.WriteVal(1001) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("1001", buf.String()) |
| } |
| |
| func Test_write_val_int_ptr(t *testing.T) { |
| should := require.New(t) |
| buf := &bytes.Buffer{} |
| stream := NewStream(buf, 4096) |
| val := 1001 |
| stream.WriteVal(&val) |
| stream.Flush() |
| should.Nil(stream.Error) |
| should.Equal("1001", buf.String()) |
| } |
| |
| func Test_json_number(t *testing.T) { |
| should := require.New(t) |
| var arr []json.Number |
| err := Unmarshal([]byte(`[1]`), &arr) |
| should.Nil(err) |
| should.Equal(json.Number("1"), arr[0]) |
| str, err := MarshalToString(arr) |
| should.Nil(err) |
| should.Equal(`[1]`, str) |
| } |
| |
| func Benchmark_jsoniter_encode_int(b *testing.B) { |
| stream := NewStream(ioutil.Discard, 64) |
| for n := 0; n < b.N; n++ { |
| stream.n = 0 |
| stream.WriteUint64(0xffffffff) |
| } |
| } |
| |
| func Benchmark_itoa(b *testing.B) { |
| for n := 0; n < b.N; n++ { |
| strconv.FormatInt(0xffffffff, 10) |
| } |
| } |
| |
| func Benchmark_jsoniter_int(b *testing.B) { |
| iter := NewIterator() |
| input := []byte(`100`) |
| for n := 0; n < b.N; n++ { |
| iter.ResetBytes(input) |
| iter.ReadInt64() |
| } |
| } |
| |
| func Benchmark_json_int(b *testing.B) { |
| for n := 0; n < b.N; n++ { |
| result := int64(0) |
| json.Unmarshal([]byte(`-100`), &result) |
| } |
| } |