Skip to content

Commit

Permalink
Merge pull request #74 from dekarrin/ghi062-testBinary
Browse files Browse the repository at this point in the history
Ghi062 test binary
  • Loading branch information
dekarrin committed Dec 2, 2023
2 parents 403ec4c + adc1ae0 commit 736720b
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 135 deletions.
133 changes: 62 additions & 71 deletions primitives_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package rezi

import (
"encoding"
"errors"
"fmt"
"math"
"math/big"
Expand Down Expand Up @@ -908,103 +909,88 @@ func Test_decText(t *testing.T) {
}

func Test_encBinary(t *testing.T) {
var nilSlice []byte

testCases := []struct {
name string
input encoding.BinaryMarshaler
expect []byte
}{
{
name: "nil bytes",
input: valueThatMarshalsWith(func() []byte {
return nil
}),
name: "nil bytes",
input: testBinary{encOverride: &nilSlice},
expect: []byte{0x00},
},
{
name: "empty bytes",
input: valueThatMarshalsWith(func() []byte {
return []byte{}
}),
name: "empty bytes",
input: testBinary{encOverride: ref([]byte{})},
expect: []byte{0x00},
},
{
name: "1 byte",
input: valueThatMarshalsWith(func() []byte {
return []byte{0xff}
}),
name: "1 byte",
input: testBinary{encOverride: ref([]byte{0xff})},
expect: []byte{0x01, 0x01, 0xff},
},
{
name: "several bytes",
input: valueThatMarshalsWith(func() []byte {
return []byte{0xff, 0x0a, 0x0b, 0x0c, 0x0e}
}),
name: "several bytes",
input: testBinary{encOverride: ref([]byte{0xff, 0x0a, 0x0b, 0x0c, 0x0e})},
expect: []byte{0x01, 0x05, 0xff, 0x0a, 0x0b, 0x0c, 0x0e},
},
{
name: "filled values",
input: testBinary{number: 8, data: "VRISKA"},
expect: []byte{0x01, 0x0b, 0x41, 0x82, 0x06, 0x56, 0x52, 0x49, 0x53, 0x4b, 0x41, 0x01, 0x08},
},
{
name: "empty values",
input: testBinary{},
expect: []byte{0x01, 0x02, 0x00, 0x00},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)

actual, _ := encBinary(tc.input)
actual, err := encBinary(tc.input)
if !assert.NoError(err) {
return
}

assert.Equal(tc.expect, actual)
})
}
}

func Test_decBinary(t *testing.T) {
var received []byte

sendToReceived := func(b []byte) error {
received = make([]byte, len(b))
copy(received, b)
return nil
}

testCases := []struct {
name string
input []byte
expectReceive []byte
expectRead int
expectError bool
consumerFunc func([]byte) error
name string
input []byte
expect testBinary
expectRead int
expectError bool
}{
{
name: "empty",
input: []byte{0x00},
expectReceive: []byte{},
expectRead: 1,
consumerFunc: sendToReceived,
name: "empty",
input: []byte{0x01, 0x02, 0x00, 0x00},
expect: testBinary{},
expectRead: 4,
},
{
name: "nil",
input: []byte{0x00},
expectReceive: []byte{},
expectRead: 1,
consumerFunc: sendToReceived,
name: "filled",
input: []byte{0x01, 0x0b, 0x41, 0x82, 0x06, 0x56, 0x52, 0x49, 0x53, 0x4b, 0x41, 0x01, 0x08},
expect: testBinary{number: 8, data: "VRISKA"},
expectRead: 13,
},
{
name: "1 byte",
input: []byte{0x01, 0x01, 0xff},
expectReceive: []byte{0xff},
expectRead: 3,
consumerFunc: sendToReceived,
name: "filled, followed by unrelated",
input: []byte{0x01, 0x0b, 0x41, 0x82, 0x06, 0x56, 0x52, 0x49, 0x53, 0x4b, 0x41, 0x01, 0x08, 0x01, 0x02, 0x03},
expect: testBinary{number: 8, data: "VRISKA"},
expectRead: 13,
},
{
name: "several bytes, followed by unrelated",
input: []byte{0x01, 0x05, 0xff, 0x0a, 0x0b, 0x0c, 0x0e, 0xff},
expectReceive: []byte{0xff, 0x0a, 0x0b, 0x0c, 0x0e},
expectRead: 7,
consumerFunc: sendToReceived,
},
{
name: "several bytes, but it will error",
input: []byte{0x01, 0x05, 0xff, 0x0a, 0x0b, 0x0c, 0x0e},
consumerFunc: func(b []byte) error {
return fmt.Errorf("error")
},
name: "several bytes, but it will error",
input: []byte{0x01, 0x05, 0xff, 0x0a, 0x0b, 0x0c, 0x0e},
expectError: true,
},
}
Expand All @@ -1013,17 +999,20 @@ func Test_decBinary(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
assert := assert.New(t)

unmarshalTo := valueThatUnmarshalsWith(tc.consumerFunc)
var actual testBinary
if tc.expectError {
actual.decErr = errors.New("error")
}

actualRead, err := decBinary(tc.input, unmarshalTo)
actualRead, err := decBinary(tc.input, &actual)
if tc.expectError {
assert.Error(err)
return
} else if !assert.NoError(err) {
return
}

assert.Equal(tc.expectReceive, received)
assert.Equal(tc.expect, actual)
assert.Equal(tc.expectRead, actualRead, "num read bytes does not match expected")
})
}
Expand Down Expand Up @@ -1904,6 +1893,8 @@ func Test_Enc_Bool(t *testing.T) {
}

func Test_Enc_Binary(t *testing.T) {
var nilSlice []byte

testURL, err := url.Parse("https://github.com/")
if err != nil {
panic(fmt.Sprintf("cannot parse test url: %v", err))
Expand All @@ -1916,24 +1907,24 @@ func Test_Enc_Binary(t *testing.T) {
expect []byte
}{
{
name: "encode to nil bytes",
input: valueThatMarshalsWith(func() []byte { return nil }),
name: "nil bytes",
input: testBinary{encOverride: &nilSlice},
expect: []byte{0x00},
},
{
name: "encode to empty bytes",
input: valueThatMarshalsWith(func() []byte { return []byte{} }),
name: "empty bytes",
input: testBinary{encOverride: ref([]byte{})},
expect: []byte{0x00},
},
{
name: "encode to one byte",
input: valueThatMarshalsWith(func() []byte { return []byte{0x03} }),
expect: []byte{0x01, 0x01, 0x03},
name: "1 byte",
input: testBinary{encOverride: ref([]byte{0xff})},
expect: []byte{0x01, 0x01, 0xff},
},
{
name: "encode to several bytes",
input: valueThatMarshalsWith(func() []byte { return []byte{0x03, 0x44, 0x15} }),
expect: []byte{0x01, 0x03, 0x03, 0x44, 0x15},
name: "several bytes",
input: testBinary{encOverride: ref([]byte{0xff, 0x0a, 0x0b, 0x0c, 0x0e})},
expect: []byte{0x01, 0x05, 0xff, 0x0a, 0x0b, 0x0c, 0x0e},
},
{
name: "actual object",
Expand Down
42 changes: 33 additions & 9 deletions rezi.go
Original file line number Diff line number Diff line change
Expand Up @@ -657,11 +657,11 @@ func MustDec(data []byte, v interface{}) int {
// the data itself (including there being fewer bytes than necessary to decode
// the value).
func Dec(data []byte, v interface{}) (n int, err error) {
// defer func() {
// if r := recover(); r != nil {
// err = errorf("%v", r)
// }
// }()
defer func() {
if r := recover(); r != nil {
err = errorf("%v", r)
}
}()

info, err := canDecode(v)
if err != nil {
Expand Down Expand Up @@ -733,11 +733,11 @@ func decWithNilCheck[E any](data []byte, v interface{}, ti typeInfo, decFn decFu
var extraInfo interface{}

if !hdr.IsNil() {
effectiveExtraIndirs = ti.Indir
decoded, extraInfo, n, err = decFn(data)
if err != nil {
return decoded, n, errorDecf(countHeaderBytes, "%s", err)
}
effectiveExtraIndirs = ti.Indir
}

if ti.Indir > 0 {
Expand Down Expand Up @@ -788,13 +788,22 @@ func decWithNilCheck[E any](data []byte, v interface{}, ti typeInfo, decFn decFu
func fn_DecToWrappedReceiver(wrapped interface{}, ti typeInfo, assertFn func(reflect.Type) bool, decToUnwrappedFn func([]byte, interface{}) (interface{}, int, error)) decFunc[interface{}] {
return func(data []byte) (interface{}, interface{}, int, error) {
// v is *(...*)T, ret-val of decFn (this lambda) is T.
receiverType := reflect.TypeOf(wrapped)
refWrapped := reflect.ValueOf(wrapped)
receiverType := refWrapped.Type()
refUnwrapped := refWrapped

if receiverType.Kind() == reflect.Pointer { // future-proofing - binary unmarshaler might come in as a T
// for every * in the (...*) part of *(...*)T up until the
// implementor/slice-ptr, do a deref.
for i := 0; i < ti.Indir; i++ {
receiverType = receiverType.Elem()
if (ti.Main == mtText || ti.Main == mtBinary) && refUnwrapped.IsValid() {
if !refUnwrapped.IsNil() {
refUnwrapped = refUnwrapped.Elem()
} else {
refUnwrapped = reflect.Value{}
}
}
}
}

Expand All @@ -813,10 +822,25 @@ func fn_DecToWrappedReceiver(wrapped interface{}, ti typeInfo, assertFn func(ref
return nil, nil, 0, errorDecf(0, "function pointer type receiver is not supported").wrap(ErrInvalidType)
}
// receiverType is *T
receiverValue = reflect.New(receiverType.Elem())

// Make shore we are actually using the populated struct for
// interface implementors, in case unmarshaling is dependant on any
// prior-set properties. No need to do this for mtStruct bc that is
// automatic and we have full control; we don't (and can't) rely on
// already set things and use reflect after actual decoding to copy
// the decoded values into the passed-in pointer.
if (ti.Main == mtText || ti.Main == mtBinary) && refUnwrapped.IsValid() && !refUnwrapped.IsNil() {
receiverValue = refUnwrapped
} else {
receiverValue = reflect.New(receiverType.Elem())
}
} else {
// receiverType is itself T (future-proofing)
receiverValue = reflect.Zero(receiverType)
if (ti.Main == mtText || ti.Main == mtBinary) && refUnwrapped.IsValid() {
receiverValue = refUnwrapped
} else {
receiverValue = reflect.Zero(receiverType)
}
}

var decoded interface{}
Expand Down
Loading

0 comments on commit 736720b

Please sign in to comment.