| OLD | NEW | 
| (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 } | 
| OLD | NEW |