1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // White-box tests for transport.go (in package http instead of http_test).
16 // Issue 15446: incorrect wrapping of errors when server closes an idle connection.
17 func TestTransportPersistConnReadLoopEOF(t
*testing
.T
) {
18 ln
:= newLocalListener(t
)
21 connc
:= make(chan net
.Conn
, 1)
33 req
, _
:= NewRequest("GET", "http://"+ln
.Addr().String(), nil)
35 treq
:= &transportRequest
{Request
: req
}
36 cm
:= connectMethod
{targetScheme
: "http", targetAddr
: ln
.Addr().String()}
37 pc
, err
:= tr
.getConn(treq
, cm
)
41 defer pc
.close(errors
.New("test over"))
45 // Already called t.Error in the accept goroutine.
48 conn
.Close() // simulate the server hanging up on the client
50 _
, err
= pc
.roundTrip(treq
)
51 if !isTransportReadFromServerError(err
) && err
!= errServerClosedIdle
{
52 t
.Errorf("roundTrip = %#v, %v; want errServerClosedIdle or transportReadFromServerError", err
, err
)
57 if !isTransportReadFromServerError(err
) && err
!= errServerClosedIdle
{
58 t
.Errorf("pc.closed = %#v, %v; want errServerClosedIdle or transportReadFromServerError", err
, err
)
62 func isTransportReadFromServerError(err error
) bool {
63 _
, ok
:= err
.(transportReadFromServerError
)
67 func newLocalListener(t
*testing
.T
) net
.Listener
{
68 ln
, err
:= net
.Listen("tcp", "127.0.0.1:0")
70 ln
, err
= net
.Listen("tcp6", "[::1]:0")
78 func dummyRequest(method
string) *Request
{
79 req
, err
:= NewRequest(method
, "http://fake.tld/", nil)
85 func dummyRequestWithBody(method
string) *Request
{
86 req
, err
:= NewRequest(method
, "http://fake.tld/", strings
.NewReader("foo"))
93 func dummyRequestWithBodyNoGetBody(method
string) *Request
{
94 req
:= dummyRequestWithBody(method
)
99 // issue22091Error acts like a golang.org/x/net/http2.ErrNoCachedConn.
100 type issue22091Error
struct{}
102 func (issue22091Error
) IsHTTP2NoCachedConnError() {}
103 func (issue22091Error
) Error() string { return "issue22091Error" }
105 func TestTransportShouldRetryRequest(t
*testing
.T
) {
114 pc
: &persistConn
{reused
: false},
115 req
: dummyRequest("POST"),
116 err
: nothingWrittenError
{},
120 pc
: &persistConn
{reused
: true},
121 req
: dummyRequest("POST"),
122 err
: nothingWrittenError
{},
126 pc
: &persistConn
{reused
: true},
127 req
: dummyRequest("POST"),
128 err
: http2ErrNoCachedConn
,
134 err
: issue22091Error
{}, // like an external http2ErrNoCachedConn
138 pc
: &persistConn
{reused
: true},
139 req
: dummyRequest("POST"),
144 pc
: &persistConn
{reused
: true},
145 req
: dummyRequest("POST"),
146 err
: transportReadFromServerError
{},
150 pc
: &persistConn
{reused
: true},
151 req
: dummyRequest("GET"),
152 err
: transportReadFromServerError
{},
156 pc
: &persistConn
{reused
: true},
157 req
: dummyRequest("GET"),
158 err
: errServerClosedIdle
,
162 pc
: &persistConn
{reused
: true},
163 req
: dummyRequestWithBody("POST"),
164 err
: nothingWrittenError
{},
168 pc
: &persistConn
{reused
: true},
169 req
: dummyRequestWithBodyNoGetBody("POST"),
170 err
: nothingWrittenError
{},
174 for i
, tt
:= range tests
{
175 got
:= tt
.pc
.shouldRetryRequest(tt
.req
, tt
.err
)
177 t
.Errorf("%d. shouldRetryRequest = %v; want %v", i
, got
, tt
.want
)