Skip to content

Commit e127d94

Browse files
authored
test(bigtable): refactor TestRetryApply for clarity (googleapis#13052)
Refactors the TestRetryApply test to improve its structure, readability, and robustness. The changes include: - Using t.Run to create distinct sub-tests for different scenarios, such as simple retries, non-retryable errors, and conditional mutations. - Using unique row keys for each sub-test to prevent interference between test cases. - Extending the error injection logic to cover CheckAndMutateRow in addition to MutateRow. Fixes: googleapis#13051
1 parent 2930b5c commit e127d94

File tree

1 file changed

+76
-51
lines changed

1 file changed

+76
-51
lines changed

bigtable/retry_test.go

Lines changed: 76 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,14 @@ func setupDefaultFakeServer(opt ...grpc.ServerOption) (tbl *Table, cleanup func(
7676
func 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

Comments
 (0)