Skip to content

Commit

Permalink
Merge pull request #204 from pace/hide-error-types
Browse files Browse the repository at this point in the history
Add error hiding func to only forward explicit and context errors
  • Loading branch information
threez committed Jun 4, 2020
2 parents 5be0ace + efd260e commit 826135b
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 0 deletions.
34 changes: 34 additions & 0 deletions maintenance/errors/context.go
@@ -0,0 +1,34 @@
package errors

import (
"context"
"errors"
"fmt"
"strings"
)

// Hide checks whether the given error err is a context.Canceled or
// context.DeadlineExceeded error and if so exposes these errors as
// wrapped errors while maintaining the given err as string. If
// the optional exposedErr is provided, it is attached as prefix
// to the returned error. If the given err is not any of the above
// ones, the given exposedErr (if present) is wrapped as prefix
// to the returned error.
func Hide(ctx context.Context, err, exposedErr error) error {
ret := errors.New(err.Error())
if exposedErr != nil {
ret = fmt.Errorf("%w: %s", exposedErr, err)
}

if ctx.Err() == context.Canceled && errors.Is(err, context.Canceled) {
s := strings.TrimSuffix(ret.Error(), context.Canceled.Error())
return fmt.Errorf("%s%w", s, context.Canceled)
}

if ctx.Err() == context.DeadlineExceeded && errors.Is(err, context.DeadlineExceeded) {
s := strings.TrimSuffix(ret.Error(), context.DeadlineExceeded.Error())
return fmt.Errorf("%s%w", s, context.DeadlineExceeded)
}

return ret
}
149 changes: 149 additions & 0 deletions maintenance/errors/context_test.go
@@ -0,0 +1,149 @@
package errors

import (
"context"
"errors"
"fmt"
"testing"
"time"

"github.com/stretchr/testify/require"
)

func TestHide(t *testing.T) {
iAmAnError := errors.New("i am an error")
iAmAnotherError := errors.New("i am another error")

backgroundContext := context.Background()
canceledContext, cancel := context.WithCancel(backgroundContext)
cancel()

exceededContext, _ := context.WithTimeout(backgroundContext, time.Millisecond)
time.Sleep(2 * time.Millisecond)

type args struct {
ctx context.Context
err error
exposedErr error
}
tests := []struct {
name string
args args
want error
}{
{
name: "normal_context_no_error_nothing_exposed",
args: args{
ctx: backgroundContext,
err: iAmAnError,
exposedErr: nil,
},
want: iAmAnError,
},
{
name: "normal_context_no_error_with_exposed",
args: args{
ctx: backgroundContext,
err: iAmAnError,
exposedErr: iAmAnotherError,
},
want: fmt.Errorf("%w: %s", iAmAnotherError, iAmAnError),
},
{
name: "normal_context_with_error_nothing_exposed",
args: args{
ctx: backgroundContext,
err: fmt.Errorf("%s: %w", iAmAnError, context.Canceled),
exposedErr: nil,
},
want: fmt.Errorf("%s: %s", iAmAnError, context.Canceled),
},
{
name: "normal_context_with_error_with_exposed",
args: args{
ctx: backgroundContext,
err: fmt.Errorf("%s: %w", iAmAnError, context.Canceled),
exposedErr: iAmAnotherError,
},
want: fmt.Errorf("%w: %s: %s", iAmAnotherError, iAmAnError, context.Canceled),
},
{
name: "canceled_context_no_error_nothing_exposed",
args: args{
ctx: canceledContext,
err: iAmAnError,
exposedErr: nil,
},
want: iAmAnError,
},
{
name: "canceled_context_no_error_with_exposed",
args: args{
ctx: canceledContext,
err: iAmAnError,
exposedErr: iAmAnotherError,
},
want: fmt.Errorf("%w: %s", iAmAnotherError, iAmAnError),
},
{
name: "canceled_context_with_error_nothing_exposed",
args: args{
ctx: canceledContext,
err: fmt.Errorf("%s: %w", iAmAnError, context.Canceled),
exposedErr: nil,
},
want: fmt.Errorf("%s: %w", iAmAnError, context.Canceled),
},
{
name: "canceled_context_with_error_with_exposed",
args: args{
ctx: canceledContext,
err: fmt.Errorf("%s: %w", iAmAnError, context.Canceled),
exposedErr: iAmAnotherError,
},
want: fmt.Errorf("%s: %s: %w", iAmAnotherError, iAmAnError, context.Canceled),
},
{
name: "exceeded_context_no_error_nothing_exposed",
args: args{
ctx: exceededContext,
err: iAmAnError,
exposedErr: nil,
},
want: iAmAnError,
},
{
name: "exceeded_context_no_error_with_exposed",
args: args{
ctx: exceededContext,
err: iAmAnError,
exposedErr: iAmAnotherError,
},
want: fmt.Errorf("%w: %s", iAmAnotherError, iAmAnError),
},
{
name: "exceeded_context_with_error_nothing_exposed",
args: args{
ctx: exceededContext,
err: fmt.Errorf("%s: %w", iAmAnError, context.DeadlineExceeded),
exposedErr: nil,
},
want: fmt.Errorf("%s: %w", iAmAnError, context.DeadlineExceeded),
},
{
name: "exceeded_context_with_error_with_exposed",
args: args{
ctx: exceededContext,
err: fmt.Errorf("%s: %w", iAmAnError, context.DeadlineExceeded),
exposedErr: iAmAnotherError,
},
want: fmt.Errorf("%s: %s: %w", iAmAnotherError, iAmAnError, context.DeadlineExceeded),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Hide(tt.args.ctx, tt.args.err, tt.args.exposedErr)
require.Equal(t, tt.want, got)
})
}
}

0 comments on commit 826135b

Please sign in to comment.