forked from asecurityteam/transport
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhedger_test.go
117 lines (107 loc) · 2.83 KB
/
hedger_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package transport
import (
"bytes"
"context"
"io/ioutil"
"net/http"
"sync"
"testing"
"time"
)
type hedgerFixtureRoundTripper struct {
Response *http.Response
Err error
Sleep time.Duration
Counter int
l sync.RWMutex
}
func (c *hedgerFixtureRoundTripper) RoundTrip(*http.Request) (*http.Response, error) {
c.incrCounter()
time.Sleep(c.Sleep)
return c.Response, c.Err
}
func (c *hedgerFixtureRoundTripper) incrCounter() {
c.l.Lock()
defer c.l.Unlock()
c.Counter = c.Counter + 1
}
func (c *hedgerFixtureRoundTripper) Count() int {
c.l.Lock()
defer c.l.Unlock()
return c.Counter
}
func TestHedger(t *testing.T) {
t.Parallel()
var successResponse = &http.Response{
Status: "200 OK",
StatusCode: 200,
Header: http.Header{},
}
var testCases = []struct {
name string
roundTripper *hedgerFixtureRoundTripper
expectedResp *http.Response
err error
backoffTime time.Duration
contextTimeout time.Duration
called int
}{
{
name: "Single successful call",
roundTripper: &hedgerFixtureRoundTripper{
Response: successResponse,
Err: nil,
Sleep: 0},
expectedResp: successResponse,
err: nil,
backoffTime: 5 * time.Millisecond,
contextTimeout: 3 * time.Millisecond,
called: 1,
},
{
name: "Single failed call due to context timeout",
roundTripper: &hedgerFixtureRoundTripper{
Response: successResponse,
Err: nil,
Sleep: 4 * time.Millisecond},
expectedResp: nil,
err: context.DeadlineExceeded,
backoffTime: 5 * time.Millisecond,
contextTimeout: 3 * time.Millisecond,
called: 1,
},
{
name: "Three calls",
roundTripper: &hedgerFixtureRoundTripper{
Response: successResponse,
Err: nil,
Sleep: 9 * time.Millisecond},
expectedResp: successResponse,
err: nil,
backoffTime: 5 * time.Millisecond,
contextTimeout: 12 * time.Millisecond,
called: 2,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
var transport = tc.roundTripper
var backoffTime = tc.backoffTime
var decorator = NewHedger(NewFixedBackoffPolicy(backoffTime))
var client = &http.Client{
Transport: decorator(transport),
}
var req, _ = http.NewRequest("GET", "/", ioutil.NopCloser(bytes.NewReader([]byte(``))))
var timeoutCtx, cancel = context.WithTimeout(context.Background(), tc.contextTimeout)
defer cancel()
req = req.WithContext(timeoutCtx)
var resp, er = client.Transport.RoundTrip(req)
if resp != tc.expectedResp || er != tc.err {
t.Fatalf("Got resp %v and err %v, expected resp %v and err %v", resp, er, tc.expectedResp, tc.err)
}
if transport.Count() != tc.called {
t.Fatalf("Called decorator %d times, expected %d", transport.Count(), tc.called)
}
})
}
}