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  }