gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

commit 10bb7e7376901d07a8650d2a26f55aa3e1094548
parent a9541d970e672141c20ed15f636c355d4da87a27
Author: francoispqt <francois@parquet.ninja>
Date:   Sun, 13 May 2018 17:12:48 +0800

add tests, bool and null values checking and exponent syntax parsing

Diffstat:
Mbenchmarks/encoder/encoder_bench_large_test.go | 2+-
Mdecode_array.go | 6+++++-
Mdecode_bool.go | 2+-
Mdecode_bool_test.go | 96++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Mdecode_embedded_json.go | 3---
Mdecode_embedded_json_test.go | 25++++++++++++++++++++++++-
Mdecode_number.go | 28+++++++++++++++++-----------
Mdecode_number_test.go | 1427+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mdecode_object_test.go | 53++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mdecode_string_test.go | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdecode_test.go | 16----------------
11 files changed, 1102 insertions(+), 657 deletions(-)

diff --git a/benchmarks/encoder/encoder_bench_large_test.go b/benchmarks/encoder/encoder_bench_large_test.go @@ -28,7 +28,7 @@ func BenchmarkJsonIterEncodeLargeStruct(b *testing.B) { } } } -b + func BenchmarkEasyJsonEncodeObjLarge(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { diff --git a/decode_array.go b/decode_array.go @@ -43,7 +43,11 @@ func (dec *Decoder) decodeArray(arr UnmarshalerArray) (int, error) { return dec.cursor, nil case 'n': // is null - dec.cursor = dec.cursor + 4 + dec.cursor++ + err := dec.assertNull() + if err != nil { + return 0, err + } return dec.cursor, nil case '{', '"', 'f', 't', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': // can't unmarshall to struct diff --git a/decode_bool.go b/decode_bool.go @@ -42,7 +42,7 @@ func (dec *Decoder) decodeBool(v *bool) error { dec.cursor++ return nil default: - dec.err = InvalidTypeError( + dec.err = InvalidUnmarshalError( fmt.Sprintf( "Cannot unmarshall to bool, wrong char '%s' found at pos %d", string(dec.data[dec.cursor]), diff --git a/decode_bool_test.go b/decode_bool_test.go @@ -75,7 +75,7 @@ func TestDecoderBool(t *testing.T) { }, }, { - name: "true-error4", + name: "true-error5", json: "t", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -84,6 +84,16 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "true-error6", + json: "a", + expectations: func(t *testing.T, v bool, err error) { + assert.NotNil(t, err, "err should be nil") + assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + assert.False(t, v, "result should be false") + }, + }, + { + name: "false-error", json: "fulse", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -92,6 +102,7 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "false-error2", json: "fause", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -100,6 +111,7 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "false-error3", json: "falze", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -108,6 +120,7 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "false-error4", json: "falso", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -116,6 +129,7 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "false-error5", json: "falsea", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -124,6 +138,7 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "false-error6", json: "f", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -132,6 +147,16 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "false-error7", + json: "a", + expectations: func(t *testing.T, v bool, err error) { + assert.NotNil(t, err, "err should be nil") + assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + assert.False(t, v, "result should be false") + }, + }, + { + name: "null-error", json: "nall", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -140,6 +165,7 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "null-error2", json: "nual", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -148,6 +174,7 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "null-error3", json: "nula", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -156,6 +183,7 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "null-error4", json: "nulle", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -164,6 +192,7 @@ func TestDecoderBool(t *testing.T) { }, }, { + name: "null-error5", json: "n", expectations: func(t *testing.T, v bool, err error) { assert.NotNil(t, err, "err should be nil") @@ -171,6 +200,32 @@ func TestDecoderBool(t *testing.T) { assert.False(t, v, "result should be false") }, }, + { + name: "null-error6", + json: "a", + expectations: func(t *testing.T, v bool, err error) { + assert.NotNil(t, err, "err should be nil") + assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + assert.False(t, v, "result should be false") + }, + }, + { + name: "null-skip", + json: "{}", + expectations: func(t *testing.T, v bool, err error) { + assert.NotNil(t, err, "err should not be nil") + assert.IsType(t, InvalidUnmarshalError(""), err, "err should be of type InvalidUnmarshalError") + assert.False(t, v, "result should be false") + }, + }, + { + name: "null-skip", + json: "", + expectations: func(t *testing.T, v bool, err error) { + assert.Nil(t, err, "err should not be nil") + assert.False(t, v, "result should be false") + }, + }, } for _, testCase := range testCases { @@ -183,45 +238,6 @@ func TestDecoderBool(t *testing.T) { } } -func TestDecoderBoolTrue(t *testing.T) { - json := []byte(`true`) - var v bool - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, true, v, "v must be equal to true") -} - -func TestDecoderBoolFalse(t *testing.T) { - json := []byte(`false`) - var v bool - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, false, v, "v must be equal to false") -} - -func TestDecoderBoolInvalidType(t *testing.T) { - json := []byte(`"string"`) - var v bool - err := Unmarshal(json, &v) - assert.NotNil(t, err, "Err must not be nil") - assert.Equal(t, false, v, "v must be equal to false as it is zero val") -} - -func TestDecoderBoolNonBooleanJSONFalse(t *testing.T) { - json := []byte(`null`) - var v bool - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, false, v, "v must be equal to false") -} - -func TestDecoderBoolInvalidJSON(t *testing.T) { - json := []byte(`hello`) - var v bool - err := Unmarshal(json, &v) - assert.NotNil(t, err, "Err must not be nil as JSON is invalid") - assert.IsType(t, InvalidJSONError(""), err, "err message must be 'Invalid JSON'") -} func TestDecoderBoolDecoderAPI(t *testing.T) { var v bool dec := BorrowDecoder(strings.NewReader("true")) diff --git a/decode_embedded_json.go b/decode_embedded_json.go @@ -1,7 +1,5 @@ package gojay -import "log" - // EmbeddedJSON is a raw encoded JSON value. // It can be used to delay JSON decoding or precompute a JSON encoding. type EmbeddedJSON []byte @@ -42,7 +40,6 @@ func (dec *Decoder) decodeEmbeddedJSON(ej *EmbeddedJSON) error { return err } dec.cursor++ - log.Print(string(dec.data[:dec.cursor])) // is an object case '{': beginOfEmbeddedJSON = dec.cursor diff --git a/decode_embedded_json_test.go b/decode_embedded_json_test.go @@ -38,6 +38,7 @@ func TestDecodeEmbeddedJSONUnmarshalAPI(t *testing.T) { name string json []byte expectedEmbedded string + err bool }{ { name: "decode-basic-string", @@ -74,6 +75,24 @@ func TestDecodeEmbeddedJSONUnmarshalAPI(t *testing.T) { json: []byte(`{"id":"someid","method":"getmydata","params":[1,2,3], "more":123}`), expectedEmbedded: `[1,2,3]`, }, + { + name: "decode-null-err", + json: []byte(`{"id":"someid","method":"getmydata","params":nil, "more":123}`), + expectedEmbedded: ``, + err: true, + }, + { + name: "decode-bool-false-err", + json: []byte(`{"id":"someid","method":"getmydata","params":faulse, "more":123}`), + expectedEmbedded: ``, + err: true, + }, + { + name: "decode-bool-true-err", + json: []byte(`{"id":"someid","method":"getmydata","params":trou, "more":123}`), + expectedEmbedded: ``, + err: true, + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { @@ -81,7 +100,11 @@ func TestDecodeEmbeddedJSONUnmarshalAPI(t *testing.T) { err := Unmarshal(testCase.json, req) t.Log(req) t.Log(string(req.params)) - assert.Nil(t, err, "err should be nil") + if testCase.err { + assert.NotNil(t, err, "err should not be nil") + } else { + assert.Nil(t, err, "err should be nil") + } assert.Equal(t, testCase.expectedEmbedded, string(req.params), "r.params should be equal to expectedEmbeddedResult") }) } diff --git a/decode_number.go b/decode_number.go @@ -450,9 +450,12 @@ func (dec *Decoder) getInt64(b byte) (int64, error) { exp := dec.getExponent() val := floatVal * float64(pow10uint64[exp+1]) return int64(val), nil - default: + case ' ', '\t', '\n', ',', ']', '}': dec.cursor = j return dec.atoi64(start, end), nil + default: + dec.cursor = j + return 0, InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor)) } } return dec.atoi64(start, end), nil @@ -484,11 +487,13 @@ func (dec *Decoder) getInt64WithExp(init int64, cursor int) (int64, error) { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': uintv := uint64(digits[dec.data[cursor]]) exp = (exp << 3) + (exp << 1) + uintv - default: + case ' ', '\t', '\n', '}', ',', ']': if sign == -1 { return init * (1 / int64(pow10uint64[exp+1])), nil } return init * int64(pow10uint64[exp+1]), nil + default: + return 0, InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor)) } } if sign == -1 { @@ -512,9 +517,7 @@ func (dec *Decoder) getUint64(b byte) (uint64, error) { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': end = j continue - case ' ', '\n', '\t', '\r': - continue - case '.', ',', '}', ']': + case ' ', '\n', '\t', '\r', '.', ',', '}', ']': dec.cursor = j return dec.atoui64(start, end), nil } @@ -568,9 +571,12 @@ func (dec *Decoder) getInt32(b byte) (int32, error) { exp := dec.getExponent() val := floatVal * float64(pow10uint64[exp+1]) return int32(val), nil - default: + case ' ', '\t', '\n', ',', ']', '}': dec.cursor = j return dec.atoi32(start, end), nil + default: + dec.cursor = j + return 0, InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor)) } } return dec.atoi32(start, end), nil @@ -605,11 +611,13 @@ func (dec *Decoder) getInt32WithExp(init int32, cursor int) (int32, error) { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': uintv := uint32(digits[dec.data[cursor]]) exp = (exp << 3) + (exp << 1) + uintv - default: + case ' ', '\t', '\n', '}', ',', ']': if sign == -1 { return init * (1 / int32(pow10uint64[exp+1])), nil } return init * int32(pow10uint64[exp+1]), nil + default: + return 0, InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor)) } } if sign == -1 { @@ -698,9 +706,7 @@ func (dec *Decoder) getFloat(b byte) (float64, error) { return float64(beforeDecimal) * (1 / float64(pow10uint64[exp*-1+1])), nil } return float64(beforeDecimal) * float64(pow10uint64[exp+1]), nil - case ' ', '\n', '\t', '\r': - continue - case ',', '}', ']': // does not have decimal + case ' ', '\n', '\t', '\r', ',', '}', ']': // does not have decimal dec.cursor = j return float64(dec.atoi64(start, end)), nil } @@ -790,7 +796,7 @@ func (dec *Decoder) atoi32(start, end int) int32 { } val = (val << 3) + (val << 1) if maxInt32-val < intv { - dec.err = InvalidTypeError("Overflows int322") + dec.err = InvalidTypeError("Overflows int32") return 0 } val += intv diff --git a/decode_number_test.go b/decode_number_test.go @@ -2,21 +2,102 @@ package gojay import ( "fmt" - "log" "math" + "reflect" "strings" "testing" "github.com/stretchr/testify/assert" ) -func TestDecoderInt64Exponent(t *testing.T) { +func TestDecoderInt(t *testing.T) { testCases := []struct { name string json string - expectedResult int64 + expectedResult int + err bool + errType interface{} }{ { + name: "basic-positive", + json: "100", + expectedResult: 100, + }, + { + name: "basic-positive2", + json: "1039405", + expectedResult: 1039405, + }, + { + name: "basic-negative", + json: "-2", + expectedResult: -2, + }, + { + name: "basic-null", + json: "null", + expectedResult: 0, + }, + { + name: "basic-null-err", + json: "nxll", + expectedResult: 0, + err: true, + errType: InvalidJSONError(""), + }, + { + name: "basic-big", + json: "9223372036854775807", + expectedResult: 9223372036854775807, + }, + { + name: "basic-big-overflow", + json: "9223372036854775808", + expectedResult: 0, + err: true, + errType: InvalidTypeError(""), + }, + { + name: "basic-big-overflow2", + json: "92233720368547758089", + expectedResult: 0, + err: true, + errType: InvalidTypeError(""), + }, + { + name: "basic-big-overflow3", + json: "92233720368547758089 ", + expectedResult: 0, + err: true, + errType: InvalidTypeError(""), + }, + { + name: "basic-negative2", + json: "-2349557", + expectedResult: -2349557, + }, + { + name: "basic-float", + json: "2.4595", + expectedResult: 2, + }, + { + name: "basic-float2", + json: "-7.8876", + expectedResult: -7, + }, + { + name: "basic-float2", + json: "-7.8876 ", + expectedResult: -7, + }, + { + name: "basic-float2", + json: "-7.8876a", + expectedResult: 0, + err: true, + }, + { name: "basic-exponent-positive-positive-exp", json: "1e2", expectedResult: 100, @@ -76,31 +157,171 @@ func TestDecoderInt64Exponent(t *testing.T) { json: "-8e+005", expectedResult: -800000, }, + { + name: "error1", + json: "132zz4", + expectedResult: 0, + err: true, + }, + { + name: "negative-error2", + json: " -1213xdde2323 ", + expectedResult: 0, + err: true, + errType: InvalidJSONError(""), + }, + { + name: "error3", + json: "-8e+00$aa5", + expectedResult: 0, + err: true, + errType: InvalidJSONError(""), + }, + { + name: "invalid-type", + json: `"string"`, + expectedResult: 0, + err: true, + errType: InvalidTypeError(""), + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { json := []byte(testCase.json) - var v int64 + var v int err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") + if testCase.err { + assert.NotNil(t, err, "Err must not be nil") + if testCase.errType != nil { + assert.IsType( + t, + testCase.errType, + err, + fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()), + ) + } + } else { + assert.Nil(t, err, "Err must be nil") + } assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult)) }) } -} -func TestDecoderInt32Exponent(t *testing.T) { + t.Run("pool-error", func(t *testing.T) { + result := int(1) + dec := NewDecoder(nil) + dec.Release() + defer func() { + err := recover() + assert.NotNil(t, err, "err shouldnot be nil") + assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") + }() + _ = dec.DecodeInt(&result) + assert.True(t, false, "should not be called as decoder should have panicked") + }) + t.Run("decoder-api", func(t *testing.T) { + var v int + dec := NewDecoder(strings.NewReader(`33`)) + defer dec.Release() + err := dec.DecodeInt(&v) + assert.Nil(t, err, "Err must be nil") + assert.Equal(t, int(33), v, "v must be equal to 33") + }) + t.Run("decoder-api-invalid-json", func(t *testing.T) { + var v int + dec := NewDecoder(strings.NewReader(``)) + defer dec.Release() + err := dec.DecodeInt(&v) + assert.NotNil(t, err, "Err must not be nil") + assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + }) +} +func TestDecoderInt64(t *testing.T) { testCases := []struct { name string json string - expectedResult int32 + expectedResult int64 + err bool + errType interface{} }{ { + name: "basic-positive", + json: "100", + expectedResult: 100, + }, + { + name: "basic-positive2", + json: "1039405", + expectedResult: 1039405, + }, + { + name: "basic-negative", + json: "-2", + expectedResult: -2, + }, + { + name: "basic-null", + json: "null", + expectedResult: 0, + }, + { + name: "basic-null-err", + json: "nxll", + expectedResult: 0, + err: true, + errType: InvalidJSONError(""), + }, + { + name: "basic-big", + json: "9223372036854775807", + expectedResult: 9223372036854775807, + }, + { + name: "basic-big-overflow", + json: "9223372036854775808", + expectedResult: 0, + err: true, + }, + { + name: "basic-big-overflow2", + json: "92233720368547758089", + expectedResult: 0, + err: true, + }, + { + name: "basic-big-overflow3", + json: "92233720368547758089 ", + expectedResult: 0, + err: true, + }, + { + name: "basic-negative2", + json: "-2349557", + expectedResult: -2349557, + }, + { + name: "basic-float", + json: "2.4595", + expectedResult: 2, + }, + { + name: "basic-float2", + json: "-7.8876", + expectedResult: -7, + }, + { + name: "basic-float2", + json: "-7.8876a", + expectedResult: 0, + err: true, + }, + { name: "basic-exponent-positive-positive-exp", json: "1e2", expectedResult: 100, }, { name: "basic-exponent-positive-positive-exp2", - json: "5e+06", + json: "5e+06 ", expectedResult: 5000000, }, { @@ -115,7 +336,7 @@ func TestDecoderInt32Exponent(t *testing.T) { }, { name: "basic-exponent-positive-negative-exp", - json: "1e-2", + json: "1e-2 ", expectedResult: 0, }, { @@ -144,6 +365,344 @@ func TestDecoderInt32Exponent(t *testing.T) { expectedResult: -5000000, }, { + name: "basic-exponent-negative-positive-exp2", + json: "-5.4e+06", + expectedResult: -5400000, + }, + { + name: "basic-exponent-negative-positive-exp3", + json: "-3e03", + expectedResult: -3000, + }, + { + name: "basic-exponent-negative-positive-exp4", + json: "-8e+005", + expectedResult: -800000, + }, + { + name: "error1", + json: "132zz4", + expectedResult: 0, + err: true, + }, + { + name: "invalid-type", + json: `"string"`, + expectedResult: 0, + err: true, + errType: InvalidTypeError(""), + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + json := []byte(testCase.json) + var v int64 + err := Unmarshal(json, &v) + if testCase.err { + assert.NotNil(t, err, "Err must not be nil") + if testCase.errType != nil { + assert.IsType( + t, + testCase.errType, + err, + fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()), + ) + } + } else { + assert.Nil(t, err, "Err must be nil") + } + assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult)) + }) + } + t.Run("pool-error", func(t *testing.T) { + result := int64(1) + dec := NewDecoder(nil) + dec.Release() + defer func() { + err := recover() + assert.NotNil(t, err, "err shouldnot be nil") + assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") + }() + _ = dec.DecodeInt64(&result) + assert.True(t, false, "should not be called as decoder should have panicked") + }) + t.Run("decoder-api", func(t *testing.T) { + var v int64 + dec := NewDecoder(strings.NewReader(`33`)) + defer dec.Release() + err := dec.DecodeInt64(&v) + assert.Nil(t, err, "Err must be nil") + assert.Equal(t, int64(33), v, "v must be equal to 33") + }) + t.Run("decoder-api-invalid-json", func(t *testing.T) { + var v int64 + dec := NewDecoder(strings.NewReader(``)) + defer dec.Release() + err := dec.DecodeInt64(&v) + assert.NotNil(t, err, "Err must not be nil") + assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + }) +} +func TestDecoderUint64(t *testing.T) { + testCases := []struct { + name string + json string + expectedResult uint64 + err bool + errType interface{} + }{ + { + name: "basic-positive", + json: "100", + expectedResult: 100, + }, + { + name: "basic-positive2", + json: "1039405", + expectedResult: 1039405, + }, + { + name: "basic-negative", + json: "-2", + expectedResult: 2, + }, + { + name: "basic-null", + json: "null", + expectedResult: 0, + }, + { + name: "basic-null-err", + json: "nxll", + expectedResult: 0, + err: true, + errType: InvalidJSONError(""), + }, + { + name: "basic-big", + json: "18446744073709551615", + expectedResult: 18446744073709551615, + }, + { + name: "basic-big-overflow", + json: "18446744073709551616", + expectedResult: 0, + err: true, + }, + { + name: "basic-big-overflow2", + json: "184467440737095516161", + expectedResult: 0, + err: true, + }, + { + name: "basic-negative2", + json: "-2349557", + expectedResult: 2349557, + }, + { + name: "basic-float", + json: "2.4595", + expectedResult: 2, + }, + { + name: "basic-float2", + json: "-7.8876", + expectedResult: 7, + }, + { + name: "error1", + json: "132zz4", + expectedResult: 0, + err: true, + }, + { + name: "invalid-type", + json: `"string"`, + expectedResult: 0, + err: true, + errType: InvalidTypeError(""), + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + json := []byte(testCase.json) + var v uint64 + err := Unmarshal(json, &v) + if testCase.err { + assert.NotNil(t, err, "Err must not be nil") + if testCase.errType != nil { + assert.IsType( + t, + testCase.errType, + err, + fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()), + ) + } + } else { + assert.Nil(t, err, "Err must be nil") + } + assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult)) + }) + } + t.Run("pool-error", func(t *testing.T) { + result := uint64(1) + dec := NewDecoder(nil) + dec.Release() + defer func() { + err := recover() + assert.NotNil(t, err, "err shouldnot be nil") + assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") + }() + _ = dec.DecodeUint64(&result) + assert.True(t, false, "should not be called as decoder should have panicked") + }) + t.Run("decoder-api", func(t *testing.T) { + var v uint64 + dec := NewDecoder(strings.NewReader(`33`)) + defer dec.Release() + err := dec.DecodeUint64(&v) + assert.Nil(t, err, "Err must be nil") + assert.Equal(t, uint64(33), v, "v must be equal to 33") + }) + t.Run("decoder-api-json-error", func(t *testing.T) { + var v uint64 + dec := NewDecoder(strings.NewReader(``)) + defer dec.Release() + err := dec.DecodeUint64(&v) + assert.NotNil(t, err, "Err must not be nil") + assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + }) +} +func TestDecoderInt32(t *testing.T) { + testCases := []struct { + name string + json string + expectedResult int32 + err bool + errType interface{} + }{ + { + name: "basic-positive", + json: "100", + expectedResult: 100, + }, + { + name: "basic-positive2", + json: "1039405", + expectedResult: 1039405, + }, + { + name: "basic-negative", + json: "-2", + expectedResult: -2, + }, + { + name: "basic-null", + json: "null", + expectedResult: 0, + }, + { + name: "basic-null-err", + json: "nxll", + expectedResult: 0, + err: true, + errType: InvalidJSONError(""), + }, + { + name: "basic-negative2", + json: "-2349557", + expectedResult: -2349557, + }, + { + name: "basic-big", + json: "2147483647", + expectedResult: 2147483647, + }, + { + name: "basic-big-overflow", + json: " 2147483648", + expectedResult: 0, + err: true, + }, + { + name: "basic-big-overflow2", + json: "21474836483", + expectedResult: 0, + err: true, + }, + { + name: "basic-float", + json: "2.4595", + expectedResult: 2, + }, + { + name: "basic-float2", + json: "-7.8876", + expectedResult: -7, + }, + { + name: "basic-float2", + json: "-7.8876a", + expectedResult: 0, + err: true, + }, + { + name: "basic-exponent-positive-positive-exp", + json: "1.2E2", + expectedResult: 120, + }, + { + name: "basic-exponent-positive-positive-exp1", + json: "3.5e+005", + expectedResult: 350000, + }, + { + name: "basic-exponent-positive-positive-exp2", + json: "5e+06", + expectedResult: 5000000, + }, + { + name: "basic-exponent-positive-positive-exp3", + json: "3e+3", + expectedResult: 3000, + }, + { + name: "basic-exponent-positive-positive-exp4", + json: "8e+005 ", + expectedResult: 800000, + }, + { + name: "basic-exponent-positive-negative-exp", + json: "1e-2 ", + expectedResult: 0, + }, + { + name: "basic-exponent-positive-negative-exp2", + json: "5E-6", + expectedResult: 0, + }, + { + name: "basic-exponent-positive-negative-exp3", + json: "3e-3", + expectedResult: 0, + }, + { + name: "basic-exponent-positive-negative-exp4", + json: "8e-005", + expectedResult: 0, + }, + { + name: "basic-exponent-negative-positive-exp", + json: "-1e2", + expectedResult: -100, + }, + { + name: "basic-exponent-negative-positive-exp2", + json: "-5e+06", + expectedResult: -5000000, + }, + { name: "basic-exponent-negative-positive-exp3", json: "-3e03", expectedResult: -3000, @@ -153,23 +712,212 @@ func TestDecoderInt32Exponent(t *testing.T) { json: "-8e+005", expectedResult: -800000, }, + { + name: "error3", + json: "-8e+00$aa5", + expectedResult: 0, + err: true, + }, + { + name: "invalid-type", + json: `"string"`, + expectedResult: 0, + err: true, + errType: InvalidTypeError(""), + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { json := []byte(testCase.json) var v int32 err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") + if testCase.err { + assert.NotNil(t, err, "Err must not be nil") + if testCase.errType != nil { + assert.IsType( + t, + testCase.errType, + err, + fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()), + ) + } + } else { + assert.Nil(t, err, "Err must be nil") + } assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult)) }) } + t.Run("pool-error", func(t *testing.T) { + result := int32(1) + dec := NewDecoder(nil) + dec.Release() + defer func() { + err := recover() + assert.NotNil(t, err, "err shouldnot be nil") + assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") + }() + _ = dec.DecodeInt32(&result) + assert.True(t, false, "should not be called as decoder should have panicked") + + }) + t.Run("decoder-api", func(t *testing.T) { + var v int32 + dec := NewDecoder(strings.NewReader(`33`)) + defer dec.Release() + err := dec.DecodeInt32(&v) + assert.Nil(t, err, "Err must be nil") + assert.Equal(t, int32(33), v, "v must be equal to 33") + }) + t.Run("decoder-api-invalid-json", func(t *testing.T) { + var v int32 + dec := NewDecoder(strings.NewReader(``)) + defer dec.Release() + err := dec.DecodeInt32(&v) + assert.NotNil(t, err, "Err must not be nil") + assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + }) } -func TestDecoderFloat64Exponent(t *testing.T) { +func TestDecoderUint32(t *testing.T) { + testCases := []struct { + name string + json string + expectedResult uint32 + err bool + errType interface{} + }{ + { + name: "basic-positive", + json: "100", + expectedResult: 100, + }, + { + name: "basic-positive2", + json: "1039405", + expectedResult: 1039405, + }, + { + name: "basic-negative", + json: "-2", + expectedResult: 2, + }, + { + name: "basic-null", + json: "null", + expectedResult: 0, + }, + { + name: "basic-null-err", + json: "nxll", + expectedResult: 0, + err: true, + errType: InvalidJSONError(""), + }, + { + name: "basic-negative2", + json: "-2349557", + expectedResult: 2349557, + }, + { + name: "basic-big", + json: "4294967295", + expectedResult: 4294967295, + }, + { + name: "basic-big-overflow", + json: " 4294967298", + expectedResult: 0, + err: true, + }, + { + name: "basic-big-overflow2", + json: "42949672983", + expectedResult: 0, + err: true, + }, + { + name: "basic-float", + json: "2.4595", + expectedResult: 2, + }, + { + name: "basic-float2", + json: "-7.8876", + expectedResult: 7, + }, + { + name: "invalid-type", + json: `"string"`, + expectedResult: 0, + err: true, + errType: InvalidTypeError(""), + }, + { + name: "invalid-json", + json: `123invalid`, + expectedResult: 0, + err: true, + errType: InvalidJSONError(""), + }, + } + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + json := []byte(testCase.json) + var v uint32 + err := Unmarshal(json, &v) + if testCase.err { + assert.NotNil(t, err, "Err must not be nil") + if testCase.errType != nil { + assert.IsType( + t, + testCase.errType, + err, + fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()), + ) + } + } else { + assert.Nil(t, err, "Err must be nil") + } + assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult)) + }) + } + t.Run("pool-error", func(t *testing.T) { + result := uint32(1) + dec := NewDecoder(nil) + dec.Release() + defer func() { + err := recover() + assert.NotNil(t, err, "err shouldnot be nil") + assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") + }() + _ = dec.DecodeUint32(&result) + assert.True(t, false, "should not be called as decoder should have panicked") + }) + t.Run("decoder-api", func(t *testing.T) { + var v uint32 + dec := NewDecoder(strings.NewReader(`33`)) + defer dec.Release() + err := dec.DecodeUint32(&v) + assert.Nil(t, err, "Err must be nil") + assert.Equal(t, uint32(33), v, "v must be equal to 33") + }) + t.Run("decoder-api-json-error", func(t *testing.T) { + var v uint32 + dec := NewDecoder(strings.NewReader(``)) + defer dec.Release() + err := dec.DecodeUint32(&v) + assert.NotNil(t, err, "Err must not be nil") + assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + }) +} + +func TestDecoderFloat64(t *testing.T) { testCases := []struct { name string json string expectedResult float64 + err bool + errType interface{} }{ { name: "basic-exponent-positive-positive-exp", @@ -187,6 +935,18 @@ func TestDecoderFloat64Exponent(t *testing.T) { expectedResult: 3000, }, { + name: "basic-null", + json: "null", + expectedResult: 0, + }, + { + name: "basic-null-err", + json: "nxll", + expectedResult: 0, + err: true, + errType: InvalidJSONError(""), + }, + { name: "basic-exponent-positive-positive-exp4", json: "8e+005", expectedResult: 800000, @@ -231,583 +991,86 @@ func TestDecoderFloat64Exponent(t *testing.T) { json: "-8e+005", expectedResult: -800000, }, + { + name: "basic-exponent-negative-positive-exp4", + json: "-8.2e-005", + expectedResult: -0.000082, + }, + { + name: "basic-float", + json: "2.4595", + expectedResult: 2.4595, + }, + { + name: "basic-float2", + json: "-7.8876", + expectedResult: -7.8876, + }, + { + name: "basic-float", + json: "2.4595e1", + expectedResult: 24.595, + }, + { + name: "basic-float2", + json: "-7.8876e002", + expectedResult: -788.76, + }, + { + name: "invalid-type", + json: `"string"`, + expectedResult: 0, + err: true, + errType: InvalidTypeError(""), + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { json := []byte(testCase.json) var v float64 err := Unmarshal(json, &v) - log.Print(v) - assert.Nil(t, err, "Err must be nil") + if testCase.err { + assert.NotNil(t, err, "Err must not be nil") + if testCase.errType != nil { + assert.IsType( + t, + testCase.errType, + err, + fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()), + ) + } + } else { + assert.Nil(t, err, "Err must be nil") + } assert.Equal(t, testCase.expectedResult*1000000, math.Round(v*1000000), fmt.Sprintf("v must be equal to %f", testCase.expectedResult)) }) } -} -func TestDecoderIntBasic(t *testing.T) { - json := []byte(`124`) - var v int - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 124, v, "v must be equal to 124") -} -func TestDecoderIntExponent(t *testing.T) { - json := []byte(`1E+2`) - var v int - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 100, v, "v must be equal to 100") -} -func TestDecoderIntExponent1(t *testing.T) { - json := []byte(`4E+2`) - var v int - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 400, v, "v must be equal to 100") -} -func TestDecoderIntExponentComplex(t *testing.T) { - json := []byte(`-3E-004`) - var v int - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 0, v, "v must be equal to 0") -} -func TestDecoderIntExponentComplex1(t *testing.T) { - json := []byte(`-3.12E+005`) - var v int - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, -312000, v, "v must be equal to -312000") -} -func TestDecoderFloatExponentComplex1(t *testing.T) { - json := []byte(`-3E-004`) - var v float64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int64(-0.0003*10000), int64(v*10000), "v must be equal to -0.0003") -} -func TestDecoderFloatExponentComplex2(t *testing.T) { - json := []byte(`-3E+004`) - var v float64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, float64(-30000), float64(v), "v must be equal to -30000") -} -func TestDecoderFloatExponentComplex3(t *testing.T) { - json := []byte(`-3.12E-004`) - var v float64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int64(-0.000312*1000000), int64(v*1000000), "v must be equal to -30000") -} -func TestDecoderIntExponentComplex2(t *testing.T) { - json := []byte(`3.12E+005`) - var v int - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 312000, v, "v must be equal to 312000") -} -func TestDecoderIntNegative(t *testing.T) { - json := []byte(` -124 `) - var v int - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, -124, v, "v must be equal to -124") -} -func TestDecoderIntNegativeError(t *testing.T) { - json := []byte(` -12x4 `) - var v int - err := Unmarshal(json, &v) - assert.NotNil(t, err, "Err must be nil") - assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError") -} -func TestDecoderIntNull(t *testing.T) { - json := []byte(`null`) - var v int - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int(0), v, "v must be equal to 0") -} -func TestDecoderIntInvalidType(t *testing.T) { - json := []byte(`"string"`) - var v int - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeErrorr") -} -func TestDecoderIntInvalidJSON(t *testing.T) { - json := []byte(`123n`) - var v int - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError") -} -func TestDecoderIntBig(t *testing.T) { - json := []byte(`9223372036854775807`) - var v int - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 9223372036854775807, v, "v must be equal to 9223372036854775807") -} -func TestDecoderIntOverfow(t *testing.T) { - json := []byte(`9223372036854775808`) - var v int - err := Unmarshal(json, &v) - assert.NotNil(t, err, "Err must not be nil as int is overflowing") - assert.Equal(t, 0, v, "v must be equal to 0") -} -func TestDecoderIntOverfow2(t *testing.T) { - json := []byte(`92233720368547758089 `) - var v int - err := Unmarshal(json, &v) - assert.NotNil(t, err, "Err must not be nil as int is overflowing") - assert.Equal(t, 0, v, "v must be equal to 0") -} -func TestDecoderIntOverfow3(t *testing.T) { - json := []byte(`92233720368547758089 `) - var v int - err := Unmarshal(json, &v) - assert.NotNil(t, err, "Err must not be nil as int is overflowing") - assert.Equal(t, 0, v, "v must be equal to 0") -} -func TestDecoderIntPoolError(t *testing.T) { - result := int(1) - dec := NewDecoder(nil) - dec.Release() - defer func() { - err := recover() - assert.NotNil(t, err, "err shouldnot be nil") - assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") - }() - _ = dec.DecodeInt(&result) - assert.True(t, false, "should not be called as decoder should have panicked") -} -func TestDecoderIntDecoderAPI(t *testing.T) { - var v int - dec := NewDecoder(strings.NewReader(`33`)) - defer dec.Release() - err := dec.DecodeInt(&v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int(33), v, "v must be equal to 33") -} - -func TestDecoderIntInvalidJSONError(t *testing.T) { - var v int - dec := NewDecoder(strings.NewReader(``)) - defer dec.Release() - err := dec.DecodeInt(&v) - assert.NotNil(t, err, "Err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") -} - -func TestDecoderInt32Basic(t *testing.T) { - json := []byte(`124`) - var v int32 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int32(124), v, "v must be equal to 124") -} -func TestDecoderInt32Negative(t *testing.T) { - json := []byte(`-124 `) - var v int32 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int32(-124), v, "v must be equal to -124") -} -func TestDecoderInt32NegativeError(t *testing.T) { - json := []byte(`-12x4 `) - var v int32 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "Err must be nil") - assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError") -} -func TestDecoderInt32Null(t *testing.T) { - json := []byte(`null`) - var v int32 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int32(0), v, "v must be equal to 0") -} -func TestDecoderInt32InvalidType(t *testing.T) { - json := []byte(`"string"`) - var v int32 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeErrorr") -} -func TestDecoderInt32InvalidJSON(t *testing.T) { - json := []byte(`123n`) - var v int32 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError") -} -func TestDecoderInt32Big(t *testing.T) { - json := []byte(`2147483647`) - var v int32 - err := Unmarshal(json, &v) - assert.Nil(t, err, "err must not be nil as int32 does not overflow") - assert.Equal(t, int32(2147483647), v, "int32 must be equal to 2147483647") -} -func TestDecoderInt32Overflow(t *testing.T) { - json := []byte(` 2147483648`) - var v int32 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil as int32 overflows") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeError") -} -func TestDecoderInt32Overflow2(t *testing.T) { - json := []byte(`21474836483`) - var v int32 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil as int32 overflows") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeError") -} -func TestDecoderInt32PoolError(t *testing.T) { - result := int32(1) - dec := NewDecoder(nil) - dec.Release() - defer func() { - err := recover() - assert.NotNil(t, err, "err shouldnot be nil") - assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") - }() - _ = dec.DecodeInt32(&result) - assert.True(t, false, "should not be called as decoder should have panicked") -} -func TestDecoderInt32tDecoderAPI(t *testing.T) { - var v int32 - dec := NewDecoder(strings.NewReader(`33`)) - defer dec.Release() - err := dec.DecodeInt32(&v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int32(33), v, "v must be equal to 33") -} - -func TestDecoderInt32InvalidJSONError(t *testing.T) { - var v int32 - dec := NewDecoder(strings.NewReader(``)) - defer dec.Release() - err := dec.DecodeInt32(&v) - assert.NotNil(t, err, "Err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") -} - -func TestDecoderUint32Basic(t *testing.T) { - json := []byte(`124 `) - var v uint32 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, uint32(124), v, "v must be equal to 124") -} -func TestDecoderUint32Null(t *testing.T) { - json := []byte(`null`) - var v uint32 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, uint32(0), v, "v must be equal to 0") -} -func TestDecoderUint32InvalidType(t *testing.T) { - json := []byte(`"string"`) - var v uint32 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeErrorr") -} -func TestDecoderUint32InvalidJSON(t *testing.T) { - json := []byte(`123n`) - var v uint32 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError") -} -func TestDecoderUint32Big(t *testing.T) { - json := []byte(`4294967295 `) - var v uint32 - err := Unmarshal(json, &v) - assert.Nil(t, err, "err must not be nil as uint32 does not overflow") - assert.Equal(t, uint32(4294967295), v, "err must be of type InvalidTypeError") -} -func TestDecoderUint32Overflow(t *testing.T) { - json := []byte(`4294967298`) - var v uint32 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil as uint32 overflows") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeError") -} - -func TestDecoderUint32Overflow2(t *testing.T) { - json := []byte(`42949672983`) - var v uint32 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil as uint32 overflows") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeError") -} -func TestDecoderUint32PoolError(t *testing.T) { - result := uint32(1) - dec := NewDecoder(nil) - dec.Release() - defer func() { - err := recover() - assert.NotNil(t, err, "err shouldnot be nil") - assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") - }() - _ = dec.DecodeUint32(&result) - assert.True(t, false, "should not be called as decoder should have panicked") -} -func TestDecoderUint32tDecoderAPI(t *testing.T) { - var v uint32 - dec := NewDecoder(strings.NewReader(`33`)) - defer dec.Release() - err := dec.DecodeUint32(&v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, uint32(33), v, "v must be equal to 33") -} - -func TestDecoderUint32InvalidJSONError(t *testing.T) { - var v uint32 - dec := NewDecoder(strings.NewReader(``)) - defer dec.Release() - err := dec.DecodeUint32(&v) - assert.NotNil(t, err, "Err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") -} - -func TestDecoderInt64Basic(t *testing.T) { - json := []byte(`124 `) - var v int64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int64(124), v, "v must be equal to 124") -} -func TestDecoderInt64Negative(t *testing.T) { - json := []byte(`-124`) - var v int64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int64(-124), v, "v must be equal to -124") -} - -func TestDecoderInt64Null(t *testing.T) { - json := []byte(`null`) - var v int64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int64(0), v, "v must be equal to 0") -} -func TestDecoderInt64InvalidType(t *testing.T) { - json := []byte(`"string"`) - var v int64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeErrorr") -} -func TestDecoderInt64InvalidJSON(t *testing.T) { - json := []byte(`123n`) - var v int64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError") -} -func TestDecoderInt64Big(t *testing.T) { - json := []byte(`9223372036854775807`) - var v int64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "err must not be nil as int64 does not overflow") - assert.Equal(t, int64(9223372036854775807), v, "err must be of type InvalidTypeError") -} -func TestDecoderInt64Overflow(t *testing.T) { - json := []byte(`9223372036854775808`) - var v int64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil as int64 overflows") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeError") -} -func TestDecoderInt64Overflow2(t *testing.T) { - json := []byte(`92233720368547758082`) - var v int64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil as int64 overflows") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeError") -} -func TestDecoderInt64PoolError(t *testing.T) { - result := int64(1) - dec := NewDecoder(nil) - dec.Release() - defer func() { - err := recover() - assert.NotNil(t, err, "err shouldnot be nil") - assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") - }() - _ = dec.DecodeInt64(&result) - assert.True(t, false, "should not be called as decoder should have panicked") -} -func TestDecoderInt64DecoderAPI(t *testing.T) { - var v int64 - dec := NewDecoder(strings.NewReader(`33`)) - defer dec.Release() - err := dec.DecodeInt64(&v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, int64(33), v, "v must be equal to 33") -} -func TestDecoderInt64InvalidJSONError(t *testing.T) { - var v int64 - dec := NewDecoder(strings.NewReader(``)) - defer dec.Release() - err := dec.DecodeInt64(&v) - assert.NotNil(t, err, "Err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") -} - -func TestDecoderUint64Basic(t *testing.T) { - json := []byte(` 124 `) - var v uint64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, uint64(124), v, "v must be equal to 124") -} -func TestDecoderUint64Null(t *testing.T) { - json := []byte(`null`) - var v uint64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, uint64(0), v, "v must be equal to 0") -} -func TestDecoderUint64InvalidType(t *testing.T) { - json := []byte(`"string"`) - var v uint64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeErrorr") -} -func TestDecoderUint64InvalidJSON(t *testing.T) { - json := []byte(`123n`) - var v uint64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError") -} -func TestDecoderUint64Big(t *testing.T) { - json := []byte(`18446744073709551615`) - var v uint64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "err must not be nil as uint64 does not overflow") - assert.Equal(t, uint64(18446744073709551615), v, "err must be of type InvalidTypeError") -} -func TestDecoderUint64Overflow(t *testing.T) { - json := []byte(`18446744073709551616`) - var v uint64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil as int32 overflows") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeError") -} -func TestDecoderUint64Overflow2(t *testing.T) { - json := []byte(`184467440737095516161`) - var v uint64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil as int32 overflows") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type InvalidTypeError") -} -func TestDecoderUint64PoolError(t *testing.T) { - result := uint64(1) - dec := NewDecoder(nil) - dec.Release() - defer func() { - err := recover() - assert.NotNil(t, err, "err shouldnot be nil") - assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") - }() - _ = dec.DecodeUint64(&result) - assert.True(t, false, "should not be called as decoder should have panicked") -} -func TestDecoderUint64tDecoderAPI(t *testing.T) { - var v uint64 - dec := NewDecoder(strings.NewReader(`33`)) - defer dec.Release() - err := dec.DecodeUint64(&v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, uint64(33), v, "v must be equal to 33") -} - -func TestDecoderUint64InvalidJSONError(t *testing.T) { - var v uint64 - dec := NewDecoder(strings.NewReader(``)) - defer dec.Release() - err := dec.DecodeUint64(&v) - assert.NotNil(t, err, "Err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") -} - -func TestDecoderFloatBasic(t *testing.T) { - json := []byte(`100.11 `) - var v float64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 100.11, v, "v must be equal to 100.11") -} -func TestDecoderFloatBasic2(t *testing.T) { - json := []byte(` 100.11 `) - var v float64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 100.11, v, "v must be equal to 100.11") -} -func TestDecoderFloatBasic3(t *testing.T) { - json := []byte(` 100 `) - var v float64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, float64(100), v, "v must be equal to 100.11") -} - -func TestDecoderFloatBig(t *testing.T) { - json := []byte(`89899843.3493493 `) - var v float64 - err := Unmarshal(json, &v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 89899843.3493493, v, "v must be equal to 8989984340.3493493") -} - -func TestDecoderFloatInvalidType(t *testing.T) { - json := []byte(`"string"`) - var v float64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "err must not be nil") - assert.IsType(t, InvalidTypeError(""), err, "err must be of type *strconv.NumError") -} - -func TestDecoderFloatInvalidJSON(t *testing.T) { - json := []byte(`hello`) - var v float64 - err := Unmarshal(json, &v) - assert.NotNil(t, err, "Err must not be nil as JSON is invalid") - assert.IsType(t, InvalidJSONError(""), err, "err message must be 'Invalid JSON'") -} -func TestDecoderFloatDecoderAPI(t *testing.T) { - var v float64 - dec := NewDecoder(strings.NewReader(`1.25`)) - defer dec.Release() - err := dec.DecodeFloat64(&v) - assert.Nil(t, err, "Err must be nil") - assert.Equal(t, 1.25, v, "v must be equal to 1.25") -} -func TestDecoderFloatPoolError(t *testing.T) { - result := float64(1) - dec := NewDecoder(nil) - dec.Release() - defer func() { - err := recover() - assert.NotNil(t, err, "err shouldnot be nil") - assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") - }() - _ = dec.DecodeFloat64(&result) - assert.True(t, false, "should not be called as decoder should have panicked") -} - -func TestDecoderFloatInvalidJSONError(t *testing.T) { - var v float64 - dec := NewDecoder(strings.NewReader(``)) - defer dec.Release() - err := dec.DecodeFloat64(&v) - assert.NotNil(t, err, "Err must not be nil") - assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + t.Run("pool-error", func(t *testing.T) { + result := float64(1) + dec := NewDecoder(nil) + dec.Release() + defer func() { + err := recover() + assert.NotNil(t, err, "err shouldnot be nil") + assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError") + }() + _ = dec.DecodeFloat64(&result) + assert.True(t, false, "should not be called as decoder should have panicked") + }) + t.Run("decoder-api", func(t *testing.T) { + var v float64 + dec := NewDecoder(strings.NewReader(`1.25`)) + defer dec.Release() + err := dec.DecodeFloat64(&v) + assert.Nil(t, err, "Err must be nil") + assert.Equal(t, 1.25, v, "v must be equal to 1.25") + }) + t.Run("decoder-api-json-error", func(t *testing.T) { + var v float64 + dec := NewDecoder(strings.NewReader(``)) + defer dec.Release() + err := dec.DecodeFloat64(&v) + assert.NotNil(t, err, "Err must not be nil") + assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError") + }) } diff --git a/decode_object_test.go b/decode_object_test.go @@ -168,6 +168,9 @@ var jsonComplex = []byte(`{ }, "testSkipNumber": 123.23, "testBool": true, + "testSkipBoolTrue": true, + "testSkipBoolFalse": false, + "testSkipBoolNull": null, "testSub": { "test": "{\"test\":\"1\",\"test1\":2}", "test2\\n": "[1,2,3]", @@ -220,7 +223,7 @@ func TestDecodeObjComplex(t *testing.T) { result := jsonObjectComplex{} err := UnmarshalObject(jsonComplex, &result) assert.NotNil(t, err, "err should not be as invalid type as been encountered nil") - assert.Equal(t, `Cannot unmarshal to struct, wrong char '"' found at pos 531`, err.Error(), "err should not be as invalid type as been encountered nil") + assert.Equal(t, `Cannot unmarshal to struct, wrong char '"' found at pos 614`, err.Error(), "err should not be as invalid type as been encountered nil") assert.Equal(t, `{"test":"1","test1":2}`, result.Test, "result.Test is not expected value") assert.Equal(t, `\\\\\\n`, result.Test2, "result.Test2 is not expected value") assert.Equal(t, 1, result.Test3, "result.test3 is not expected value") @@ -454,3 +457,51 @@ func TestDecoderObjectPoolError(t *testing.T) { _ = dec.DecodeObject(&result) assert.True(t, false, "should not be called as decoder should have panicked") } + +func TestSkipData(t *testing.T) { + testCases := []struct { + name string + err bool + json string + }{ + { + name: "skip-bool-false-err", + json: `fulse`, + err: true, + }, + { + name: "skip-bool-true-err", + json: `trou`, + err: true, + }, + { + name: "skip-bool-null-err", + json: `nil`, + err: true, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + dec := NewDecoder(strings.NewReader(testCase.json)) + err := dec.skipData() + if testCase.err { + assert.NotNil(t, err, "err should not be nil") + } else { + assert.Nil(t, err, "err should be nil") + } + }) + } + t.Run("error-invalid-json", func(t *testing.T) { + dec := NewDecoder(strings.NewReader("")) + err := dec.skipData() + assert.NotNil(t, err, "err should not be nil as data is empty") + assert.IsType(t, InvalidJSONError(""), err, "err should of type InvalidJSONError") + }) + t.Run("skip-array-error-invalid-json", func(t *testing.T) { + dec := NewDecoder(strings.NewReader("")) + _, err := dec.skipArray() + assert.NotNil(t, err, "err should not be nil as data is empty") + assert.IsType(t, InvalidJSONError(""), err, "err should of type InvalidJSONError") + }) +} diff --git a/decode_string_test.go b/decode_string_test.go @@ -1,6 +1,8 @@ package gojay import ( + "fmt" + "log" "strings" "sync" "testing" @@ -16,6 +18,23 @@ func TestDecoderStringBasic(t *testing.T) { assert.Equal(t, "string", v, "v must be equal to 'string'") } +func TestDecoderStringEmpty(t *testing.T) { + json := []byte(``) + var v string + err := Unmarshal(json, &v) + assert.Nil(t, err, "Err must be nil") + assert.Equal(t, "", v, "v must be equal to 'string'") +} + +func TestDecoderStringNullInvalid(t *testing.T) { + json := []byte(`nall`) + var v string + err := Unmarshal(json, &v) + assert.NotNil(t, err, "Err must be nil") + assert.IsType(t, InvalidJSONError(""), err, "Err must be nil") + assert.Equal(t, "", v, "v must be equal to 'string'") +} + func TestDecoderStringComplex(t *testing.T) { json := []byte(` "string with spaces and \"escape\"d \"quotes\" and escaped line returns \\n and escaped \\\\ escaped char"`) var v string @@ -107,3 +126,85 @@ func TestDecoderSkipStringError(t *testing.T) { assert.NotNil(t, err, "Err must be nil") assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError") } + +func TestParseEscapedString(t *testing.T) { + testCases := []struct { + name string + json string + expectedResult string + err bool + errType interface{} + }{ + { + name: "escape quote err", + json: `"test string \\" escaped"`, + expectedResult: ``, + err: true, + errType: InvalidJSONError(""), + }, + { + name: "escape quote err", + json: `"test string \\\l escaped"`, + expectedResult: ``, + err: true, + errType: InvalidJSONError(""), + }, + } + + for _, testCase := range testCases { + str := "" + dec := NewDecoder(strings.NewReader(testCase.json)) + err := dec.Decode(&str) + if testCase.err { + assert.NotNil(t, err, "err should not be nil") + if testCase.errType != nil { + assert.IsType(t, testCase.errType, err, "err should be of expected type") + } + log.Print(err) + } else { + assert.Nil(t, err, "err should be nil") + } + assert.Equal(t, testCase.expectedResult, str, fmt.Sprintf("str should be equal to '%s'", testCase.expectedResult)) + } +} + +func TestSkipString(t *testing.T) { + testCases := []struct { + name string + json string + expectedResult string + err bool + errType interface{} + }{ + { + name: "escape quote err", + json: `test string \\" escaped"`, + expectedResult: ``, + err: true, + errType: InvalidJSONError(""), + }, + { + name: "escape quote err", + json: `test string \\\l escaped"`, + expectedResult: ``, + err: true, + errType: InvalidJSONError(""), + }, + } + + for _, testCase := range testCases { + str := "" + dec := NewDecoder(strings.NewReader(testCase.json)) + err := dec.skipString() + if testCase.err { + assert.NotNil(t, err, "err should not be nil") + if testCase.errType != nil { + assert.IsType(t, testCase.errType, err, "err should be of expected type") + } + log.Print(err) + } else { + assert.Nil(t, err, "err should be nil") + } + assert.Equal(t, testCase.expectedResult, str, fmt.Sprintf("str should be equal to '%s'", testCase.expectedResult)) + } +} diff --git a/decode_test.go b/decode_test.go @@ -4,7 +4,6 @@ import ( "fmt" "io" "reflect" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -553,18 +552,3 @@ func TestUnmarshalObjects(t *testing.T) { }) } } - -func TestSkipData(t *testing.T) { - t.Run("error-invalid-json", func(t *testing.T) { - dec := NewDecoder(strings.NewReader("")) - err := dec.skipData() - assert.NotNil(t, err, "err should not be nil as data is empty") - assert.IsType(t, InvalidJSONError(""), err, "err should of type InvalidJSONError") - }) - t.Run("skip-array-error-invalid-json", func(t *testing.T) { - dec := NewDecoder(strings.NewReader("")) - _, err := dec.skipArray() - assert.NotNil(t, err, "err should not be nil as data is empty") - assert.IsType(t, InvalidJSONError(""), err, "err should of type InvalidJSONError") - }) -}