(t *testing.T)
| 46 | } |
| 47 | |
| 48 | func Test_CAS_Backoff(t *testing.T) { |
| 49 | testCases := []struct { |
| 50 | name string |
| 51 | setupMocks func(*MockDynamodbClient, *CodecMock, *DescMock, map[dynamodbKey]dynamodbItem, []dynamodbKey) |
| 52 | expectedQueryCalls int |
| 53 | expectedBatchCalls int |
| 54 | }{ |
| 55 | { |
| 56 | name: "query_fails_and_backs_off", |
| 57 | setupMocks: func(ddbMock *MockDynamodbClient, codecMock *CodecMock, descMock *DescMock, expectedBatch map[dynamodbKey]dynamodbItem, expectedDelete []dynamodbKey) { |
| 58 | ddbMock.On("Query").Return(map[string]dynamodbItem{}, errors.Errorf("query failed")).Once() |
| 59 | ddbMock.On("Query").Return(map[string]dynamodbItem{}, nil).Once() |
| 60 | ddbMock.On("Batch", context.TODO(), expectedBatch, expectedDelete).Return(false, nil).Once() |
| 61 | }, |
| 62 | expectedQueryCalls: 2, |
| 63 | expectedBatchCalls: 1, |
| 64 | }, |
| 65 | { |
| 66 | name: "batch_fails_and_backs_off", |
| 67 | setupMocks: func(ddbMock *MockDynamodbClient, codecMock *CodecMock, descMock *DescMock, expectedBatch map[dynamodbKey]dynamodbItem, expectedDelete []dynamodbKey) { |
| 68 | ddbMock.On("Query").Return(map[string]dynamodbItem{}, nil).Twice() |
| 69 | ddbMock.On("Batch", context.TODO(), expectedBatch, expectedDelete).Return(true, errors.Errorf("batch failed")).Once() |
| 70 | ddbMock.On("Batch", context.TODO(), expectedBatch, expectedDelete).Return(false, nil).Once() |
| 71 | }, |
| 72 | expectedQueryCalls: 2, |
| 73 | expectedBatchCalls: 2, |
| 74 | }, |
| 75 | } |
| 76 | |
| 77 | for _, tc := range testCases { |
| 78 | t.Run(tc.name, func(t *testing.T) { |
| 79 | ddbMock := NewDynamodbClientMock() |
| 80 | codecMock := &CodecMock{} |
| 81 | descMock := &DescMock{} |
| 82 | c := NewClientMock(ddbMock, codecMock, TestLogger{}, prometheus.NewPedanticRegistry(), defaultPullTime, defaultBackoff) |
| 83 | |
| 84 | expectedBatch := map[dynamodbKey]dynamodbItem{} |
| 85 | expectedDelete := []dynamodbKey{{primaryKey: "test", sortKey: "childkey"}} |
| 86 | |
| 87 | tc.setupMocks(ddbMock, codecMock, descMock, expectedBatch, expectedDelete) |
| 88 | |
| 89 | codecMock.On("DecodeMultiKey").Return(descMock, nil).Times(tc.expectedQueryCalls) |
| 90 | descMock.On("Clone").Return(descMock).Times(tc.expectedQueryCalls) |
| 91 | descMock.On("FindDifference", descMock).Return(descMock, []string{"childkey"}, nil).Times(tc.expectedBatchCalls) |
| 92 | codecMock.On("EncodeMultiKey").Return(map[string][]byte{}, nil).Times(tc.expectedBatchCalls) |
| 93 | |
| 94 | err := c.CAS(context.TODO(), key, func(in any) (out any, retry bool, err error) { |
| 95 | return descMock, true, nil |
| 96 | }) |
| 97 | |
| 98 | require.NoError(t, err) |
| 99 | ddbMock.AssertNumberOfCalls(t, "Query", tc.expectedQueryCalls) |
| 100 | ddbMock.AssertNumberOfCalls(t, "Batch", tc.expectedBatchCalls) |
| 101 | }) |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | func Test_CAS_Failed(t *testing.T) { |
nothing calls this directly
no test coverage detected