Skip to content

Commit

Permalink
add decoding interface tests
Browse files Browse the repository at this point in the history
  • Loading branch information
shamaton committed Aug 6, 2024
1 parent 912c5b1 commit fa57eea
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 29 deletions.
5 changes: 3 additions & 2 deletions internal/common/testutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package testutil

import (
"errors"
"reflect"
"strings"
"testing"
)
Expand Down Expand Up @@ -37,9 +38,9 @@ func ErrorContains(t *testing.T, err error, errStr string) {
}
}

func Equal[T comparable](t *testing.T, actual, expected T) {
func Equal[T any](t *testing.T, actual, expected T) {
t.Helper()
if actual != expected {
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("not equal. actual: %v, expected: %v", actual, expected)
}
}
Expand Down
4 changes: 2 additions & 2 deletions internal/stream/decoding/decoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
tu "github.com/shamaton/msgpack/v2/internal/common/testutil"
)

type AsXXXTestCase[T comparable] struct {
type AsXXXTestCase[T any] struct {
Name string
Code byte
Data []byte
Expand All @@ -23,7 +23,7 @@ type AsXXXTestCase[T comparable] struct {
MethodAsCustom func(d *decoder) (T, error)
}

type AsXXXTestCases[T comparable] []AsXXXTestCase[T]
type AsXXXTestCases[T any] []AsXXXTestCase[T]

func (tc *AsXXXTestCase[T]) Run(t *testing.T) {
const kind = reflect.String
Expand Down
12 changes: 8 additions & 4 deletions internal/stream/decoding/interface.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package decoding

import (
"errors"
"fmt"
"reflect"

Expand All @@ -10,7 +11,7 @@ import (
func (d *decoder) asInterface(k reflect.Kind) (interface{}, error) {
code, err := d.readSize1()
if err != nil {
return 0, err
return nil, err
}
return d.asInterfaceWithCode(code, k)
}
Expand Down Expand Up @@ -133,7 +134,7 @@ func (d *decoder) asInterfaceWithCode(code byte, k reflect.Kind) (interface{}, e
return 0, err
}

if d.canSetAsMapKey(keyCode) != nil {
if err := d.canSetAsMapKey(keyCode); err != nil {
return nil, err
}
key, err := d.asInterfaceWithCode(keyCode, k)
Expand Down Expand Up @@ -166,12 +167,15 @@ func (d *decoder) asInterfaceWithCode(code byte, k reflect.Kind) (interface{}, e
return nil, d.errorTemplate(code, k)
}

var ErrCanNotSetSliceAsMapKey = errors.New("can not set slice as map key")
var ErrCanNotSetMapAsMapKey = errors.New("can not set map as map key")

func (d *decoder) canSetAsMapKey(code byte) error {
switch {
case d.isFixSlice(code), code == def.Array16, code == def.Array32:
return fmt.Errorf("can not use slice code for map key/ code: %x", code)
return fmt.Errorf("%w. code: %x", ErrCanNotSetSliceAsMapKey, code)
case d.isFixMap(code), code == def.Map16, code == def.Map32:
return fmt.Errorf("can not use map code for map key/ code: %x", code)
return fmt.Errorf("%w. code: %x", ErrCanNotSetMapAsMapKey, code)
}
return nil
}
220 changes: 220 additions & 0 deletions internal/stream/decoding/interface_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
package decoding

import (
"fmt"
"io"
"reflect"
"testing"

"github.com/shamaton/msgpack/v2/def"
"github.com/shamaton/msgpack/v2/ext"
)

func Test_asInterface(t *testing.T) {
method := func(d *decoder) func(reflect.Kind) (any, error) {
return d.asInterface
}
testcases := AsXXXTestCases[any]{
{
Name: "error",
Data: []byte{},
Error: io.EOF,
ReadCount: 0,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.Nil},
Expected: nil,
ReadCount: 1,
MethodAs: method,
},
}

for _, tc := range testcases {
tc.Run(t)
}
}

func Test_asInterfaceWithCode(t *testing.T) {
dec := testExt2StreamDecoder{}
AddExtDecoder(&dec)
defer RemoveExtDecoder(&dec)

method := func(d *decoder) func(byte, reflect.Kind) (any, error) {
return d.asInterfaceWithCode
}
testcases := AsXXXTestCases[any]{
{
Name: "Uint8.error",
Code: def.Uint8,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Uint16.error",
Code: def.Uint16,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Uint32.error",
Code: def.Uint32,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Uint64.error",
Code: def.Uint64,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Int8.error",
Code: def.Int8,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Int16.error",
Code: def.Int16,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Int32.error",
Code: def.Int32,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Int64.error",
Code: def.Int64,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Float32.error",
Code: def.Float32,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Float64.error",
Code: def.Float64,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Str.error",
Code: def.Str8,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Bin.error",
Code: def.Bin8,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Array.error.length",
Code: def.Array16,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Array.error.set",
Code: def.Array16,
Data: []byte{0, 1},
ReadCount: 1,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Map.error.length",
Code: def.Map16,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Map.error.set.key_code",
Code: def.Map16,
Data: []byte{0, 1},
ReadCount: 1,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Map.error.set.can.slice",
Code: def.Map16,
Data: []byte{0, 1, def.Array16},
ReadCount: 2,
Error: ErrCanNotSetSliceAsMapKey,
MethodAsWithCode: method,
},
{
Name: "Map.error.set.can.map",
Code: def.Map16,
Data: []byte{0, 1, def.Map16},
ReadCount: 2,
Error: ErrCanNotSetMapAsMapKey,
MethodAsWithCode: method,
},
{
Name: "Map.error.set.key",
Code: def.Map16,
Data: []byte{0, 1, def.FixStr + 1},
ReadCount: 2,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Map.error.set.value",
Code: def.Map16,
Data: []byte{0, 1, def.FixStr + 1, 'a'},
ReadCount: 3,
Error: io.EOF,
MethodAsWithCode: method,
},
{
Name: "Ext.error",
Code: def.Fixext1,
Data: []byte{3, 0},
ReadCount: 2,
Error: ErrTestExtStreamDecoder,
MethodAsWithCode: method,
},
{
Name: "Unexpected",
Code: def.Fixext1,
Data: []byte{4, 0},
ReadCount: 2,
IsTemplateError: true,
MethodAsWithCode: method,
},
}

for _, tc := range testcases {
tc.Run(t)
}
}

// TODO: to testutil
type testExt2StreamDecoder struct{}

var _ ext.StreamDecoder = (*testExt2StreamDecoder)(nil)

func (td *testExt2StreamDecoder) Code() int8 {
return 3
}

func (td *testExt2StreamDecoder) IsType(_ byte, code int8, _ int) bool {
return code == td.Code()
}

var ErrTestExtStreamDecoder = fmt.Errorf("testExtStreamDecoder")

func (td *testExt2StreamDecoder) ToValue(_ byte, _ []byte, k reflect.Kind) (any, error) {
return nil, ErrTestExtStreamDecoder
}
44 changes: 23 additions & 21 deletions internal/stream/decoding/string_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package decoding

import (
"bytes"
"io"
"math"
"reflect"
"testing"

"github.com/shamaton/msgpack/v2/def"
"github.com/shamaton/msgpack/v2/internal/common"
tu "github.com/shamaton/msgpack/v2/internal/common/testutil"
)

func Test_stringByteLength(t *testing.T) {
Expand Down Expand Up @@ -87,22 +84,27 @@ func Test_asString(t *testing.T) {
}

func Test_asStringByte(t *testing.T) {
t.Run("read error", func(t *testing.T) {
d := decoder{
r: tu.NewErrReader(),
buf: common.GetBuffer(),
}
v, err := d.asStringByte(reflect.String)
tu.IsError(t, err, tu.ErrReaderErr)
tu.EqualSlice(t, v, emptyBytes)
})
t.Run("ok", func(t *testing.T) {
d := decoder{
r: bytes.NewReader([]byte{def.FixStr + 1, 'a'}),
buf: common.GetBuffer(),
}
v, err := d.asStringByte(reflect.String)
tu.NoError(t, err)
tu.EqualSlice(t, v, []byte("a"))
})
method := func(d *decoder) func(reflect.Kind) ([]byte, error) {
return d.asStringByte
}
testcases := AsXXXTestCases[[]byte]{
{
Name: "error",
Data: []byte{def.FixStr + 1},
Error: io.EOF,
ReadCount: 1,
MethodAs: method,
},
{
Name: "ok",
Data: []byte{def.FixStr + 1, 'a'},
Expected: []byte{'a'},
ReadCount: 2,
MethodAs: method,
},
}

for _, tc := range testcases {
tc.Run(t)
}
}

0 comments on commit fa57eea

Please sign in to comment.