github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/common/rpc/errors_test.go (about) 1 package rpc 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 8 "github.com/hashicorp/go-multierror" 9 "github.com/stretchr/testify/assert" 10 "google.golang.org/grpc/codes" 11 "google.golang.org/grpc/status" 12 13 "github.com/onflow/flow-go/storage" 14 ) 15 16 func TestConvertError(t *testing.T) { 17 defaultCode := codes.Internal 18 t.Run("no error", func(t *testing.T) { 19 err := ConvertError(nil, "", defaultCode) 20 assert.NoError(t, err) 21 }) 22 23 t.Run("preset status code", func(t *testing.T) { 24 err := ConvertError(status.Error(codes.Unavailable, "Unavailable"), "", defaultCode) 25 assert.Equal(t, codes.Unavailable, status.Code(err)) 26 27 err = ConvertError(status.Error(codes.OutOfRange, "OutOfRange"), "", defaultCode) 28 assert.Equal(t, codes.OutOfRange, status.Code(err)) 29 30 err = ConvertError(status.Error(codes.Internal, "Internal"), "", defaultCode) 31 assert.Equal(t, codes.Internal, status.Code(err)) 32 }) 33 34 t.Run("multierror", func(t *testing.T) { 35 var errors *multierror.Error 36 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 37 errors = multierror.Append(errors, fmt.Errorf("not a grpc status code")) 38 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 39 40 err := ConvertError(errors, "some prefix", defaultCode) 41 assert.Equal(t, defaultCode, status.Code(err)) 42 assert.ErrorContains(t, err, "some prefix: ") 43 }) 44 45 t.Run("derived code", func(t *testing.T) { 46 err := ConvertError(context.Canceled, "", defaultCode) 47 assert.Equal(t, codes.Canceled, status.Code(err)) 48 49 err = ConvertError(context.DeadlineExceeded, "some prefix", defaultCode) 50 assert.Equal(t, codes.DeadlineExceeded, status.Code(err)) 51 assert.ErrorContains(t, err, "some prefix: ") 52 }) 53 54 t.Run("unhandled code", func(t *testing.T) { 55 err := ConvertError(storage.ErrNotFound, "", defaultCode) 56 assert.Equal(t, codes.Internal, status.Code(err)) 57 58 err = ConvertError(status.Error(codes.Unknown, "Unknown"), "", defaultCode) 59 assert.Equal(t, codes.Internal, status.Code(err)) 60 61 err = ConvertError(status.Error(codes.Internal, "Internal"), "", defaultCode) 62 assert.Equal(t, codes.Internal, status.Code(err)) 63 64 err = ConvertError(fmt.Errorf("unhandled error"), "", defaultCode) 65 assert.Equal(t, codes.Internal, status.Code(err)) 66 67 err = ConvertError(fmt.Errorf("unhandled error"), "some prefix", defaultCode) 68 assert.Equal(t, defaultCode, status.Code(err)) 69 assert.ErrorContains(t, err, "some prefix: ") 70 }) 71 } 72 73 func TestConvertMultiError(t *testing.T) { 74 defaultCode := codes.Internal 75 t.Run("single error", func(t *testing.T) { 76 var errors *multierror.Error 77 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 78 79 err := ConvertMultiError(errors, "", defaultCode) 80 assert.Equal(t, codes.NotFound, status.Code(err)) 81 }) 82 83 t.Run("same code", func(t *testing.T) { 84 var errors *multierror.Error 85 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 86 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 87 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 88 89 err := ConvertMultiError(errors, "", defaultCode) 90 assert.Equal(t, codes.NotFound, status.Code(err)) 91 }) 92 93 t.Run("same codes - unavailable ignored", func(t *testing.T) { 94 var errors *multierror.Error 95 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 96 errors = multierror.Append(errors, status.Error(codes.Unavailable, "unavailable")) 97 errors = multierror.Append(errors, status.Error(codes.Unavailable, "unavailable")) 98 99 err := ConvertMultiError(errors, "", defaultCode) 100 assert.Equal(t, codes.NotFound, status.Code(err)) 101 }) 102 103 t.Run("same codes - deadline exceeded ignored", func(t *testing.T) { 104 var errors *multierror.Error 105 errors = multierror.Append(errors, status.Error(codes.DeadlineExceeded, "deadline exceeded")) 106 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 107 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 108 109 err := ConvertMultiError(errors, "", defaultCode) 110 assert.Equal(t, codes.NotFound, status.Code(err)) 111 }) 112 113 t.Run("all different codes", func(t *testing.T) { 114 var errors *multierror.Error 115 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 116 errors = multierror.Append(errors, status.Error(codes.Internal, "internal")) 117 errors = multierror.Append(errors, status.Error(codes.InvalidArgument, "invalid arg")) 118 119 err := ConvertMultiError(errors, "", defaultCode) 120 assert.Equal(t, defaultCode, status.Code(err)) 121 }) 122 123 t.Run("non-grpc errors", func(t *testing.T) { 124 var errors *multierror.Error 125 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 126 errors = multierror.Append(errors, fmt.Errorf("not a grpc status code")) 127 errors = multierror.Append(errors, status.Error(codes.NotFound, "not found")) 128 129 err := ConvertMultiError(errors, "some prefix", defaultCode) 130 assert.Equal(t, defaultCode, status.Code(err)) 131 assert.ErrorContains(t, err, "some prefix: ") 132 }) 133 }