github.com/argoproj/argo-cd/v3@v3.2.1/util/grpc/errors_test.go (about) 1 package grpc 2 3 import ( 4 "errors" 5 "fmt" 6 "testing" 7 8 "google.golang.org/grpc/codes" 9 "google.golang.org/grpc/status" 10 apierrors "k8s.io/apimachinery/pkg/api/errors" 11 "k8s.io/apimachinery/pkg/runtime/schema" 12 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func Test_gitErrToGRPC(t *testing.T) { 18 var ok bool 19 require.NoError(t, gitErrToGRPC(nil)) 20 21 defaultErrorMsg := "default error" 22 defaultError := gitErrToGRPC(errors.New(defaultErrorMsg)) 23 _, ok = defaultError.(interface{ GRPCStatus() *status.Status }) 24 assert.False(t, ok) 25 assert.Equal(t, defaultError.Error(), defaultErrorMsg) 26 27 grpcErrorMsg := "grpc error" 28 grpcError := gitErrToGRPC(status.Error(codes.Unknown, grpcErrorMsg)) 29 se, ok := grpcError.(interface{ GRPCStatus() *status.Status }) 30 assert.True(t, ok) 31 assert.Equal(t, codes.Unknown, se.GRPCStatus().Code()) 32 assert.Equal(t, se.GRPCStatus().Message(), grpcErrorMsg) 33 34 notFoundMsg := "repository not found" 35 notFound := gitErrToGRPC(status.Error(codes.NotFound, notFoundMsg)) 36 se1, ok := notFound.(interface{ GRPCStatus() *status.Status }) 37 assert.True(t, ok) 38 assert.Equal(t, codes.NotFound, se1.GRPCStatus().Code()) 39 assert.Equal(t, se1.GRPCStatus().Message(), notFoundMsg) 40 } 41 42 func Test_kubeErrToGRPC(t *testing.T) { 43 type testCase struct { 44 name string 45 givenErrFn func() error 46 expectedErrFn func() error 47 expectedGRPCStatus *status.Status 48 } 49 newForbiddenError := func() error { 50 gr := schema.GroupResource{ 51 Group: "apps", 52 Resource: "Deployment", 53 } 54 return apierrors.NewForbidden(gr, "some-app", errors.New("authentication error")) 55 } 56 newUnauthorizedError := func() error { 57 return apierrors.NewUnauthorized("unauthenticated") 58 } 59 cases := []*testCase{ 60 { 61 name: "will return standard error if not grpc status", 62 givenErrFn: func() error { 63 return errors.New("standard error") 64 }, 65 expectedErrFn: func() error { 66 return errors.New("standard error") 67 }, 68 expectedGRPCStatus: nil, 69 }, 70 { 71 name: "will return wrapped status if nested in err", 72 givenErrFn: func() error { 73 grpcStatus := status.New(codes.NotFound, "Not found") 74 return fmt.Errorf("wrapped status: %w", grpcStatus.Err()) 75 }, 76 expectedErrFn: func() error { 77 grpcStatus := status.New(codes.NotFound, "Not found") 78 return grpcStatus.Err() 79 }, 80 expectedGRPCStatus: status.New(codes.NotFound, "Not found"), 81 }, 82 { 83 name: "will return permission denied if apierrors.IsForbidden", 84 givenErrFn: func() error { 85 return newForbiddenError() 86 }, 87 expectedErrFn: func() error { 88 err := newForbiddenError() 89 grpcStatus := status.New(codes.PermissionDenied, err.Error()) 90 return grpcStatus.Err() 91 }, 92 expectedGRPCStatus: status.New(codes.PermissionDenied, newForbiddenError().Error()), 93 }, 94 { 95 name: "will return unauthenticated if apierrors.IsUnauthorized", 96 givenErrFn: func() error { 97 return newUnauthorizedError() 98 }, 99 expectedErrFn: func() error { 100 err := newUnauthorizedError() 101 grpcStatus := status.New(codes.Unauthenticated, err.Error()) 102 return grpcStatus.Err() 103 }, 104 expectedGRPCStatus: status.New(codes.Unauthenticated, newUnauthorizedError().Error()), 105 }, 106 { 107 name: "will return Unavailable if apierrors.IsServerTimeout", 108 givenErrFn: func() error { 109 return apierrors.NewServerTimeout(schema.GroupResource{}, "update", 1) 110 }, 111 expectedErrFn: func() error { 112 err := apierrors.NewServerTimeout(schema.GroupResource{}, "update", 1) 113 grpcStatus := status.New(codes.Unavailable, err.Error()) 114 return grpcStatus.Err() 115 }, 116 expectedGRPCStatus: status.New(codes.Unavailable, apierrors.NewServerTimeout(schema.GroupResource{}, "update", 1).Error()), 117 }, 118 { 119 name: "will return Aborted if apierrors.IsConflict", 120 givenErrFn: func() error { 121 return apierrors.NewConflict(schema.GroupResource{}, "foo", errors.New("foo")) 122 }, 123 expectedErrFn: func() error { 124 err := apierrors.NewConflict(schema.GroupResource{}, "foo", errors.New("foo")) 125 grpcStatus := status.New(codes.Aborted, err.Error()) 126 return grpcStatus.Err() 127 }, 128 expectedGRPCStatus: status.New(codes.Aborted, apierrors.NewConflict(schema.GroupResource{}, "foo", errors.New("foo")).Error()), 129 }, 130 { 131 name: "will return ResourceExhausted if apierrors.IsTooManyRequests", 132 givenErrFn: func() error { 133 return apierrors.NewTooManyRequests("foo", 1) 134 }, 135 expectedErrFn: func() error { 136 err := apierrors.NewTooManyRequests("foo", 1) 137 grpcStatus := status.New(codes.ResourceExhausted, err.Error()) 138 return grpcStatus.Err() 139 }, 140 expectedGRPCStatus: status.New(codes.ResourceExhausted, apierrors.NewTooManyRequests("foo", 1).Error()), 141 }, 142 } 143 for _, c := range cases { 144 c := c 145 t.Run(c.name, func(t *testing.T) { 146 // when 147 err := kubeErrToGRPC(c.givenErrFn()) 148 149 // then 150 assert.Equal(t, c.expectedErrFn(), err, "error comparison mismatch") 151 grpcStatus := UnwrapGRPCStatus(err) 152 assert.Equal(t, c.expectedGRPCStatus, grpcStatus, "grpc status mismatch") 153 }) 154 } 155 }