Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(181)

Side by Side Diff: client/internal/lhttp/client_test.go

Issue 1159563002: Move retry and lhttp packages from client/internal to common/. (Closed) Base URL: git@github.com:luci/luci-go@master
Patch Set: move-retry-http Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « client/internal/lhttp/client.go ('k') | client/internal/lhttp/doc.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package lhttp
6
7 import (
8 "bytes"
9 "encoding/json"
10 "errors"
11 "fmt"
12 "io"
13 "io/ioutil"
14 "net/http"
15 "net/http/httptest"
16 "testing"
17 "time"
18
19 "github.com/luci/luci-go/client/internal/retry"
20 "github.com/maruel/ut"
21 )
22
23 func TestNewRequestGET(t *testing.T) {
24 // First call returns HTTP 500, second succeeds.
25 serverCalls := 0
26 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
27 serverCalls++
28 content, err := ioutil.ReadAll(r.Body)
29 ut.ExpectEqual(t, nil, err)
30 ut.ExpectEqual(t, []byte{}, content)
31 if serverCalls == 1 {
32 w.WriteHeader(500)
33 } else {
34 fmt.Fprintf(w, "Hello, client\n")
35 }
36 }))
37 defer ts.Close()
38
39 httpReq, err := http.NewRequest("GET", ts.URL, nil)
40 ut.AssertEqual(t, nil, err)
41
42 clientCalls := 0
43 clientReq, err := NewRequest(http.DefaultClient, httpReq, func(resp *htt p.Response) error {
44 clientCalls++
45 content, err := ioutil.ReadAll(resp.Body)
46 ut.AssertEqual(t, nil, err)
47 ut.AssertEqual(t, "Hello, client\n", string(content))
48 ut.AssertEqual(t, nil, resp.Body.Close())
49 return nil
50 })
51 ut.AssertEqual(t, nil, err)
52
53 ut.AssertEqual(t, nil, fast.Do(clientReq))
54 ut.AssertEqual(t, 200, clientReq.Status())
55 ut.AssertEqual(t, 2, serverCalls)
56 ut.AssertEqual(t, 1, clientCalls)
57 }
58
59 func TestNewRequestPOST(t *testing.T) {
60 // First call returns HTTP 500, second succeeds.
61 serverCalls := 0
62 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
63 serverCalls++
64 content, err := ioutil.ReadAll(r.Body)
65 ut.ExpectEqual(t, nil, err)
66 // The same data is sent twice.
67 ut.ExpectEqual(t, "foo bar", string(content))
68 if serverCalls == 1 {
69 w.WriteHeader(500)
70 } else {
71 fmt.Fprintf(w, "Hello, client\n")
72 }
73 }))
74 defer ts.Close()
75
76 httpReq, err := http.NewRequest("POST", ts.URL, newReader([]byte("foo ba r")))
77 ut.AssertEqual(t, nil, err)
78
79 clientCalls := 0
80 clientReq, err := NewRequest(http.DefaultClient, httpReq, func(resp *htt p.Response) error {
81 clientCalls++
82 content, err := ioutil.ReadAll(resp.Body)
83 ut.AssertEqual(t, nil, err)
84 ut.AssertEqual(t, "Hello, client\n", string(content))
85 ut.AssertEqual(t, nil, resp.Body.Close())
86 return nil
87 })
88 ut.AssertEqual(t, nil, err)
89
90 ut.AssertEqual(t, nil, fast.Do(clientReq))
91 ut.AssertEqual(t, 200, clientReq.Status())
92 ut.AssertEqual(t, 2, serverCalls)
93 ut.AssertEqual(t, 1, clientCalls)
94 }
95
96 func TestNewRequestNotSeeker(t *testing.T) {
97 // bytes.NewReader() doesn't implement io.Seeker.
98 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
99 t.Fail()
100 }))
101 defer ts.Close()
102 httpReq, err := http.NewRequest("POST", ts.URL, bytes.NewReader([]byte(" foo bar")))
103 ut.AssertEqual(t, nil, err)
104
105 clientReq, err := NewRequest(http.DefaultClient, httpReq, func(resp *htt p.Response) error {
106 t.Fail()
107 return nil
108 })
109
110 ut.AssertEqual(t, nil, clientReq)
111 ut.AssertEqual(t, errors.New("req.Body must implement io.Seeker"), err)
112 }
113
114 func TestNewRequestBadURL(t *testing.T) {
115 httpReq, err := http.NewRequest("GET", "invalid url", nil)
116 ut.AssertEqual(t, nil, err)
117
118 clientReq, err := NewRequest(http.DefaultClient, httpReq, func(resp *htt p.Response) error {
119 t.Fail()
120 return nil
121 })
122 ut.AssertEqual(t, errors.New("unsupported protocol scheme \"\""), err)
123 ut.AssertEqual(t, nil, clientReq)
124 }
125
126 func TestNewRequestGETFail(t *testing.T) {
127 serverCalls := 0
128 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
129 serverCalls++
130 w.WriteHeader(500)
131 }))
132 defer ts.Close()
133
134 httpReq, err := http.NewRequest("GET", ts.URL, nil)
135 ut.AssertEqual(t, nil, err)
136
137 clientReq, err := NewRequest(http.DefaultClient, httpReq, func(resp *htt p.Response) error {
138 t.Fail()
139 return nil
140 })
141
142 ut.AssertEqual(t, retry.Error{errors.New("http request failed: Internal Server Error (HTTP 500)")}, fast.Do(clientReq))
143 ut.AssertEqual(t, 500, clientReq.Status())
144 ut.AssertEqual(t, fast.MaxTries, serverCalls)
145 }
146
147 func TestNewRequestJSONBadURL(t *testing.T) {
148 clientReq, err := NewRequestJSON(http.DefaultClient, "GET", "invalid url ", nil, nil)
149 ut.AssertEqual(t, errors.New("unsupported protocol scheme \"\""), err)
150 ut.AssertEqual(t, nil, clientReq)
151 }
152
153 func TestGetJSON(t *testing.T) {
154 // First call returns HTTP 500, second succeeds.
155 serverCalls := 0
156 ts := httptest.NewServer(handlerJSON(t, func(body io.Reader) interface{} {
157 serverCalls++
158 content, err := ioutil.ReadAll(body)
159 ut.ExpectEqual(t, nil, err)
160 ut.ExpectEqual(t, []byte{}, content)
161 if serverCalls == 1 {
162 return nil
163 }
164 return map[string]string{"success": "yeah"}
165 }))
166 defer ts.Close()
167
168 actual := map[string]string{}
169 status, err := GetJSON(fast, http.DefaultClient, ts.URL, &actual)
170 ut.AssertEqual(t, nil, err)
171 ut.AssertEqual(t, 200, status)
172 ut.AssertEqual(t, map[string]string{"success": "yeah"}, actual)
173 ut.AssertEqual(t, 2, serverCalls)
174 }
175
176 func TestGetJSONBadResult(t *testing.T) {
177 serverCalls := 0
178 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
179 serverCalls++
180 w.Header().Set("Content-Type", jsonContentType)
181 _, err := io.WriteString(w, "yo")
182 ut.ExpectEqual(t, nil, err)
183 }))
184 defer ts.Close()
185
186 actual := map[string]string{}
187 status, err := GetJSON(fast, http.DefaultClient, ts.URL, &actual)
188 ut.AssertEqual(t, retry.Error{errors.New("bad response " + ts.URL + ": i nvalid character 'y' looking for beginning of value")}, err)
189 ut.AssertEqual(t, 200, status)
190 ut.AssertEqual(t, map[string]string{}, actual)
191 ut.AssertEqual(t, fast.MaxTries, serverCalls)
192 }
193
194 func TestGetJSONBadResultIgnore(t *testing.T) {
195 serverCalls := 0
196 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
197 serverCalls++
198 w.Header().Set("Content-Type", jsonContentType)
199 _, err := io.WriteString(w, "yo")
200 ut.ExpectEqual(t, nil, err)
201 }))
202 defer ts.Close()
203
204 status, err := GetJSON(fast, http.DefaultClient, ts.URL, nil)
205 ut.AssertEqual(t, retry.Error{errors.New("bad response " + ts.URL + ": i nvalid character 'y' looking for beginning of value")}, err)
206 ut.AssertEqual(t, 200, status)
207 }
208
209 func TestGetJSONBadContentTypeIgnore(t *testing.T) {
210 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
211 _, err := io.WriteString(w, "{}")
212 ut.ExpectEqual(t, nil, err)
213 }))
214 defer ts.Close()
215
216 status, err := GetJSON(fast, http.DefaultClient, ts.URL, nil)
217 ut.AssertEqual(t, errors.New("unexpected Content-Type, expected \"applic ation/json; charset=utf-8\", got \"text/plain; charset=utf-8\""), err)
218 ut.AssertEqual(t, 200, status)
219 }
220
221 func TestPostJSON(t *testing.T) {
222 // First call returns HTTP 500, second succeeds.
223 serverCalls := 0
224 ts := httptest.NewServer(handlerJSON(t, func(body io.Reader) interface{} {
225 serverCalls++
226 data := map[string]string{}
227 ut.ExpectEqual(t, nil, json.NewDecoder(body).Decode(&data))
228 ut.ExpectEqual(t, map[string]string{"in": "all"}, data)
229 if serverCalls == 1 {
230 return nil
231 }
232 return map[string]string{"success": "yeah"}
233 }))
234 defer ts.Close()
235
236 in := map[string]string{"in": "all"}
237 actual := map[string]string{}
238 status, err := PostJSON(fast, http.DefaultClient, ts.URL, in, &actual)
239 ut.AssertEqual(t, nil, err)
240 ut.AssertEqual(t, 200, status)
241 ut.AssertEqual(t, map[string]string{"success": "yeah"}, actual)
242 ut.AssertEqual(t, 2, serverCalls)
243 }
244
245 // Private details.
246
247 var fast = &retry.Config{
248 MaxTries: 3,
249 SleepMax: 0,
250 }
251
252 // slow is to be used when no retry should happen. The test will hang in that
253 // case.
254 var slow = &retry.Config{
255 MaxTries: 3,
256 SleepMax: time.Hour,
257 SleepBase: time.Hour,
258 }
259
260 type jsonAPI func(body io.Reader) interface{}
261
262 // handlerJSON converts a jsonAPI http handler to a proper http.Handler.
263 func handlerJSON(t *testing.T, handler jsonAPI) http.Handler {
264 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
265 //ut.ExpectEqual(t, jsonContentType, r.Header.Get("Content-Type" ))
266 defer r.Body.Close()
267 out := handler(r.Body)
268 if out == nil {
269 w.WriteHeader(500)
270 } else {
271 w.Header().Set("Content-Type", jsonContentType)
272 ut.ExpectEqual(t, nil, json.NewEncoder(w).Encode(out))
273 }
274 })
275 }
OLDNEW
« no previous file with comments | « client/internal/lhttp/client.go ('k') | client/internal/lhttp/doc.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698