Skip to content

Commit

Permalink
allowed to create xerrors.TransportError() from grpc status error + r…
Browse files Browse the repository at this point in the history
…efactoring of xerrors tests
  • Loading branch information
asmyasnikov committed Oct 23, 2023
1 parent 461b0fe commit f71a1c9
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 122 deletions.
79 changes: 65 additions & 14 deletions internal/xerrors/operation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,72 @@ import (
)

func TestIsOperationError(t *testing.T) {
for _, code := range [...]Ydb.StatusIds_StatusCode{
Ydb.StatusIds_BAD_REQUEST,
Ydb.StatusIds_BAD_SESSION,
for _, tt := range []struct {
err error
codes []Ydb.StatusIds_StatusCode
match bool
}{
// check only operation error with any ydb status code
{
err: &operationError{code: Ydb.StatusIds_BAD_REQUEST},
match: true,
},
{
err: fmt.Errorf("wrapped: %w", &operationError{code: Ydb.StatusIds_BAD_REQUEST}),
match: true,
},
{
err: Join(
fmt.Errorf("test"),
&operationError{code: Ydb.StatusIds_BAD_REQUEST},
Retryable(fmt.Errorf("test")),
),
match: true,
},
// match ydb status code
{
err: &operationError{code: Ydb.StatusIds_BAD_REQUEST},
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST},
match: true,
},
{
err: fmt.Errorf("wrapped: %w", &operationError{code: Ydb.StatusIds_BAD_REQUEST}),
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST},
match: true,
},
{
err: Join(
fmt.Errorf("test"),
&operationError{code: Ydb.StatusIds_BAD_REQUEST},
Retryable(fmt.Errorf("test")),
),
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST},
match: true,
},
// no match ydb status code
{
err: &operationError{code: Ydb.StatusIds_BAD_REQUEST},
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED},
match: false,
},
{
err: fmt.Errorf("wrapped: %w", &operationError{code: Ydb.StatusIds_BAD_REQUEST}),
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED},
match: false,
},
{
err: Join(
fmt.Errorf("test"),
&operationError{code: Ydb.StatusIds_BAD_REQUEST},
Retryable(fmt.Errorf("test")),
),
codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED},
match: false,
},
} {
for _, err := range []error{
&operationError{code: code},
Operation(WithStatusCode(code)),
fmt.Errorf("wrapped: %w", &operationError{code: code}),
} {
t.Run("", func(t *testing.T) {
if !IsOperationError(err, code) {
t.Errorf("expected %v to be operationError with code=%v", err, code)
}
})
}
t.Run("", func(t *testing.T) {
require.Equal(t, tt.match, IsOperationError(tt.err, tt.codes...))
})
}
}

Expand Down
106 changes: 106 additions & 0 deletions internal/xerrors/pessimized_error_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package xerrors

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

grpcCodes "google.golang.org/grpc/codes"
grpcStatus "google.golang.org/grpc/status"
)

func TestMustPessimizeEndpoint(t *testing.T) {
for _, test := range []struct {
error error
pessimize bool
}{
{
error: Transport(grpcStatus.Error(grpcCodes.Canceled, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Unknown, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.InvalidArgument, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.DeadlineExceeded, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.NotFound, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.AlreadyExists, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.PermissionDenied, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.ResourceExhausted, "")),
pessimize: false,
},
{
error: Transport(grpcStatus.Error(grpcCodes.FailedPrecondition, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Aborted, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.OutOfRange, "")),
pessimize: false,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Unimplemented, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Internal, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Unavailable, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.DataLoss, "")),
pessimize: true,
},
{
error: Transport(grpcStatus.Error(grpcCodes.Unauthenticated, "")),
pessimize: true,
},
{
error: context.Canceled,
pessimize: false,
},
{
error: context.DeadlineExceeded,
pessimize: false,
},
{
error: fmt.Errorf("user error"),
pessimize: false,
},
} {
err := errors.Unwrap(test.error)
if err == nil {
err = test.error
}
t.Run(err.Error(), func(t *testing.T) {
pessimize := MustPessimizeEndpoint(test.error)
if pessimize != test.pessimize {
t.Errorf("unexpected pessimization status for error `%v`: %t, exp: %t", test.error, pessimize, test.pessimize)
}
})
}
}
21 changes: 17 additions & 4 deletions internal/xerrors/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,23 @@ func IsTransportError(err error, codes ...grpcCodes.Code) bool {
if err == nil {
return false
}
var status *grpcStatus.Status
if t := (*transportError)(nil); errors.As(err, &t) {
status = t.status
} else if t, has := grpcStatus.FromError(err); has {
status = t
}
if status != nil {
if len(codes) == 0 {
return true
}
for _, code := range codes {
if t.status.Code() == code {
if status.Code() == code {
return true
}
}
return false
}
_, has := grpcStatus.FromError(err)
return has
return false
}

// Transport returns a new transport error with given options
Expand Down Expand Up @@ -178,9 +182,18 @@ func MustPessimizeEndpoint(err error, codes ...grpcCodes.Code) bool {
}

func TransportError(err error) Error {
if err == nil {
return nil
}
var t *transportError
if errors.As(err, &t) {
return t
}
if s, ok := grpcStatus.FromError(err); ok {
return &transportError{
status: s,
err: err,
}
}
return nil
}
Loading

0 comments on commit f71a1c9

Please sign in to comment.