-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcache_test.go
135 lines (117 loc) · 3.08 KB
/
cache_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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
import (
"bytes"
"errors"
"io/ioutil"
"net/http"
"net/http/httputil"
"testing"
"time"
)
type constCache struct {
resp []byte
}
func (cc *constCache) Get (k string) (*Item, error) {
return &Item{Key: k, Value: cc.resp}, nil
}
func (cc *constCache) Set (*Item) error {
return nil
}
type constTransport struct {
respBody string
}
func (ct *constTransport) RoundTrip (r *http.Request) (*http.Response, error) {
return &http.Response{
Status: "200 OK",
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString(ct.respBody)),
}, nil
}
// cacheTransport returns cached results if available
func TestCacheTransportCachedResponse(t *testing.T) {
// set up
cachedResp := &http.Response{
Status: "200 OK",
StatusCode: 200,
Body: ioutil.NopCloser(bytes.NewBufferString(
"test cached body")),
}
dump, err := httputil.DumpResponse(cachedResp, true)
if err != nil {
t.Errorf("could not dump response:", err)
}
testTransport := &cacheTransport{
wrappedTransport: &constTransport{"test upstream body"},
cacheKey: func (r *http.Request) (string, error) {
return "test key", nil
},
cache: &constCache{dump},
}
// run SUT
resp, err := testTransport.RoundTrip(&http.Request{})
// confirm assumptions
if err != nil {
t.Errorf("test transport error:", err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Errorf("could not read body:", err)
}
if string(body) != "test cached body" {
t.Errorf("expected cached response, got", string(body))
}
}
type emptyCache struct {
latestItem *Item
}
func (ec *emptyCache) Get (k string) (*Item, error) {
return nil, errors.New("empty cache has no items")
}
func (ec *emptyCache) Set (i *Item) error {
ec.latestItem = i
return nil
}
// cacheTransport returns upstream result if no cache is available
func TestCacheTransportFreshResponse(t *testing.T) {
// set up
mockCache := &emptyCache{}
mockTransport := &constTransport{"test upstream body"}
testTransport := &cacheTransport{
wrappedTransport: mockTransport,
cacheKey: func (r *http.Request) (string, error) {
return "test key", nil
},
cache: mockCache,
}
// run SUT
resp, err := testTransport.RoundTrip(&http.Request{})
// confirm assumptions
if err != nil {
t.Errorf("test transport error:", err)
}
// response is the upstream response (from the wrapped transport)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Errorf("could not read body:", err)
}
if string(body) != "test upstream body" {
t.Errorf("expected cached response, got", string(body))
}
// the cache was set to the correct item
response, err := mockTransport.RoundTrip(&http.Request{})
if err != nil {
t.Errorf("mock transport RoundTrip error", err)
}
expectedValue, err := httputil.DumpResponse(response, true)
if err != nil {
t.Errorf("could not dump response:", err)
}
// cache is set async so we should wait some reasonable time for it.
time.Sleep(1 * time.Millisecond)
if !bytes.Equal(mockCache.latestItem.Value, expectedValue) {
t.Errorf("\nexpected %v\nset to %v",
string(expectedValue),
string(mockCache.latestItem.Value),
)
}
}