github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/xerrors/operation_test.go (about)

     1  package xerrors
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
     9  	"github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Issue"
    10  )
    11  
    12  func TestIsOperationError(t *testing.T) {
    13  	for _, tt := range []struct {
    14  		err   error
    15  		codes []Ydb.StatusIds_StatusCode
    16  		match bool
    17  	}{
    18  		// check only operation error with any ydb status code
    19  		{
    20  			err:   &operationError{code: Ydb.StatusIds_BAD_REQUEST},
    21  			match: true,
    22  		},
    23  		{
    24  			err:   fmt.Errorf("wrapped: %w", &operationError{code: Ydb.StatusIds_BAD_REQUEST}),
    25  			match: true,
    26  		},
    27  		{
    28  			err: Join(
    29  				fmt.Errorf("test"),
    30  				&operationError{code: Ydb.StatusIds_BAD_REQUEST},
    31  				Retryable(fmt.Errorf("test")),
    32  			),
    33  			match: true,
    34  		},
    35  		// match ydb status code
    36  		{
    37  			err:   &operationError{code: Ydb.StatusIds_BAD_REQUEST},
    38  			codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST},
    39  			match: true,
    40  		},
    41  		{
    42  			err:   fmt.Errorf("wrapped: %w", &operationError{code: Ydb.StatusIds_BAD_REQUEST}),
    43  			codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST},
    44  			match: true,
    45  		},
    46  		{
    47  			err: Join(
    48  				fmt.Errorf("test"),
    49  				&operationError{code: Ydb.StatusIds_BAD_REQUEST},
    50  				Retryable(fmt.Errorf("test")),
    51  			),
    52  			codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_BAD_REQUEST},
    53  			match: true,
    54  		},
    55  		// no match ydb status code
    56  		{
    57  			err:   &operationError{code: Ydb.StatusIds_BAD_REQUEST},
    58  			codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED},
    59  			match: false,
    60  		},
    61  		{
    62  			err:   fmt.Errorf("wrapped: %w", &operationError{code: Ydb.StatusIds_BAD_REQUEST}),
    63  			codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED},
    64  			match: false,
    65  		},
    66  		{
    67  			err: Join(
    68  				fmt.Errorf("test"),
    69  				&operationError{code: Ydb.StatusIds_BAD_REQUEST},
    70  				Retryable(fmt.Errorf("test")),
    71  			),
    72  			codes: []Ydb.StatusIds_StatusCode{Ydb.StatusIds_ABORTED},
    73  			match: false,
    74  		},
    75  	} {
    76  		t.Run("", func(t *testing.T) {
    77  			require.Equal(t, tt.match, IsOperationError(tt.err, tt.codes...))
    78  		})
    79  	}
    80  }
    81  
    82  func TestIsOperationErrorTransactionLocksInvalidated(t *testing.T) {
    83  	for _, tt := range [...]struct {
    84  		err   error
    85  		isTLI bool
    86  	}{
    87  		{
    88  			err: Operation(
    89  				WithStatusCode(Ydb.StatusIds_ABORTED),
    90  				WithIssues([]*Ydb_Issue.IssueMessage{{
    91  					IssueCode: issueCodeTransactionLocksInvalidated,
    92  				}}),
    93  			),
    94  			isTLI: true,
    95  		},
    96  		{
    97  			err: Operation(
    98  				WithStatusCode(Ydb.StatusIds_OVERLOADED),
    99  				WithIssues([]*Ydb_Issue.IssueMessage{{
   100  					IssueCode: issueCodeTransactionLocksInvalidated,
   101  				}}),
   102  			),
   103  			isTLI: false,
   104  		},
   105  		{
   106  			err: Operation(
   107  				WithStatusCode(Ydb.StatusIds_ABORTED),
   108  			),
   109  			isTLI: false,
   110  		},
   111  		{
   112  			err: Operation(
   113  				WithStatusCode(Ydb.StatusIds_ABORTED),
   114  				WithIssues([]*Ydb_Issue.IssueMessage{{
   115  					Issues: []*Ydb_Issue.IssueMessage{{
   116  						IssueCode: issueCodeTransactionLocksInvalidated,
   117  					}},
   118  				}}),
   119  			),
   120  			isTLI: true,
   121  		},
   122  	} {
   123  		t.Run("", func(t *testing.T) {
   124  			require.Equal(t, tt.isTLI, IsOperationErrorTransactionLocksInvalidated(tt.err))
   125  		})
   126  	}
   127  }
   128  
   129  func Test_operationError_Error(t *testing.T) {
   130  	for _, tt := range []struct {
   131  		err  error
   132  		text string
   133  	}{
   134  		{
   135  			err:  Operation(WithStatusCode(Ydb.StatusIds_BAD_REQUEST), WithAddress("localhost")),
   136  			text: "operation/BAD_REQUEST (code = 400010, address = localhost)",
   137  		},
   138  		{
   139  			err:  Operation(WithStatusCode(Ydb.StatusIds_BAD_REQUEST)),
   140  			text: "operation/BAD_REQUEST (code = 400010)",
   141  		},
   142  		{
   143  			err:  Operation(WithStatusCode(Ydb.StatusIds_BAD_SESSION)),
   144  			text: "operation/BAD_SESSION (code = 400100)",
   145  		},
   146  		{
   147  			err: Operation(WithStatusCode(Ydb.StatusIds_PRECONDITION_FAILED), WithIssues([]*Ydb_Issue.IssueMessage{
   148  				{
   149  					Message:   "issue one",
   150  					IssueCode: 1,
   151  					Position: &Ydb_Issue.IssueMessage_Position{
   152  						Row:    15,
   153  						Column: 3,
   154  						File:   "",
   155  					},
   156  				},
   157  				{
   158  					Message:   "issue two",
   159  					IssueCode: 2,
   160  					Issues: []*Ydb_Issue.IssueMessage{
   161  						{
   162  							Message:   "issue three",
   163  							IssueCode: 3,
   164  							Position: &Ydb_Issue.IssueMessage_Position{
   165  								Row:    16,
   166  								Column: 4,
   167  								File:   "test.yql",
   168  							},
   169  						},
   170  						{
   171  							Message:   "issue four",
   172  							IssueCode: 4,
   173  						},
   174  					},
   175  				},
   176  			})),
   177  			text: "operation/PRECONDITION_FAILED (code = 400120, issues = [{15:3 => #1 'issue one'},{#2 'issue two' [{test.yql:16:4 => #3 'issue three'},{#4 'issue four'}]}])", //nolint:lll
   178  		},
   179  	} {
   180  		t.Run("", func(t *testing.T) {
   181  			require.Equal(t, tt.text, tt.err.Error())
   182  		})
   183  	}
   184  }