Skip to content

Commit 3b988eb

Browse files
johanbrandhorstbradfitz
authored andcommitted
net/http: use httptest.Server Client in tests
After merging https://go-review.googlesource.com/c/34639/, it was pointed out to me that a lot of tests under net/http could use the new functionality to simplify and unify testing. Using the httptest.Server provided Client removes the need to call CloseIdleConnections() on all Transports created, as it is automatically called on the Transport associated with the client when Server.Close() is called. Change the transport used by the non-TLS httptest.Server to a new *http.Transport rather than using http.DefaultTransport implicitly. The TLS version already used its own *http.Transport. This change is to prevent concurrency problems with using DefaultTransport implicitly across several httptest.Server's. Add tests to ensure the httptest.Server.Client().Transport RoundTripper interface is implemented by a *http.Transport, as is now assumed across large parts of net/http tests. Change-Id: I9f9d15f59d72893deead5678d314388718c91821 Reviewed-on: https://go-review.googlesource.com/37771 Run-TryBot: Brad Fitzpatrick <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent 2bd6360 commit 3b988eb

File tree

9 files changed

+321
-456
lines changed

9 files changed

+321
-456
lines changed

src/net/http/client_test.go

Lines changed: 61 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"bytes"
1111
"context"
1212
"crypto/tls"
13-
"crypto/x509"
1413
"encoding/base64"
1514
"errors"
1615
"fmt"
@@ -73,7 +72,7 @@ func TestClient(t *testing.T) {
7372
ts := httptest.NewServer(robotsTxtHandler)
7473
defer ts.Close()
7574

76-
c := &Client{Transport: &Transport{DisableKeepAlives: true}}
75+
c := ts.Client()
7776
r, err := c.Get(ts.URL)
7877
var b []byte
7978
if err == nil {
@@ -220,10 +219,7 @@ func TestClientRedirects(t *testing.T) {
220219
}))
221220
defer ts.Close()
222221

223-
tr := &Transport{}
224-
defer tr.CloseIdleConnections()
225-
226-
c := &Client{Transport: tr}
222+
c := ts.Client()
227223
_, err := c.Get(ts.URL)
228224
if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
229225
t.Errorf("with default client Get, expected error %q, got %q", e, g)
@@ -252,13 +248,10 @@ func TestClientRedirects(t *testing.T) {
252248
var checkErr error
253249
var lastVia []*Request
254250
var lastReq *Request
255-
c = &Client{
256-
Transport: tr,
257-
CheckRedirect: func(req *Request, via []*Request) error {
258-
lastReq = req
259-
lastVia = via
260-
return checkErr
261-
},
251+
c.CheckRedirect = func(req *Request, via []*Request) error {
252+
lastReq = req
253+
lastVia = via
254+
return checkErr
262255
}
263256
res, err := c.Get(ts.URL)
264257
if err != nil {
@@ -313,21 +306,16 @@ func TestClientRedirectContext(t *testing.T) {
313306
}))
314307
defer ts.Close()
315308

316-
tr := &Transport{}
317-
defer tr.CloseIdleConnections()
318-
319309
ctx, cancel := context.WithCancel(context.Background())
320-
c := &Client{
321-
Transport: tr,
322-
CheckRedirect: func(req *Request, via []*Request) error {
323-
cancel()
324-
select {
325-
case <-req.Context().Done():
326-
return nil
327-
case <-time.After(5 * time.Second):
328-
return errors.New("redirected request's context never expired after root request canceled")
329-
}
330-
},
310+
c := ts.Client()
311+
c.CheckRedirect = func(req *Request, via []*Request) error {
312+
cancel()
313+
select {
314+
case <-req.Context().Done():
315+
return nil
316+
case <-time.After(5 * time.Second):
317+
return errors.New("redirected request's context never expired after root request canceled")
318+
}
331319
}
332320
req, _ := NewRequest("GET", ts.URL, nil)
333321
req = req.WithContext(ctx)
@@ -461,11 +449,12 @@ func testRedirectsByMethod(t *testing.T, method string, table []redirectTest, wa
461449
}))
462450
defer ts.Close()
463451

452+
c := ts.Client()
464453
for _, tt := range table {
465454
content := tt.redirectBody
466455
req, _ := NewRequest(method, ts.URL+tt.suffix, strings.NewReader(content))
467456
req.GetBody = func() (io.ReadCloser, error) { return ioutil.NopCloser(strings.NewReader(content)), nil }
468-
res, err := DefaultClient.Do(req)
457+
res, err := c.Do(req)
469458

470459
if err != nil {
471460
t.Fatal(err)
@@ -519,17 +508,12 @@ func TestClientRedirectUseResponse(t *testing.T) {
519508
}))
520509
defer ts.Close()
521510

522-
tr := &Transport{}
523-
defer tr.CloseIdleConnections()
524-
525-
c := &Client{
526-
Transport: tr,
527-
CheckRedirect: func(req *Request, via []*Request) error {
528-
if req.Response == nil {
529-
t.Error("expected non-nil Request.Response")
530-
}
531-
return ErrUseLastResponse
532-
},
511+
c := ts.Client()
512+
c.CheckRedirect = func(req *Request, via []*Request) error {
513+
if req.Response == nil {
514+
t.Error("expected non-nil Request.Response")
515+
}
516+
return ErrUseLastResponse
533517
}
534518
res, err := c.Get(ts.URL)
535519
if err != nil {
@@ -558,7 +542,7 @@ func TestClientRedirect308NoLocation(t *testing.T) {
558542
w.WriteHeader(308)
559543
}))
560544
defer ts.Close()
561-
c := &Client{Transport: &Transport{DisableKeepAlives: true}}
545+
c := ts.Client()
562546
res, err := c.Get(ts.URL)
563547
if err != nil {
564548
t.Fatal(err)
@@ -586,7 +570,7 @@ func TestClientRedirect308NoGetBody(t *testing.T) {
586570
if err != nil {
587571
t.Fatal(err)
588572
}
589-
c := &Client{Transport: &Transport{DisableKeepAlives: true}}
573+
c := ts.Client()
590574
req.GetBody = nil // so it can't rewind.
591575
res, err := c.Do(req)
592576
if err != nil {
@@ -678,12 +662,8 @@ func TestRedirectCookiesJar(t *testing.T) {
678662
var ts *httptest.Server
679663
ts = httptest.NewServer(echoCookiesRedirectHandler)
680664
defer ts.Close()
681-
tr := &Transport{}
682-
defer tr.CloseIdleConnections()
683-
c := &Client{
684-
Transport: tr,
685-
Jar: new(TestJar),
686-
}
665+
c := ts.Client()
666+
c.Jar = new(TestJar)
687667
u, _ := url.Parse(ts.URL)
688668
c.Jar.SetCookies(u, []*Cookie{expectedCookies[0]})
689669
resp, err := c.Get(ts.URL)
@@ -727,13 +707,10 @@ func TestJarCalls(t *testing.T) {
727707
}))
728708
defer ts.Close()
729709
jar := new(RecordingJar)
730-
c := &Client{
731-
Jar: jar,
732-
Transport: &Transport{
733-
Dial: func(_ string, _ string) (net.Conn, error) {
734-
return net.Dial("tcp", ts.Listener.Addr().String())
735-
},
736-
},
710+
c := ts.Client()
711+
c.Jar = jar
712+
c.Transport.(*Transport).Dial = func(_ string, _ string) (net.Conn, error) {
713+
return net.Dial("tcp", ts.Listener.Addr().String())
737714
}
738715
_, err := c.Get("http://firsthost.fake/")
739716
if err != nil {
@@ -845,7 +822,8 @@ func TestClientWrites(t *testing.T) {
845822
}
846823
return c, err
847824
}
848-
c := &Client{Transport: &Transport{Dial: dialer}}
825+
c := ts.Client()
826+
c.Transport.(*Transport).Dial = dialer
849827

850828
_, err := c.Get(ts.URL)
851829
if err != nil {
@@ -878,14 +856,11 @@ func TestClientInsecureTransport(t *testing.T) {
878856
// TODO(bradfitz): add tests for skipping hostname checks too?
879857
// would require a new cert for testing, and probably
880858
// redundant with these tests.
859+
c := ts.Client()
881860
for _, insecure := range []bool{true, false} {
882-
tr := &Transport{
883-
TLSClientConfig: &tls.Config{
884-
InsecureSkipVerify: insecure,
885-
},
861+
c.Transport.(*Transport).TLSClientConfig = &tls.Config{
862+
InsecureSkipVerify: insecure,
886863
}
887-
defer tr.CloseIdleConnections()
888-
c := &Client{Transport: tr}
889864
res, err := c.Get(ts.URL)
890865
if (err == nil) != insecure {
891866
t.Errorf("insecure=%v: got unexpected err=%v", insecure, err)
@@ -919,22 +894,6 @@ func TestClientErrorWithRequestURI(t *testing.T) {
919894
}
920895
}
921896

922-
func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport {
923-
certs := x509.NewCertPool()
924-
for _, c := range ts.TLS.Certificates {
925-
roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1])
926-
if err != nil {
927-
t.Fatalf("error parsing server's root cert: %v", err)
928-
}
929-
for _, root := range roots {
930-
certs.AddCert(root)
931-
}
932-
}
933-
return &Transport{
934-
TLSClientConfig: &tls.Config{RootCAs: certs},
935-
}
936-
}
937-
938897
func TestClientWithCorrectTLSServerName(t *testing.T) {
939898
defer afterTest(t)
940899

@@ -946,9 +905,8 @@ func TestClientWithCorrectTLSServerName(t *testing.T) {
946905
}))
947906
defer ts.Close()
948907

949-
trans := newTLSTransport(t, ts)
950-
trans.TLSClientConfig.ServerName = serverName
951-
c := &Client{Transport: trans}
908+
c := ts.Client()
909+
c.Transport.(*Transport).TLSClientConfig.ServerName = serverName
952910
if _, err := c.Get(ts.URL); err != nil {
953911
t.Fatalf("expected successful TLS connection, got error: %v", err)
954912
}
@@ -961,9 +919,8 @@ func TestClientWithIncorrectTLSServerName(t *testing.T) {
961919
errc := make(chanWriter, 10) // but only expecting 1
962920
ts.Config.ErrorLog = log.New(errc, "", 0)
963921

964-
trans := newTLSTransport(t, ts)
965-
trans.TLSClientConfig.ServerName = "badserver"
966-
c := &Client{Transport: trans}
922+
c := ts.Client()
923+
c.Transport.(*Transport).TLSClientConfig.ServerName = "badserver"
967924
_, err := c.Get(ts.URL)
968925
if err == nil {
969926
t.Fatalf("expected an error")
@@ -997,13 +954,12 @@ func TestTransportUsesTLSConfigServerName(t *testing.T) {
997954
}))
998955
defer ts.Close()
999956

1000-
tr := newTLSTransport(t, ts)
957+
c := ts.Client()
958+
tr := c.Transport.(*Transport)
1001959
tr.TLSClientConfig.ServerName = "example.com" // one of httptest's Server cert names
1002960
tr.Dial = func(netw, addr string) (net.Conn, error) {
1003961
return net.Dial(netw, ts.Listener.Addr().String())
1004962
}
1005-
defer tr.CloseIdleConnections()
1006-
c := &Client{Transport: tr}
1007963
res, err := c.Get("https://some-other-host.tld/")
1008964
if err != nil {
1009965
t.Fatal(err)
@@ -1018,13 +974,12 @@ func TestResponseSetsTLSConnectionState(t *testing.T) {
1018974
}))
1019975
defer ts.Close()
1020976

1021-
tr := newTLSTransport(t, ts)
977+
c := ts.Client()
978+
tr := c.Transport.(*Transport)
1022979
tr.TLSClientConfig.CipherSuites = []uint16{tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA}
1023980
tr.Dial = func(netw, addr string) (net.Conn, error) {
1024981
return net.Dial(netw, ts.Listener.Addr().String())
1025982
}
1026-
defer tr.CloseIdleConnections()
1027-
c := &Client{Transport: tr}
1028983
res, err := c.Get("https://example.com/")
1029984
if err != nil {
1030985
t.Fatal(err)
@@ -1119,14 +1074,12 @@ func TestEmptyPasswordAuth(t *testing.T) {
11191074
}
11201075
}))
11211076
defer ts.Close()
1122-
tr := &Transport{}
1123-
defer tr.CloseIdleConnections()
1124-
c := &Client{Transport: tr}
11251077
req, err := NewRequest("GET", ts.URL, nil)
11261078
if err != nil {
11271079
t.Fatal(err)
11281080
}
11291081
req.URL.User = url.User(gopher)
1082+
c := ts.Client()
11301083
resp, err := c.Do(req)
11311084
if err != nil {
11321085
t.Fatal(err)
@@ -1503,21 +1456,17 @@ func TestClientCopyHeadersOnRedirect(t *testing.T) {
15031456
defer ts2.Close()
15041457
ts2URL = ts2.URL
15051458

1506-
tr := &Transport{}
1507-
defer tr.CloseIdleConnections()
1508-
c := &Client{
1509-
Transport: tr,
1510-
CheckRedirect: func(r *Request, via []*Request) error {
1511-
want := Header{
1512-
"User-Agent": []string{ua},
1513-
"X-Foo": []string{xfoo},
1514-
"Referer": []string{ts2URL},
1515-
}
1516-
if !reflect.DeepEqual(r.Header, want) {
1517-
t.Errorf("CheckRedirect Request.Header = %#v; want %#v", r.Header, want)
1518-
}
1519-
return nil
1520-
},
1459+
c := ts1.Client()
1460+
c.CheckRedirect = func(r *Request, via []*Request) error {
1461+
want := Header{
1462+
"User-Agent": []string{ua},
1463+
"X-Foo": []string{xfoo},
1464+
"Referer": []string{ts2URL},
1465+
}
1466+
if !reflect.DeepEqual(r.Header, want) {
1467+
t.Errorf("CheckRedirect Request.Header = %#v; want %#v", r.Header, want)
1468+
}
1469+
return nil
15211470
}
15221471

15231472
req, _ := NewRequest("GET", ts2.URL, nil)
@@ -1606,13 +1555,9 @@ func TestClientAltersCookiesOnRedirect(t *testing.T) {
16061555
}))
16071556
defer ts.Close()
16081557

1609-
tr := &Transport{}
1610-
defer tr.CloseIdleConnections()
16111558
jar, _ := cookiejar.New(nil)
1612-
c := &Client{
1613-
Transport: tr,
1614-
Jar: jar,
1615-
}
1559+
c := ts.Client()
1560+
c.Jar = jar
16161561

16171562
u, _ := url.Parse(ts.URL)
16181563
req, _ := NewRequest("GET", ts.URL, nil)
@@ -1730,9 +1675,7 @@ func TestClientRedirectTypes(t *testing.T) {
17301675
}))
17311676
defer ts.Close()
17321677

1733-
tr := &Transport{}
1734-
defer tr.CloseIdleConnections()
1735-
1678+
c := ts.Client()
17361679
for i, tt := range tests {
17371680
handlerc <- func(w ResponseWriter, r *Request) {
17381681
w.Header().Set("Location", ts.URL)
@@ -1745,7 +1688,6 @@ func TestClientRedirectTypes(t *testing.T) {
17451688
continue
17461689
}
17471690

1748-
c := &Client{Transport: tr}
17491691
c.CheckRedirect = func(req *Request, via []*Request) error {
17501692
if got, want := req.Method, tt.wantMethod; got != want {
17511693
return fmt.Errorf("#%d: got next method %q; want %q", i, got, want)
@@ -1799,9 +1741,8 @@ func TestTransportBodyReadError(t *testing.T) {
17991741
w.Header().Set("X-Body-Read", fmt.Sprintf("%v, %v", n, err))
18001742
}))
18011743
defer ts.Close()
1802-
tr := &Transport{}
1803-
defer tr.CloseIdleConnections()
1804-
c := &Client{Transport: tr}
1744+
c := ts.Client()
1745+
tr := c.Transport.(*Transport)
18051746

18061747
// Do one initial successful request to create an idle TCP connection
18071748
// for the subsequent request to reuse. (The Transport only retries

0 commit comments

Comments
 (0)