| 27 | ) |
| 28 | |
| 29 | func TestHedge(t *testing.T) { |
| 30 | tests := []struct { |
| 31 | name string |
| 32 | returnIn time.Duration |
| 33 | hedgeAt time.Duration |
| 34 | expectedHedgedRequests int32 |
| 35 | }{ |
| 36 | { |
| 37 | name: "hedge disabled", |
| 38 | expectedHedgedRequests: 1, |
| 39 | }, |
| 40 | { |
| 41 | name: "hedge enabled doesn't hit", |
| 42 | hedgeAt: time.Hour, |
| 43 | expectedHedgedRequests: 1, |
| 44 | }, |
| 45 | { |
| 46 | name: "hedge enabled and hits", |
| 47 | hedgeAt: time.Millisecond, |
| 48 | returnIn: 100 * time.Millisecond, |
| 49 | expectedHedgedRequests: 2, |
| 50 | }, |
| 51 | } |
| 52 | |
| 53 | for _, tc := range tests { |
| 54 | t.Run(tc.name, func(t *testing.T) { |
| 55 | count := int32(0) |
| 56 | server := fakeServer(t, tc.returnIn, &count) |
| 57 | |
| 58 | r, w, _, err := New(&Config{ |
| 59 | BucketName: "blerg", |
| 60 | Insecure: true, |
| 61 | Endpoint: server.URL, |
| 62 | HedgeRequestsAt: tc.hedgeAt, |
| 63 | HedgeRequestsUpTo: 2, |
| 64 | }) |
| 65 | require.NoError(t, err) |
| 66 | |
| 67 | ctx := context.Background() |
| 68 | |
| 69 | // the first call on each client initiates an extra http request |
| 70 | // clearing that here |
| 71 | _, _, _ = r.Read(ctx, "object", []string{"test"}, nil) |
| 72 | time.Sleep(tc.returnIn) |
| 73 | atomic.StoreInt32(&count, 0) |
| 74 | |
| 75 | // calls that should hedge |
| 76 | _, _, _ = r.Read(ctx, "object", []string{"test"}, nil) |
| 77 | time.Sleep(tc.returnIn) |
| 78 | assert.Equal(t, tc.expectedHedgedRequests, atomic.LoadInt32(&count)) |
| 79 | atomic.StoreInt32(&count, 0) |
| 80 | |
| 81 | _ = r.ReadRange(ctx, "object", []string{"test"}, 10, []byte{}, nil) |
| 82 | time.Sleep(tc.returnIn) |
| 83 | assert.Equal(t, tc.expectedHedgedRequests, atomic.LoadInt32(&count)) |
| 84 | atomic.StoreInt32(&count, 0) |
| 85 | |
| 86 | // calls that should not hedge |