diff --git a/bool_test.go b/bool_test.go index b6eebe9..1ed57ec 100644 --- a/bool_test.go +++ b/bool_test.go @@ -6,19 +6,19 @@ import ( "github.com/stretchr/testify/require" ) -func Test_true(t *testing.T) { +func TestTrue(t *testing.T) { should := require.New(t) iter := DecodeStr(`true`) should.True(iter.Bool()) } -func Test_false(t *testing.T) { +func TestFalse(t *testing.T) { should := require.New(t) iter := DecodeStr(`false`) should.False(iter.Bool()) } -func Test_write_true_false(t *testing.T) { +func TestWriteTrueFalse(t *testing.T) { should := require.New(t) w := GetEncoder() w.Bool(true) diff --git a/dec_skip_cases_test.go b/dec_skip_cases_test.go index 38fc829..28d14a4 100644 --- a/dec_skip_cases_test.go +++ b/dec_skip_cases_test.go @@ -30,81 +30,244 @@ var testBools = []string{ "\tfalse", } -var testNumbers = []string{ - "", // invalid - "0", // valid - "-", // invalid - "--", // invalid - "+", // invalid - ".", // invalid - "e", // invalid - "E", // invalid - "-.", // invalid - "-1", // valid - "--1", // invalid - "+1", // invalid - "++1", // invalid - "-a", // invalid - "-0", // valid - "00", // invalid - "01", // invalid - ".00", // invalid - "00.1", // invalid - "-00", // invalid - "-01", // invalid - "-\x00", // invalid, zero byte - "0.1", // valid - "0e1", // valid - "0e+1", // valid - "0e-1", // valid - "0e-11", // valid - "0e-1a", // invalid - "1.e1", // invalid - "0e-1+", // invalid - "0e", // invalid - "e", // invalid - "-e", // invalid - "+e", // invalid - ".e", // invalid - "e.", // invalid - "0.e", // invalid - "0-e", // invalid - "0e-", // invalid - "0e+", // invalid - "0.0e", // invalid - "0.0e1", // valid - "0.0e+", // invalid - "0.0e-", // invalid - "0e0+0", // invalid - "0.e0+0", // invalid - "0.0e+0", // valid - "0.0e+1", // valid - "0.0e0+0", // invalid - "0.", // invalid - "1.", // invalid - "0..1", // invalid, more dot - "1e+1", // valid - "1+1", // invalid - "1E1", // valid, e or E - "1ee1", // invalid - "100a", // invalid - "10.", // invalid - "-0.12", // valid - "0]", // invalid - "0e]", // invalid - "0e+]", // invalid - "1.2.3", // invalid - "0.0.0", // invalid - "9223372036854775807", // valid - "9223372036854775808", // valid - "9223372036854775807.1", // valid - " 9223372036854775807", // valid - " 9223372036854775808", // valid - " 9223372036854775807.1", // valid - "\n9223372036854775807", // valid - "\n9223372036854775808", // valid - "\n9223372036854775807.1", // valid -} +var testNumbers = append([]string{ + "", // invalid + "0", // valid + "-", // invalid + "--", // invalid + "+", // invalid + ".", // invalid + "e", // invalid + "E", // invalid + "-.", // invalid + "-1", // valid + "--1", // invalid + "+1", // invalid + "++1", // invalid + "-a", // invalid + "-0", // valid + "00", // invalid + "01", // invalid + ".00", // invalid + "00.1", // invalid + "-00", // invalid + "-01", // invalid + "-\x00", // invalid, zero byte + "0.1", // valid + "0e0", // valid + "-0e0", // valid + "+0e0", // valid + "0e-0", // valid + "-0e-0", // valid + "+0e-0", // valid + "0e+0", // valid + "-0e+0", // valid + "+0e+0", // valid + "0e+01234567890123456789", // valid + "0.00e-01234567890123456789", // valid + "-0e+01234567890123456789", // valid + "-0.00e-01234567890123456789", // valid + "0e1", // valid + "0e+1", // valid + "0e-1", // valid + "0e-11", // valid + "0e-1a", // invalid + "1.e1", // invalid + "0e-1+", // invalid + "0e", // invalid + "0.e", // invalid + "0-e", // invalid + "0e-", // invalid + "0e+", // invalid + "0.0e", // invalid + "0.0e1", // valid + "0.0e+", // invalid + "0.0e-", // invalid + "0e0+0", // invalid + "0.e0+0", // invalid + "0.0e+0", // valid + "0.0e+1", // valid + "0.0e0+0", // invalid + "e", // invalid + "-e", // invalid + "+e", // invalid + ".e", // invalid + "e.", // invalid + "0.", // invalid + "1.", // invalid + "0..1", // invalid, more dot + "0.1.", // invalid, more dot + "1..", // invalid, more dot + "1e+1", // valid + "1+1", // invalid + "1E1", // valid, e or E + "1ee1", // invalid + "100a", // invalid + "10.", // invalid + "-0.12", // valid + "0]", // invalid + "0e]", // invalid + "0e+]", // invalid + "1.2.3", // invalid + "0.0.0", // invalid + "9223372036854775807", // valid + "9223372036854775808", // valid + "9223372036854775807.1", // valid + " 9223372036854775807", // valid + " 9223372036854775808", // valid + " 9223372036854775807.1", // valid + "\n9223372036854775807", // valid + "\n9223372036854775808", // valid + "\n9223372036854775807.1", // valid + "-12.000000", // valid +}, []string{ + // Test cases from strconv. + + // Copyright 2009 The Go Authors. All rights reserved. + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + "1e23", + "1E23", + "100000000000000000000000", + "1e-100", + "123456700", + "99999999999999974834176", + "100000000000000000000001", + "100000000000000008388608", + "100000000000000016777215", + "100000000000000016777216", + "1e-20", + "625e-3", + + // zeros + "0", + "0e0", + "-0e0", + "+0e0", + "0e-0", + "-0e-0", + "+0e-0", + "0e+0", + "-0e+0", + "+0e+0", + "0e+01234567890123456789", + "0.00e-01234567890123456789", + "-0e+01234567890123456789", + "-0.00e-01234567890123456789", + + "0e291", + "0e292", + "0e347", + "0e348", + "-0e291", + "-0e292", + "-0e347", + "-0e348", + + // NaNs + "nan", + "NaN", + "NAN", + + // Infs + "inf", + "-Inf", + "+INF", + "-Infinity", + "+INFINITY", + "Infinity", + + // largest float64 + "1.7976931348623157e308", + "-1.7976931348623157e308", + + // next float64 - too large + // "1.7976931348623159e308", // json.Valid checks overflow. + // "-1.7976931348623159e308", // json.Valid checks overflow. + + // the border is ...158079 + // borderline - okay + "1.7976931348623158e308", + "-1.7976931348623158e308", + // borderline - too large + // "1.797693134862315808e308", // json.Valid checks overflow. + // "-1.797693134862315808e308", // json.Valid checks overflow. + + // a little too large + "1e308", + // "2e308", // json.Valid checks overflow. + // "1e309", // json.Valid checks overflow. + + // way too large + // "1e310", // json.Valid check overflow. + // "-1e310", // json.Valid check overflow. + // "1e400", // json.Valid check overflow. + // "-1e400", // json.Valid check overflow. + // "1e400000", // json.Valid check overflow. + // "-1e400000", // json.Valid check overflow. + + // denormalized + "1e-305", + "1e-306", + "1e-307", + "1e-308", + "1e-309", + "1e-310", + "1e-322", + // smallest denormal + "5e-324", + "4e-324", + "3e-324", + // too small + "2e-324", + // way too small + "1e-350", + "1e-400000", + + // try to overflow exponent + "1e-4294967296", + // "1e+4294967296", // json.Valid check overflow. + "1e-18446744073709551616", + // "1e+18446744073709551616", // json.Valid check overflow. + + // Parse errors + "1e", + "1e-", + ".e-1", + "1\x00.2", + + // https://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ + "2.2250738585072012e-308", + // https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ + "2.2250738585072011e-308", + + // A very large number (initially wrongly parsed by the fast algorithm). + "4.630813248087435e+307", + + // A different kind of very large number. + "22.222222222222222", + "2." + strings.Repeat("2", 4000) + "e+1", + + // Exactly halfway between 1 and math.Nextafter(1, 2). + // Round to even (down). + "1.00000000000000011102230246251565404236316680908203125", + // Slightly lower; still round down. + "1.00000000000000011102230246251565404236316680908203124", + // Slightly higher; round up. + "1.00000000000000011102230246251565404236316680908203126", + // Slightly higher, but you have to read all the way to the end. + "1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1", + + // Halfway between x := math.Nextafter(1, 2) and math.Nextafter(x, 2) + // Round to even (up). + "1.00000000000000033306690738754696212708950042724609375", + + // Halfway between 1090544144181609278303144771584 and 1090544144181609419040633126912 + // (15497564393479157p+46, should round to even 15497564393479156p+46, issue 36657) + "1090544144181609348671888949248", + // slightly above, rounds up + "1090544144181609348835077142190", +}...) var testStrings = append([]string{ `""`, // valid diff --git a/float_test.go b/float_test.go index be4ab61..ee98e96 100644 --- a/float_test.go +++ b/float_test.go @@ -15,7 +15,7 @@ import ( // epsilon to compare floats. const epsilon = 1e-6 -func Test_read_big_float(t *testing.T) { +func TestReadBigFloat(t *testing.T) { should := require.New(t) r := DecodeStr(`12.3`) val, err := r.BigFloat() @@ -24,7 +24,7 @@ func Test_read_big_float(t *testing.T) { should.Equal(12.3, val64) } -func Test_read_big_int(t *testing.T) { +func TestReadBigInt(t *testing.T) { should := require.New(t) iter := DecodeStr(`92233720368547758079223372036854775807`) val, err := iter.BigInt() @@ -33,7 +33,7 @@ func Test_read_big_int(t *testing.T) { should.Equal(`92233720368547758079223372036854775807`, val.String()) } -func Test_encode_inf(t *testing.T) { +func TestEncodeInf(t *testing.T) { should := require.New(t) _, err := json.Marshal(math.Inf(1)) should.Error(err) @@ -43,7 +43,7 @@ func Test_encode_inf(t *testing.T) { should.Error(err) } -func Test_encode_nan(t *testing.T) { +func TestEncodeNaN(t *testing.T) { should := require.New(t) _, err := json.Marshal(math.NaN()) should.Error(err) @@ -53,54 +53,70 @@ func Test_encode_nan(t *testing.T) { should.Error(err) } -func Test_read_float(t *testing.T) { +func TestReadFloat(t *testing.T) { inputs := []string{ - `1.1`, `1000`, `9223372036854775807`, `12.3`, `-12.3`, `720368.54775807`, `720368.547758075`, - `1e1`, `1e+1`, `1e-1`, `1E1`, `1E+1`, `1E-1`, `-1e1`, `-1e+1`, `-1e-1`, + `1.1`, + `1000`, + `9223372036854775807`, + `12.3`, + `-12.3`, + `720368.54775807`, + `720368.547758075`, + `1e1`, + `1e+1`, + `1e-1`, + `1E1`, + `1E+1`, + `1E-1`, + `-1e1`, + `-1e+1`, + `-1e-1`, } - for _, input := range inputs { - // non-streaming - t.Run(input, func(t *testing.T) { - should := require.New(t) - r := DecodeStr(input + ",") - expected, err := strconv.ParseFloat(input, 32) - should.NoError(err) - got, err := r.Float32() - should.NoError(err) - should.Equal(float32(expected), got) - }) - t.Run(input, func(t *testing.T) { - should := require.New(t) - r := DecodeStr(input + ",") - expected, err := strconv.ParseFloat(input, 64) - should.NoError(err) - got, err := r.Float64() - should.NoError(err) - should.Equal(expected, got) - }) - t.Run(input, func(t *testing.T) { - should := require.New(t) - iter := Decode(bytes.NewBufferString(input+","), 2) - expected, err := strconv.ParseFloat(input, 32) - should.NoError(err) - got, err := iter.Float32() - should.NoError(err) - should.Equal(float32(expected), got) - }) - t.Run(input, func(t *testing.T) { - should := require.New(t) - iter := Decode(bytes.NewBufferString(input+","), 2) - val := float64(0) - err := json.Unmarshal([]byte(input), &val) - should.NoError(err) - got, err := iter.Float64() - should.NoError(err) - should.Equal(val, got) + for i, input := range inputs { + t.Run(fmt.Sprintf("Test%d", i+1), func(t *testing.T) { + // non-streaming + t.Run("Float32", func(t *testing.T) { + should := require.New(t) + r := DecodeStr(input + ",") + expected, err := strconv.ParseFloat(input, 32) + should.NoError(err) + got, err := r.Float32() + should.NoError(err) + should.Equal(float32(expected), got) + }) + t.Run("Float64", func(t *testing.T) { + should := require.New(t) + r := DecodeStr(input + ",") + expected, err := strconv.ParseFloat(input, 64) + should.NoError(err) + got, err := r.Float64() + should.NoError(err) + should.Equal(expected, got) + }) + t.Run("Reader", func(t *testing.T) { + should := require.New(t) + iter := Decode(bytes.NewBufferString(input+","), 2) + expected, err := strconv.ParseFloat(input, 32) + should.NoError(err) + got, err := iter.Float32() + should.NoError(err) + should.Equal(float32(expected), got) + }) + t.Run("StdJSONCompliance", func(t *testing.T) { + should := require.New(t) + iter := Decode(bytes.NewBufferString(input+","), 2) + val := float64(0) + err := json.Unmarshal([]byte(input), &val) + should.NoError(err) + got, err := iter.Float64() + should.NoError(err) + should.Equal(val, got) + }) }) } } -func Test_write_float32(t *testing.T) { +func TestWriteFloat32(t *testing.T) { vals := []float32{0, 1, -1, 99, 0xff, 0xfff, 0xffff, 0xfffff, 0xffffff, 0x4ffffff, 0xfffffff, -0x4ffffff, -0xfffffff, 1.2345, 1.23456, 1.234567, 1.001} for _, val := range vals { @@ -119,7 +135,7 @@ func Test_write_float32(t *testing.T) { should.Equal("1e-7", string(e.Bytes())) } -func Test_write_float64(t *testing.T) { +func TestWriteFloat64(t *testing.T) { vals := []float64{0, 1, -1, 99, 0xff, 0xfff, 0xffff, 0xfffff, 0xffffff, 0x4ffffff, 0xfffffff, -0x4ffffff, -0xfffffff, 1.2345, 1.23456, 1.234567, 1.001} for _, val := range vals { diff --git a/int_test.go b/int_test.go index bff3d31..79fe90f 100644 --- a/int_test.go +++ b/int_test.go @@ -12,14 +12,14 @@ import ( "github.com/stretchr/testify/require" ) -func Test_read_uint64_invalid(t *testing.T) { +func TestReadUint64Invalid(t *testing.T) { should := require.New(t) iter := DecodeStr(",") _, err := iter.UInt64() should.Error(err) } -func TestDecoder_int_numbers(t *testing.T) { +func TestDecoderIntNumbers(t *testing.T) { for i := 1; i < 10; i++ { // 10 digits var data []byte v := 0 @@ -72,7 +72,7 @@ func TestDecoder_int_numbers(t *testing.T) { } } -func Test_read_int32(t *testing.T) { +func TestReadInt32(t *testing.T) { inputs := []string{`1`, `12`, `123`, `1234`, `12345`, `123456`, `2147483647`, `-2147483648`} for _, input := range inputs { t.Run(input, func(t *testing.T) { @@ -96,7 +96,7 @@ func Test_read_int32(t *testing.T) { } } -func TestDecoder_int_overflow(t *testing.T) { +func TestDecoderIntOverflow(t *testing.T) { t.Run("32", func(t *testing.T) { for _, s := range []string{ "18446744073709551617", @@ -167,14 +167,14 @@ func TestDecoder_int_overflow(t *testing.T) { }) } -func Test_read_int64_overflow(t *testing.T) { +func TestReadInt64Overflow(t *testing.T) { s := `123456789232323232321545111111111111111111111111111111145454545445` iter := DecodeStr(s) _, err := iter.Int64() require.Error(t, err) } -func Test_read_int64(t *testing.T) { +func TestReadInt64(t *testing.T) { inputs := []string{`1`, `12`, `123`, `1234`, `12345`, `123456`, `9223372036854775807`, `-9223372036854775808`} for _, input := range inputs { t.Run(input, func(t *testing.T) { @@ -198,7 +198,7 @@ func Test_read_int64(t *testing.T) { } } -func Test_write_uint32(t *testing.T) { +func TestWriteUint32(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) { @@ -215,7 +215,7 @@ func Test_write_uint32(t *testing.T) { should.Equal("a4294967295", e.String()) } -func Test_write_int32(t *testing.T) { +func TestWriteInt32(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) { @@ -232,7 +232,7 @@ func Test_write_int32(t *testing.T) { should.Equal("a-2147483647", e.String()) } -func Test_write_uint64(t *testing.T) { +func TestWriteUint64(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} @@ -251,7 +251,7 @@ func Test_write_uint64(t *testing.T) { should.Equal("a4294967295", e.String()) } -func Test_write_int64(t *testing.T) { +func TestWriteInt64(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} diff --git a/null_test.go b/null_test.go index 1e08150..6a633a1 100644 --- a/null_test.go +++ b/null_test.go @@ -6,14 +6,14 @@ import ( "github.com/stretchr/testify/require" ) -func Test_write_null(t *testing.T) { +func TestWriteNull(t *testing.T) { should := require.New(t) e := GetEncoder() e.Null() should.Equal("null", e.String()) } -func Test_decode_null_array_element(t *testing.T) { +func TestDecodeNullArrayElement(t *testing.T) { should := require.New(t) iter := DecodeStr(`[null,"a"]`) should.True(iter.Elem()) @@ -24,7 +24,7 @@ func Test_decode_null_array_element(t *testing.T) { should.Equal("a", s) } -func Test_decode_null_string(t *testing.T) { +func TestDecodeNullString(t *testing.T) { should := require.New(t) iter := DecodeStr(`[null,"a"]`) should.True(iter.Elem()) @@ -35,7 +35,7 @@ func Test_decode_null_string(t *testing.T) { should.Equal("a", s) } -func Test_decode_null_skip(t *testing.T) { +func TestDecodeNullSkip(t *testing.T) { iter := DecodeStr(`[null,"a"]`) iter.Elem() iter.Skip() diff --git a/obj_test.go b/obj_test.go index 6d99da1..2d391f1 100644 --- a/obj_test.go +++ b/obj_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func Test_empty_object(t *testing.T) { +func TestEmptyObject(t *testing.T) { iter := DecodeStr(`{}`) require.NoError(t, iter.Obj(func(iter *Decoder, field string) error { t.Error("should not call") @@ -17,7 +17,7 @@ func Test_empty_object(t *testing.T) { })) } -func Test_one_field(t *testing.T) { +func TestOneField(t *testing.T) { should := require.New(t) d := DecodeStr(`{"a": "stream"}`) should.NoError(d.Obj(func(iter *Decoder, field string) error { diff --git a/string_test.go b/string_test.go index 19292b9..8960c36 100644 --- a/string_test.go +++ b/string_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" ) -func Test_read_string(t *testing.T) { +func TestReadString(t *testing.T) { badInputs := []string{ ``, `null`,