@@ -76,12 +76,14 @@ func setupDefaultFakeServer(opt ...grpc.ServerOption) (tbl *Table, cleanup func(
7676func TestRetryApply (t * testing.T ) {
7777 ctx := context .Background ()
7878
79- errCount := 0
80- code := codes .Unavailable // Will be retried
81- errMsg := ""
79+ var errCount int
80+ var code codes.Code
81+ var errMsg string
82+
8283 // Intercept requests and return an error or defer to the underlying handler
8384 errInjector := func (ctx context.Context , req interface {}, info * grpc.UnaryServerInfo , handler grpc.UnaryHandler ) (interface {}, error ) {
84- if strings .HasSuffix (info .FullMethod , "MutateRow" ) && errCount < 3 {
85+ // The test is designed to fail the first 3 calls to MutateRow or CheckAndMutateRow.
86+ if (strings .HasSuffix (info .FullMethod , "MutateRow" ) || strings .HasSuffix (info .FullMethod , "CheckAndMutateRow" )) && errCount < 3 {
8587 errCount ++
8688 return nil , status .Error (code , errMsg )
8789 }
@@ -95,66 +97,89 @@ func TestRetryApply(t *testing.T) {
9597
9698 mut := NewMutation ()
9799 mut .Set ("cf" , "col" , 1000 , []byte ("val" ))
98- if err := tbl .Apply (ctx , "row1" , mut ); err != nil {
99- t .Errorf ("applying single mutation with retries: %v" , err )
100- }
101- row , err := tbl .ReadRow (ctx , "row1" )
102- if err != nil {
103- t .Errorf ("reading single value with retries: %v" , err )
104- }
105- if row == nil {
106- t .Errorf ("applying single mutation with retries: could not read back row" )
107- }
108100
109- code = codes .FailedPrecondition // Won't be retried
110- errCount = 0
111- if err := tbl .Apply (ctx , "row" , mut ); err == nil {
112- t .Errorf ("applying single mutation with no retries: no error" )
113- }
101+ t .Run ("SimpleRetry" , func (t * testing.T ) {
102+ errCount = 0
103+ code = codes .Unavailable // Will be retried
104+ errMsg = ""
114105
115- // Check and mutate
106+ if err := tbl .Apply (ctx , "row-simple-retry" , mut ); err != nil {
107+ t .Errorf ("applying single mutation with retries: %v" , err )
108+ }
109+ row , err := tbl .ReadRow (ctx , "row-simple-retry" )
110+ if err != nil {
111+ t .Errorf ("reading single value with retries: %v" , err )
112+ }
113+ if row == nil {
114+ t .Errorf ("applying single mutation with retries: could not read back row" )
115+ }
116+ })
117+
118+ t .Run ("NonRetryable" , func (t * testing.T ) {
119+ errCount = 0
120+ code = codes .FailedPrecondition // Won't be retried
121+ errMsg = ""
122+
123+ if err := tbl .Apply (ctx , "row-non-retryable" , mut ); err == nil {
124+ t .Errorf ("applying single mutation with no retries: got nil, want error" )
125+ }
126+ })
127+
128+ // Conditional mutations are idempotent if their true and false mutations are idempotent.
129+ // In this test, mutTrue (DeleteRow) and mutFalse (Set with fixed timestamp) are idempotent.
116130 mutTrue := NewMutation ()
117131 mutTrue .DeleteRow ()
118132 mutFalse := NewMutation ()
119133 mutFalse .Set ("cf" , "col" , 1000 , []byte ("val" ))
120134 condMut := NewCondMutation (ValueFilter (".*" ), mutTrue , mutFalse )
121135
122- errCount = 0
123- code = codes .Unavailable // Won't be retried
124- if err := tbl .Apply (ctx , "row1" , condMut ); err == nil {
125- t .Errorf ("conditionally mutating row with no retries: no error" )
126- }
127-
128- for _ , msg := range retryableInternalErrMsgs {
136+ t .Run ("ConditionalNotRetried" , func (t * testing.T ) {
129137 errCount = 0
130- code = codes .Internal // Will be retried
131- errMsg = msg
132- if err := tbl .Apply (ctx , "row" , mut ); err != nil {
133- t .Errorf ("applying single mutation with retries: %v, errMsg: %v" , err , errMsg )
134- }
135- row , err = tbl .ReadRow (ctx , "row" )
136- if err != nil {
137- t .Errorf ("reading single value with retries: %v, errMsg: %v" , err , errMsg )
138+ code = codes .Unavailable // Won't be retried, as CheckAndMutateRow has no retry policy by default
139+ errMsg = ""
140+
141+ if err := tbl .Apply (ctx , "row-cond-not-retried" , condMut ); err == nil {
142+ t .Errorf ("conditionally mutating row with no retries: got nil, want error" )
138143 }
139- if row == nil {
140- t .Errorf ("applying single mutation with retries: could not read back row. errMsg: %v" , errMsg )
144+ })
145+
146+ t .Run ("RetryableInternal" , func (t * testing.T ) {
147+ for _ , msg := range retryableInternalErrMsgs {
148+ t .Run (msg , func (t * testing.T ) {
149+ errCount = 0
150+ code = codes .Internal // Will be retried
151+ errMsg = msg
152+ if err := tbl .Apply (ctx , "row-retryable-internal" , mut ); err != nil {
153+ t .Errorf ("applying single mutation with retries: %v, errMsg: %v" , err , errMsg )
154+ }
155+ row , err := tbl .ReadRow (ctx , "row-retryable-internal" )
156+ if err != nil {
157+ t .Errorf ("reading single value with retries: %v, errMsg: %v" , err , errMsg )
158+ }
159+ if row == nil {
160+ t .Errorf ("applying single mutation with retries: could not read back row. errMsg: %v" , errMsg )
161+ }
162+ })
141163 }
142- }
164+ })
143165
144- errCount = 0
145- errMsg = ""
146- code = codes .Internal // Won't be retried
147- errMsg = "Placeholder message"
148- if err := tbl .Apply (ctx , "row" , condMut ); err == nil {
149- t .Errorf ("conditionally mutating row with no retries: no error" )
150- }
166+ t .Run ("ConditionalNonRetryableInternal" , func (t * testing.T ) {
167+ errCount = 0
168+ code = codes .Internal // Won't be retried for conditional mutation with non-retryable message
169+ errMsg = "Placeholder message"
170+ if err := tbl .Apply (ctx , "row-cond-non-retryable-internal" , condMut ); err == nil {
171+ t .Errorf ("conditionally mutating row with no retries: got nil, want error" )
172+ }
173+ })
151174
152- errCount = 0
153- errMsg = ""
154- code = codes .FailedPrecondition // Won't be retried
155- if err := tbl .Apply (ctx , "row" , condMut ); err == nil {
156- t .Errorf ("conditionally mutating row with no retries: no error" )
157- }
175+ t .Run ("ConditionalNonRetryableFailedPrecondition" , func (t * testing.T ) {
176+ errCount = 0
177+ code = codes .FailedPrecondition // Won't be retried
178+ errMsg = ""
179+ if err := tbl .Apply (ctx , "row-cond-non-retryable-failed-precondition" , condMut ); err == nil {
180+ t .Errorf ("conditionally mutating row with no retries: got nil, want error" )
181+ }
182+ })
158183}
159184
160185// Test overall request failure and retries.
0 commit comments