github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/xerrors/transport_test.go (about) 1 package xerrors 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 grpcCodes "google.golang.org/grpc/codes" 9 grpcStatus "google.golang.org/grpc/status" 10 11 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest" 12 ) 13 14 func TestIsTransportError(t *testing.T) { 15 for _, tt := range []struct { 16 name string 17 err error 18 codes []grpcCodes.Code 19 match bool 20 }{ 21 // check only transport error with any grpc status code 22 { 23 name: xtest.CurrentFileLine(), 24 err: grpcStatus.Error(grpcCodes.Canceled, ""), 25 match: true, 26 }, 27 { 28 name: xtest.CurrentFileLine(), 29 err: &transportError{status: grpcStatus.New(grpcCodes.Canceled, "")}, 30 match: true, 31 }, 32 { 33 name: xtest.CurrentFileLine(), 34 err: fmt.Errorf("wrapped: %w", &transportError{status: grpcStatus.New(grpcCodes.Canceled, "")}), 35 match: true, 36 }, 37 { 38 name: xtest.CurrentFileLine(), 39 err: fmt.Errorf("wrapped: %w", grpcStatus.Error(grpcCodes.Canceled, "")), 40 match: true, 41 }, 42 { 43 name: xtest.CurrentFileLine(), 44 err: Join( 45 fmt.Errorf("test"), 46 grpcStatus.Error(grpcCodes.Canceled, ""), 47 Retryable(fmt.Errorf("test")), 48 ), 49 match: true, 50 }, 51 // match grpc status code 52 { 53 name: xtest.CurrentFileLine(), 54 err: grpcStatus.Error(grpcCodes.Canceled, ""), 55 codes: []grpcCodes.Code{grpcCodes.Canceled}, 56 match: true, 57 }, 58 { 59 name: xtest.CurrentFileLine(), 60 err: &transportError{status: grpcStatus.New(grpcCodes.Canceled, "")}, 61 codes: []grpcCodes.Code{grpcCodes.Canceled}, 62 match: true, 63 }, 64 { 65 name: xtest.CurrentFileLine(), 66 err: fmt.Errorf("wrapped: %w", &transportError{status: grpcStatus.New(grpcCodes.Canceled, "")}), 67 codes: []grpcCodes.Code{grpcCodes.Canceled}, 68 match: true, 69 }, 70 { 71 name: xtest.CurrentFileLine(), 72 err: fmt.Errorf("wrapped: %w", grpcStatus.Error(grpcCodes.Canceled, "")), 73 codes: []grpcCodes.Code{grpcCodes.Canceled}, 74 match: true, 75 }, 76 { 77 name: xtest.CurrentFileLine(), 78 err: Join( 79 fmt.Errorf("test"), 80 grpcStatus.Error(grpcCodes.Canceled, ""), 81 Retryable(fmt.Errorf("test")), 82 ), 83 codes: []grpcCodes.Code{grpcCodes.Canceled}, 84 match: true, 85 }, 86 // no match grpc status code 87 { 88 name: xtest.CurrentFileLine(), 89 err: grpcStatus.Error(grpcCodes.Canceled, ""), 90 codes: []grpcCodes.Code{grpcCodes.Aborted}, 91 match: false, 92 }, 93 { 94 name: xtest.CurrentFileLine(), 95 err: &transportError{status: grpcStatus.New(grpcCodes.Canceled, "")}, 96 codes: []grpcCodes.Code{grpcCodes.Aborted}, 97 match: false, 98 }, 99 { 100 name: xtest.CurrentFileLine(), 101 err: fmt.Errorf("wrapped: %w", &transportError{status: grpcStatus.New(grpcCodes.Canceled, "")}), 102 codes: []grpcCodes.Code{grpcCodes.Aborted}, 103 match: false, 104 }, 105 { 106 name: xtest.CurrentFileLine(), 107 err: fmt.Errorf("wrapped: %w", grpcStatus.Error(grpcCodes.Canceled, "")), 108 codes: []grpcCodes.Code{grpcCodes.Aborted}, 109 match: false, 110 }, 111 { 112 name: xtest.CurrentFileLine(), 113 err: Join( 114 fmt.Errorf("test"), 115 grpcStatus.Error(grpcCodes.Canceled, ""), 116 Retryable(fmt.Errorf("test")), 117 ), 118 codes: []grpcCodes.Code{grpcCodes.Aborted}, 119 match: false, 120 }, 121 } { 122 t.Run(tt.name, func(t *testing.T) { 123 require.Equal(t, tt.match, IsTransportError(tt.err, tt.codes...)) 124 }) 125 } 126 } 127 128 func TestGrpcError(t *testing.T) { 129 for _, err := range []error{ 130 WithStackTrace(grpcStatus.Error(grpcCodes.Aborted, "")), 131 WithStackTrace(WithStackTrace(grpcStatus.Error(grpcCodes.Aborted, ""))), 132 WithStackTrace(WithStackTrace(WithStackTrace(grpcStatus.Error(grpcCodes.Aborted, "")))), 133 WithStackTrace(Transport(grpcStatus.Error(grpcCodes.Aborted, ""))), 134 WithStackTrace(Transport(WithStackTrace(grpcStatus.Error(grpcCodes.Aborted, "")))), 135 WithStackTrace(Transport(WithStackTrace(WithStackTrace(grpcStatus.Error(grpcCodes.Aborted, ""))))), 136 } { 137 t.Run(err.Error(), func(t *testing.T) { 138 require.True(t, IsTransportError(err)) 139 s, has := grpcStatus.FromError(err) 140 require.True(t, has) 141 require.NotNil(t, s) 142 }) 143 } 144 } 145 146 func Test_transportError_Error(t *testing.T) { 147 for _, tt := range []struct { 148 err error 149 text string 150 }{ 151 { 152 err: Transport(grpcStatus.Error(grpcCodes.FailedPrecondition, "")), 153 text: "transport/FailedPrecondition (code = 9, source error = \"rpc error: code = FailedPrecondition desc = \")", 154 }, 155 { 156 err: Transport(grpcStatus.Error(grpcCodes.Unavailable, ""), WithAddress("localhost:2135")), 157 text: "transport/Unavailable (code = 14, source error = \"rpc error: code = Unavailable desc = \", address: \"localhost:2135\")", //nolint:lll 158 }, 159 } { 160 t.Run("", func(t *testing.T) { 161 require.Equal(t, tt.text, tt.err.Error()) 162 }) 163 } 164 } 165 166 func TestTransportErrorName(t *testing.T) { 167 for _, tt := range []struct { 168 err error 169 name string 170 }{ 171 { 172 err: nil, 173 name: "", 174 }, 175 { 176 err: grpcStatus.Error(grpcCodes.Aborted, ""), 177 name: "transport/Aborted", 178 }, 179 { 180 err: TransportError(grpcStatus.Error(grpcCodes.Aborted, "")), 181 name: "transport/Aborted", 182 }, 183 { 184 err: WithStackTrace(grpcStatus.Error(grpcCodes.Aborted, "")), 185 name: "transport/Aborted", 186 }, 187 { 188 err: WithStackTrace(TransportError(grpcStatus.Error(grpcCodes.Aborted, ""))), 189 name: "transport/Aborted", 190 }, 191 } { 192 t.Run("", func(t *testing.T) { 193 if tt.err == nil { 194 require.Nil(t, TransportError(tt.err)) //nolint:testifylint 195 } else { 196 require.Equal(t, tt.name, TransportError(tt.err).Name()) 197 } 198 }) 199 } 200 }