Skip to content

Commit

Permalink
Make encoder/decoder underlying errors unwrappable (stellar#15)
Browse files Browse the repository at this point in the history
Add `Unwrap` methods to the `MarshalError` and `UnmarshalError` types that return the underlying IO errors if present.

The `MarshalError` and `UnmarshalError` error types wrap IO and other errors. Since Go 1.13 if an error provides an `Unwrap` function that returns the underlying error, the `errors` stdlib package can be used to test if the error or any of its underlying errors are an error. This is helpful for testing for general underlying IO errors in code the uses the encoder/decoder as a reader.
  • Loading branch information
leighmcculloch authored Oct 4, 2021
1 parent f80a23d commit b95df30
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
10 changes: 10 additions & 0 deletions xdr3/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ type UnmarshalError struct {
Err error // The underlying error for IO errors
}

// Unwrap returns the underlying error if there is one.
func (e *UnmarshalError) Unwrap() error {
return e.Err
}

// Error satisfies the error interface and prints human-readable errors.
func (e *UnmarshalError) Error() string {
switch e.ErrorCode {
Expand Down Expand Up @@ -145,6 +150,11 @@ type MarshalError struct {
Err error // The underlying error for IO errors
}

// Unwrap returns the underlying error if there is one.
func (e *MarshalError) Unwrap() error {
return e.Err
}

// Error satisfies the error interface and prints human-readable errors.
func (e *MarshalError) Error() string {
switch e.ErrorCode {
Expand Down
30 changes: 30 additions & 0 deletions xdr3/error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package xdr_test

import (
"errors"
"io"
"testing"

. "github.com/stellar/go-xdr/xdr3"
Expand Down Expand Up @@ -64,6 +66,16 @@ func TestUnmarshalError(t *testing.T) {
},
"xdr:test: EOF while decoding 5 bytes - read: 'testval'",
},
{
UnmarshalError{
ErrorCode: ErrIO,
Func: "test",
Description: "underlying io error",
Value: "testval",
Err: io.ErrShortBuffer,
},
"xdr:test: underlying io error - read: 'testval'",
},
{
UnmarshalError{
ErrorCode: ErrBadEnumValue,
Expand Down Expand Up @@ -91,6 +103,10 @@ func TestUnmarshalError(t *testing.T) {
test.want)
continue
}
if test.in.Err != nil && !errors.Is(&test.in, test.in.Err) {
t.Errorf("Error #%d\n is not is-able on underlying error", i)
continue
}
}
}

Expand All @@ -109,6 +125,16 @@ func TestMarshalError(t *testing.T) {
},
"xdr:test: EOF while encoding 5 bytes - wrote: '[1 2]'",
},
{
MarshalError{
ErrorCode: ErrIO,
Func: "test",
Description: "underlying io error",
Value: []byte{0x01, 0x02},
Err: io.ErrShortWrite,
},
"xdr:test: underlying io error - wrote: '[1 2]'",
},
{
MarshalError{
ErrorCode: ErrBadEnumValue,
Expand Down Expand Up @@ -136,5 +162,9 @@ func TestMarshalError(t *testing.T) {
test.want)
continue
}
if test.in.Err != nil && !errors.Is(&test.in, test.in.Err) {
t.Errorf("Error #%d\n is not is-able on underlying error", i)
continue
}
}
}

0 comments on commit b95df30

Please sign in to comment.