commit 351d8479a311a6afdea8bac4f8f28de77eb1e880
parent 1da60bb4601ddd313012d7e9bc0e5d1deba2cbc3
Author: francoispqt <francois@parquet.ninja>
Date: Tue, 1 May 2018 11:19:37 +0800
add tests for encode api, fix race condition in stream tests, update make cover to use atomic covermode
Diffstat:
19 files changed, 353 insertions(+), 111 deletions(-)
diff --git a/Makefile b/Makefile
@@ -4,7 +4,7 @@ test:
.PHONY: cover
cover:
- go test -coverprofile=coverage.out
+ go test -coverprofile=coverage.out -covermode=atomic
.PHONY: coverhtml
coverhtml:
diff --git a/decode_pool.go b/decode_pool.go
@@ -59,9 +59,9 @@ func borrowDecoder(r io.Reader, bufSize int) *Decoder {
// If a decoder is used after calling Release
// a panic will be raised with an InvalidUsagePooledDecoderError error.
func (dec *Decoder) Release() {
+ dec.isPooled = 1
select {
case decPool <- dec:
- dec.isPooled = 1
default:
}
}
diff --git a/decode_stream_pool.go b/decode_stream_pool.go
@@ -58,9 +58,9 @@ func (s stream) borrowDecoder(r io.Reader, bufSize int) *StreamDecoder {
// If a decoder is used after calling Release
// a panic will be raised with an InvalidUsagePooledDecoderError error.
func (dec *StreamDecoder) Release() {
+ dec.isPooled = 1
select {
case streamDecPool <- dec:
- dec.isPooled = 1
default:
}
}
diff --git a/encode.go b/encode.go
@@ -126,39 +126,39 @@ func Marshal(v interface{}) ([]byte, error) {
defer enc.Release()
case int:
enc := BorrowEncoder(nil)
- b, err = enc.encodeInt(int64(vt))
+ b, err = enc.encodeInt(vt)
defer enc.Release()
case int64:
enc := BorrowEncoder(nil)
defer enc.Release()
- return enc.encodeInt(vt)
+ return enc.encodeInt64(vt)
case int32:
enc := BorrowEncoder(nil)
defer enc.Release()
- return enc.encodeInt(int64(vt))
+ return enc.encodeInt(int(vt))
case int16:
enc := BorrowEncoder(nil)
defer enc.Release()
- return enc.encodeInt(int64(vt))
+ return enc.encodeInt(int(vt))
case int8:
enc := BorrowEncoder(nil)
defer enc.Release()
- return enc.encodeInt(int64(vt))
+ return enc.encodeInt(int(vt))
case uint64:
enc := BorrowEncoder(nil)
defer enc.Release()
- return enc.encodeInt(int64(vt))
+ return enc.encodeInt(int(vt))
case uint32:
enc := BorrowEncoder(nil)
defer enc.Release()
- return enc.encodeInt(int64(vt))
+ return enc.encodeInt(int(vt))
case uint16:
enc := BorrowEncoder(nil)
defer enc.Release()
- return enc.encodeInt(int64(vt))
+ return enc.encodeInt(int(vt))
case uint8:
enc := BorrowEncoder(nil)
- b, err = enc.encodeInt(int64(vt))
+ b, err = enc.encodeInt(int(vt))
defer enc.Release()
case float64:
enc := BorrowEncoder(nil)
@@ -167,7 +167,7 @@ func Marshal(v interface{}) ([]byte, error) {
case float32:
enc := BorrowEncoder(nil)
defer enc.Release()
- return enc.encodeFloat(float64(vt))
+ return enc.encodeFloat32(vt)
default:
err = InvalidMarshalError(fmt.Sprintf(invalidMarshalErrorMsg, reflect.TypeOf(vt).String()))
}
diff --git a/encode_array.go b/encode_array.go
@@ -1,11 +1,17 @@
package gojay
// EncodeArray encodes an implementation of MarshalerArray to JSON
-func (enc *Encoder) EncodeArray(v MarshalerArray) ([]byte, error) {
+func (enc *Encoder) EncodeArray(v MarshalerArray) error {
if enc.isPooled == 1 {
panic(InvalidUsagePooledEncoderError("Invalid usage of pooled encoder"))
}
- return enc.encodeArray(v)
+ _, _ = enc.encodeArray(v)
+ _, err := enc.write()
+ if err != nil {
+ enc.err = err
+ return err
+ }
+ return nil
}
func (enc *Encoder) encodeArray(v MarshalerArray) ([]byte, error) {
enc.grow(200)
diff --git a/encode_array_test.go b/encode_array_test.go
@@ -1,6 +1,7 @@
package gojay
import (
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -136,17 +137,27 @@ func TestEncoderArrayInterfacesEncoderAPI(t *testing.T) {
testBool: true,
},
}
- enc := BorrowEncoder(nil)
+ builder := &strings.Builder{}
+ enc := BorrowEncoder(builder)
defer enc.Release()
- r, err := enc.EncodeArray(v)
+ err := enc.EncodeArray(v)
assert.Nil(t, err, "Error should be nil")
assert.Equal(
t,
`[1,1,1,1,1,1,1,1,1.31,[],true,"test",{"test":"hello world","test2":"foobar","testInt":1,"testBool":true,"testArr":[],"testF64":0,"testF32":0}]`,
- string(r),
+ builder.String(),
"Result of marshalling is different as the one expected")
}
+func TestEncoderArrayInterfacesEncoderAPIWriteError(t *testing.T) {
+ v := &testEncodingArrInterfaces{}
+ w := TestWriterError("")
+ enc := BorrowEncoder(w)
+ defer enc.Release()
+ err := enc.EncodeArray(v)
+ assert.NotNil(t, err, "err should not be nil")
+}
+
func TestEncoderArrayPooledError(t *testing.T) {
v := &testEncodingArrInterfaces{}
enc := BorrowEncoder(nil)
@@ -157,6 +168,6 @@ func TestEncoderArrayPooledError(t *testing.T) {
assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError")
assert.Equal(t, "Invalid usage of pooled encoder", err.(InvalidUsagePooledEncoderError).Error(), "err should be of type InvalidUsagePooledDecoderError")
}()
- _, _ = enc.EncodeArray(v)
+ _ = enc.EncodeArray(v)
assert.True(t, false, "should not be called as it should have panicked")
}
diff --git a/encode_bool.go b/encode_bool.go
@@ -3,11 +3,17 @@ package gojay
import "strconv"
// EncodeBool encodes a bool to JSON
-func (enc *Encoder) EncodeBool(v bool) ([]byte, error) {
+func (enc *Encoder) EncodeBool(v bool) error {
if enc.isPooled == 1 {
panic(InvalidUsagePooledEncoderError("Invalid usage of pooled encoder"))
}
- return enc.encodeBool(v)
+ _, _ = enc.encodeBool(v)
+ _, err := enc.write()
+ if err != nil {
+ enc.err = err
+ return err
+ }
+ return nil
}
// encodeBool encodes a bool to JSON
diff --git a/encode_bool_test.go b/encode_bool_test.go
@@ -1,29 +1,33 @@
package gojay
import (
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestEncoderBoolTrue(t *testing.T) {
- enc := BorrowEncoder(nil)
+ builder := &strings.Builder{}
+ enc := BorrowEncoder(builder)
defer enc.Release()
- b, err := enc.EncodeBool(true)
+ err := enc.EncodeBool(true)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, "true", string(b), "string(b) must be equal to 'true'")
+ assert.Equal(t, "true", builder.String(), "string(b) must be equal to 'true'")
}
func TestEncoderBoolFalse(t *testing.T) {
- enc := BorrowEncoder(nil)
+ builder := &strings.Builder{}
+ enc := BorrowEncoder(builder)
defer enc.Release()
- b, err := enc.EncodeBool(false)
+ err := enc.EncodeBool(false)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, "false", string(b), "string(b) must be equal to 'false'")
+ assert.Equal(t, "false", builder.String(), "string(b) must be equal to 'false'")
}
func TestEncoderBoolPoolError(t *testing.T) {
- enc := BorrowEncoder(nil)
+ builder := &strings.Builder{}
+ enc := BorrowEncoder(builder)
enc.Release()
defer func() {
err := recover()
@@ -31,6 +35,14 @@ func TestEncoderBoolPoolError(t *testing.T) {
assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError")
assert.Equal(t, "Invalid usage of pooled encoder", err.(InvalidUsagePooledEncoderError).Error(), "err should be of type InvalidUsagePooledEncoderError")
}()
- _, _ = enc.EncodeBool(false)
+ _ = enc.EncodeBool(false)
assert.True(t, false, "should not be called as it should have panicked")
}
+func TestEncoderBoolPoolEncoderAPIWriteError(t *testing.T) {
+ v := true
+ w := TestWriterError("")
+ enc := BorrowEncoder(w)
+ defer enc.Release()
+ err := enc.EncodeBool(v)
+ assert.NotNil(t, err, "err should not be nil")
+}
diff --git a/encode_interface.go b/encode_interface.go
@@ -9,41 +9,41 @@ import (
//
// If Encode cannot find a way to encode the type to JSON
// it will return an InvalidMarshalError.
-func (enc *Encoder) Encode(v interface{}) ([]byte, error) {
+func (enc *Encoder) Encode(v interface{}) error {
if enc.isPooled == 1 {
panic(InvalidUsagePooledEncoderError("Invalid usage of pooled encoder"))
}
switch vt := v.(type) {
case string:
- return enc.encodeString(vt)
+ return enc.EncodeString(vt)
case bool:
- return enc.encodeBool(vt)
+ return enc.EncodeBool(vt)
case MarshalerArray:
- return enc.encodeArray(vt)
+ return enc.EncodeArray(vt)
case MarshalerObject:
- return enc.encodeObject(vt)
+ return enc.EncodeObject(vt)
case int:
- return enc.encodeInt(int64(vt))
+ return enc.EncodeInt(vt)
case int64:
- return enc.encodeInt(vt)
+ return enc.EncodeInt64(vt)
case int32:
- return enc.encodeInt(int64(vt))
+ return enc.EncodeInt(int(vt))
case int8:
- return enc.encodeInt(int64(vt))
+ return enc.EncodeInt(int(vt))
case uint64:
- return enc.encodeInt(int64(vt))
+ return enc.EncodeInt(int(vt))
case uint32:
- return enc.encodeInt(int64(vt))
+ return enc.EncodeInt(int(vt))
case uint16:
- return enc.encodeInt(int64(vt))
+ return enc.EncodeInt(int(vt))
case uint8:
- return enc.encodeInt(int64(vt))
+ return enc.EncodeInt(int(vt))
case float64:
- return enc.encodeFloat(vt)
+ return enc.EncodeFloat(vt)
case float32:
- return enc.encodeFloat(float64(vt))
+ return enc.EncodeFloat32(vt)
default:
- return nil, InvalidMarshalError(fmt.Sprintf(invalidMarshalErrorMsg, reflect.TypeOf(vt).String()))
+ return InvalidMarshalError(fmt.Sprintf(invalidMarshalErrorMsg, reflect.TypeOf(vt).String()))
}
}
diff --git a/encode_interface_test.go b/encode_interface_test.go
@@ -3,6 +3,7 @@ package gojay
import (
"fmt"
"reflect"
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -10,109 +11,116 @@ import (
var encoderTestCases = []struct {
v interface{}
- expectations func(t *testing.T, b []byte, err error)
+ expectations func(t *testing.T, b string, err error)
}{
{
v: 100,
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "100", string(b), "string(b) should equal 100")
+ assert.Equal(t, "100", b, "b should equal 100")
},
},
{
v: int64(100),
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "100", string(b), "string(b) should equal 100")
+ assert.Equal(t, "100", b, "b should equal 100")
},
},
{
v: int32(100),
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "100", string(b), "string(b) should equal 100")
+ assert.Equal(t, "100", b, "b should equal 100")
},
},
{
v: int8(100),
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "100", string(b), "string(b) should equal 100")
+ assert.Equal(t, "100", b, "b should equal 100")
},
},
{
v: uint64(100),
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "100", string(b), "string(b) should equal 100")
+ assert.Equal(t, "100", b, "b should equal 100")
},
},
{
v: uint32(100),
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "100", string(b), "string(b) should equal 100")
+ assert.Equal(t, "100", b, "b should equal 100")
},
},
{
v: uint16(100),
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "100", string(b), "string(b) should equal 100")
+ assert.Equal(t, "100", b, "b should equal 100")
},
},
{
v: uint8(100),
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "100", string(b), "string(b) should equal 100")
+ assert.Equal(t, "100", b, "b should equal 100")
},
},
{
v: float64(100.12),
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "100.12", string(b), "string(b) should equal 100.12")
+ assert.Equal(t, "100.12", b, "b should equal 100.12")
+ },
+ },
+ {
+ v: float32(100.12),
+ expectations: func(t *testing.T, b string, err error) {
+ assert.Nil(t, err, "err should be nil")
+ assert.Equal(t, "100.12", b, "b should equal 100.12")
},
},
{
v: true,
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, "true", string(b), "string(b) should equal true")
+ assert.Equal(t, "true", b, "b should equal true")
},
},
{
v: "hello world",
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, `"hello world"`, string(b), `string(b) should equal "hello world"`)
+ assert.Equal(t, `"hello world"`, b, `b should equal "hello world"`)
},
},
{
v: "hello world",
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, `"hello world"`, string(b), `string(b) should equal "hello world"`)
+ assert.Equal(t, `"hello world"`, b, `b should equal "hello world"`)
},
},
{
v: &TestEncodingArrStrings{"hello world", "foo bar"},
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, `["hello world","foo bar"]`, string(b), `string(b) should equal ["hello world","foo bar"]`)
+ assert.Equal(t, `["hello world","foo bar"]`, b, `b should equal ["hello world","foo bar"]`)
},
},
{
v: &testObject{"漢字", 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.1, 1.1, true},
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
assert.Equal(t, `{"testStr":"漢字","testInt":1,"testInt64":1,"testInt32":1,"testInt16":1,"testInt8":1,"testUint64":1,"testUint32":1,"testUint16":1,"testUint8":1,"testFloat64":1.1,"testFloat32":1.1,"testBool":true}`, string(b), `string(b) should equal {"testStr":"漢字","testInt":1,"testInt64":1,"testInt32":1,"testInt16":1,"testInt8":1,"testUint64":1,"testUint32":1,"testUint16":1,"testUint8":1,"testFloat64":1.1,"testFloat32":1.1,"testBool":true}`)
},
},
{
v: &struct{}{},
- expectations: func(t *testing.T, b []byte, err error) {
+ expectations: func(t *testing.T, b string, err error) {
assert.NotNil(t, err, "err should be nil")
assert.IsType(t, InvalidMarshalError(""), err, "err should be of type InvalidMarshalError")
assert.Equal(t, fmt.Sprintf(invalidMarshalErrorMsg, reflect.TypeOf(&struct{}{}).String()), err.Error(), "err message should be equal to invalidMarshalErrorMsg")
@@ -120,18 +128,41 @@ var encoderTestCases = []struct {
},
}
-func TestEncoderInterfaceAllTypesDecoderAPI(t *testing.T) {
+func TestEncoderInterfaceAllTypesEncoderAPI(t *testing.T) {
for _, test := range encoderTestCases {
- enc := BorrowEncoder(nil)
- b, err := enc.Encode(test.v)
+ builder := &strings.Builder{}
+ enc := BorrowEncoder(builder)
+ err := enc.Encode(test.v)
enc.Release()
- test.expectations(t, b, err)
+ test.expectations(t, builder.String(), err)
}
}
+func TestEncoderInterfaceAllTypesEncoderAPIWriteError(t *testing.T) {
+ v := ""
+ w := TestWriterError("")
+ enc := BorrowEncoder(w)
+ err := enc.Encode(v)
+ assert.NotNil(t, err, "err should not be nil")
+}
+
+func TestEncoderInterfaceAllTypesEncoderAPIPoolError(t *testing.T) {
+ v := ""
+ w := TestWriterError("")
+ enc := BorrowEncoder(w)
+ enc.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err should not be nil")
+ assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError")
+ }()
+ _ = enc.Encode(v)
+ assert.True(t, false, "should not be called as decoder should have panicked")
+}
+
func TestEncoderInterfaceAllTypesMarshalAPI(t *testing.T) {
for _, test := range encoderTestCases {
b, err := Marshal(test.v)
- test.expectations(t, b, err)
+ test.expectations(t, string(b), err)
}
}
diff --git a/encode_number.go b/encode_number.go
@@ -3,30 +3,50 @@ package gojay
import "strconv"
// EncodeInt encodes an int to JSON
-func (enc *Encoder) EncodeInt(n int64) ([]byte, error) {
+func (enc *Encoder) EncodeInt(n int) error {
if enc.isPooled == 1 {
panic(InvalidUsagePooledEncoderError("Invalid usage of pooled encoder"))
}
- return enc.encodeInt(n)
+ _, _ = enc.encodeInt(n)
+ _, err := enc.write()
+ if err != nil {
+ return err
+ }
+ return nil
}
// encodeInt encodes an int to JSON
-func (enc *Encoder) encodeInt(n int64) ([]byte, error) {
- s := strconv.Itoa(int(n))
- enc.writeString(s)
+func (enc *Encoder) encodeInt(n int) ([]byte, error) {
+ enc.buf = strconv.AppendInt(enc.buf, int64(n), 10)
return enc.buf, nil
}
-// EncodeFloat encodes a float64 to JSON
-func (enc *Encoder) EncodeFloat(n float64) error {
+// EncodeInt64 encodes an int64 to JSON
+func (enc *Encoder) EncodeInt64(n int64) error {
if enc.isPooled == 1 {
panic(InvalidUsagePooledEncoderError("Invalid usage of pooled encoder"))
}
- _, err := enc.encodeFloat(n)
+ _, _ = enc.encodeInt64(n)
+ _, err := enc.write()
if err != nil {
return err
}
- _, err = enc.write()
+ return nil
+}
+
+// encodeInt64 encodes an int to JSON
+func (enc *Encoder) encodeInt64(n int64) ([]byte, error) {
+ enc.buf = strconv.AppendInt(enc.buf, n, 10)
+ return enc.buf, nil
+}
+
+// EncodeFloat encodes a float64 to JSON
+func (enc *Encoder) EncodeFloat(n float64) error {
+ if enc.isPooled == 1 {
+ panic(InvalidUsagePooledEncoderError("Invalid usage of pooled encoder"))
+ }
+ _, _ = enc.encodeFloat(n)
+ _, err := enc.write()
if err != nil {
return err
}
@@ -44,11 +64,8 @@ func (enc *Encoder) EncodeFloat32(n float32) error {
if enc.isPooled == 1 {
panic(InvalidUsagePooledEncoderError("Invalid usage of pooled encoder"))
}
- _, err := enc.encodeFloat32(n)
- if err != nil {
- return err
- }
- _, err = enc.write()
+ _, _ = enc.encodeFloat32(n)
+ _, err := enc.write()
if err != nil {
return err
}
diff --git a/encode_number_test.go b/encode_number_test.go
@@ -1,6 +1,7 @@
package gojay
import (
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -15,6 +16,36 @@ func TestEncoderInt(t *testing.T) {
string(r),
"Result of marshalling is different as the one expected")
}
+func TestEncoderIntEncodeAPI(t *testing.T) {
+ builder := &strings.Builder{}
+ enc := NewEncoder(builder)
+ err := enc.EncodeInt(1)
+ assert.Nil(t, err, "Error should be nil")
+ assert.Equal(
+ t,
+ `1`,
+ builder.String(),
+ "Result of marshalling is different as the one expected")
+}
+func TestEncoderIntEncodeAPIPoolError(t *testing.T) {
+ builder := &strings.Builder{}
+ enc := NewEncoder(builder)
+ enc.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err should not be nil")
+ assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError")
+ }()
+ _ = enc.EncodeInt(1)
+ assert.True(t, false, "should not be called as decoder should have panicked")
+}
+func TestEncoderIntEncodeAPIWriteError(t *testing.T) {
+ w := TestWriterError("")
+ enc := NewEncoder(w)
+ err := enc.EncodeInt(1)
+ assert.NotNil(t, err, "err should not be nil")
+ assert.Equal(t, "Test Error", err.Error(), "err should be of type InvalidUsagePooledEncoderError")
+}
func TestEncoderInt64(t *testing.T) {
r, err := Marshal(int64(1))
@@ -25,6 +56,36 @@ func TestEncoderInt64(t *testing.T) {
string(r),
"Result of marshalling is different as the one expected")
}
+func TestEncoderInt64EncodeAPI(t *testing.T) {
+ builder := &strings.Builder{}
+ enc := NewEncoder(builder)
+ err := enc.EncodeInt64(int64(1))
+ assert.Nil(t, err, "Error should be nil")
+ assert.Equal(
+ t,
+ `1`,
+ builder.String(),
+ "Result of marshalling is different as the one expected")
+}
+func TestEncoderInt64EncodeAPIPoolError(t *testing.T) {
+ builder := &strings.Builder{}
+ enc := NewEncoder(builder)
+ enc.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err should not be nil")
+ assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError")
+ }()
+ _ = enc.EncodeInt64(1)
+ assert.True(t, false, "should not be called as decoder should have panicked")
+}
+func TestEncoderInt64EncodeAPIWriteError(t *testing.T) {
+ w := TestWriterError("")
+ enc := NewEncoder(w)
+ err := enc.EncodeInt64(1)
+ assert.NotNil(t, err, "err should not be nil")
+ assert.Equal(t, "Test Error", err.Error(), "err should be of type InvalidUsagePooledEncoderError")
+}
func TestEncoderInt32(t *testing.T) {
r, err := Marshal(int32(1))
@@ -101,6 +162,67 @@ func TestEncoderFloat(t *testing.T) {
string(r),
"Result of marshalling is different as the one expected")
}
+func TestEncoderFloatEncodeAPI(t *testing.T) {
+ builder := &strings.Builder{}
+ enc := NewEncoder(builder)
+ err := enc.EncodeFloat(float64(1.1))
+ assert.Nil(t, err, "Error should be nil")
+ assert.Equal(
+ t,
+ `1.1`,
+ builder.String(),
+ "Result of marshalling is different as the one expected")
+}
+func TestEncoderFloatEncodeAPIPoolError(t *testing.T) {
+ builder := &strings.Builder{}
+ enc := NewEncoder(builder)
+ enc.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err should not be nil")
+ assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError")
+ }()
+ _ = enc.EncodeFloat(1.1)
+ assert.True(t, false, "should not be called as decoder should have panicked")
+}
+func TestEncoderFloatEncodeAPIWriteError(t *testing.T) {
+ w := TestWriterError("")
+ enc := NewEncoder(w)
+ err := enc.EncodeFloat(1.1)
+ assert.NotNil(t, err, "err should not be nil")
+ assert.Equal(t, "Test Error", err.Error(), "err should be of type InvalidUsagePooledEncoderError")
+}
+
+func TestEncoderFloat32EncodeAPI(t *testing.T) {
+ builder := &strings.Builder{}
+ enc := NewEncoder(builder)
+ err := enc.EncodeFloat32(float32(1.12))
+ assert.Nil(t, err, "Error should be nil")
+ assert.Equal(
+ t,
+ `1.12`,
+ builder.String(),
+ "Result of marshalling is different as the one expected")
+}
+func TestEncoderFloat32EncodeAPIPoolError(t *testing.T) {
+ builder := &strings.Builder{}
+ enc := NewEncoder(builder)
+ enc.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err should not be nil")
+ assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError")
+ }()
+ _ = enc.EncodeFloat32(float32(1.1))
+ assert.True(t, false, "should not be called as decoder should have panicked")
+}
+func TestEncoderFloat32EncodeAPIWriteError(t *testing.T) {
+ w := TestWriterError("")
+ enc := NewEncoder(w)
+ err := enc.EncodeFloat32(float32(1.1))
+ assert.NotNil(t, err, "err should not be nil")
+ assert.Equal(t, "Test Error", err.Error(), "err should be of type InvalidUsagePooledEncoderError")
+}
func TestEncoderIntPooledError(t *testing.T) {
v := 1
@@ -112,7 +234,7 @@ func TestEncoderIntPooledError(t *testing.T) {
assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError")
assert.Equal(t, "Invalid usage of pooled encoder", err.(InvalidUsagePooledEncoderError).Error(), "err should be of type InvalidUsagePooledDecoderError")
}()
- _, _ = enc.EncodeInt(int64(v))
+ _ = enc.EncodeInt(v)
assert.True(t, false, "should not be called as it should have panicked")
}
diff --git a/encode_object_test.go b/encode_object_test.go
@@ -1,7 +1,6 @@
package gojay
import (
- "errors"
"strings"
"testing"
@@ -67,14 +66,8 @@ func TestEncoderObjectBasicEncoderApi(t *testing.T) {
)
}
-type TestWiterError string
-
-func (t TestWiterError) Write(b []byte) (int, error) {
- return 0, errors.New("Test Error")
-}
-
func TestEncoderObjectBasicEncoderApiError(t *testing.T) {
- w := TestWiterError("")
+ w := TestWriterError("")
enc := NewEncoder(w)
err := enc.EncodeObject(&testObject{"漢字", 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.1, 1.1, true})
assert.NotNil(t, err, "Error should not be nil")
diff --git a/encode_pool.go b/encode_pool.go
@@ -29,9 +29,9 @@ func BorrowEncoder(w io.Writer) *Encoder {
// Release sends back a Encoder to the pool.
func (enc *Encoder) Release() {
enc.buf = nil
+ enc.isPooled = 1
select {
case encPool <- enc:
- enc.isPooled = 1
default:
}
}
diff --git a/encode_stream.go b/encode_stream.go
@@ -145,11 +145,7 @@ func consume(init *StreamEncoder, s *StreamEncoder, m MarshalerStream) {
return
}
i, err := s.Encoder.write()
- if i == 0 {
- init.Cancel(err)
- return
- }
- if err != nil {
+ if err != nil || i == 0 {
init.Cancel(err)
return
}
diff --git a/encode_stream_test.go b/encode_stream_test.go
@@ -110,6 +110,19 @@ func TestEncodeStreamSingleConsumerMarshalError(t *testing.T) {
assert.NotNil(t, enc.Err(), "enc.Err() should not be nil")
}
}
+
+func TestEncodeStreamSingleConsumerWriteError(t *testing.T) {
+ // create our writer
+ w := TestWriterError("")
+ enc := Stream.NewEncoder(w).LineDelimited()
+ s := StreamChanObject(make(chan *testObject))
+ go enc.EncodeStream(s)
+ go feedStream(s, 100)
+ select {
+ case <-enc.Done():
+ assert.NotNil(t, enc.Err(), "enc.Err() should not be nil")
+ }
+}
func TestEncodeStreamSingleConsumerCommaDelimited(t *testing.T) {
expectedStr :=
`{"testStr":"","testInt":0,"testInt64":0,"testInt32":0,"testInt16":0,"testInt8":0,"testUint64":0,"testUint32":0,"testUint16":0,"testUint8":0,"testFloat64":0,"testFloat32":0,"testBool":false},`
diff --git a/encode_string.go b/encode_string.go
@@ -1,11 +1,17 @@
package gojay
// EncodeString encodes a string to
-func (enc *Encoder) EncodeString(s string) ([]byte, error) {
+func (enc *Encoder) EncodeString(s string) error {
if enc.isPooled == 1 {
panic(InvalidUsagePooledEncoderError("Invalid usage of pooled encoder"))
}
- return enc.encodeString(s)
+ _, _ = enc.encodeString(s)
+ _, err := enc.write()
+ if err != nil {
+ enc.err = err
+ return err
+ }
+ return nil
}
// encodeString encodes a string to
diff --git a/encode_string_test.go b/encode_string_test.go
@@ -1,6 +1,7 @@
package gojay
import (
+ "strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -15,6 +16,17 @@ func TestEncoderString(t *testing.T) {
string(r),
"Result of marshalling is different as the one expected")
}
+func TestEncoderStringEncodeAPI(t *testing.T) {
+ builder := &strings.Builder{}
+ enc := NewEncoder(builder)
+ err := enc.EncodeString("漢字")
+ assert.Nil(t, err, "Error should be nil")
+ assert.Equal(
+ t,
+ `"漢字"`,
+ builder.String(),
+ "Result of marshalling is different as the one expected")
+}
func TestEncoderStringUTF8(t *testing.T) {
r, err := Marshal("漢字")
@@ -36,6 +48,15 @@ func TestEncoderStringPooledError(t *testing.T) {
assert.IsType(t, InvalidUsagePooledEncoderError(""), err, "err should be of type InvalidUsagePooledEncoderError")
assert.Equal(t, "Invalid usage of pooled encoder", err.(InvalidUsagePooledEncoderError).Error(), "err should be of type InvalidUsagePooledDecoderError")
}()
- _, _ = enc.EncodeString(v)
+ _ = enc.EncodeString(v)
assert.True(t, false, "should not be called as it should have panicked")
}
+
+func TestEncoderStringPoolEncoderAPIWriteError(t *testing.T) {
+ v := "test"
+ w := TestWriterError("")
+ enc := BorrowEncoder(w)
+ defer enc.Release()
+ err := enc.EncodeString(v)
+ assert.NotNil(t, err, "err should not be nil")
+}
diff --git a/encode_test.go b/encode_test.go
@@ -1 +1,9 @@
package gojay
+
+import "errors"
+
+type TestWriterError string
+
+func (t TestWriterError) Write(b []byte) (int, error) {
+ return 0, errors.New("Test Error")
+}