mirror of
https://github.com/golang/go
synced 2024-11-17 06:04:47 -07:00
net/http: deflake TestTransportConnectionCloseOnRequest
Fixes #52450 (hopefully) Change-Id: Ib723f8efb4a13af1b98c25cd02935425172d01e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/401314 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Bryan Mills <bcmills@google.com> Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
338a81741a
commit
a2f7d9d95a
@ -306,3 +306,12 @@ func ExportCloseTransportConnsAbruptly(tr *Transport) {
|
|||||||
}
|
}
|
||||||
tr.idleMu.Unlock()
|
tr.idleMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResponseWriterConnForTesting returns w's underlying connection, if w
|
||||||
|
// is a regular *response ResponseWriter.
|
||||||
|
func ResponseWriterConnForTesting(w ResponseWriter) (c net.Conn, ok bool) {
|
||||||
|
if r, ok := w.(*response); ok {
|
||||||
|
return r.conn.rwc, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
@ -57,6 +57,12 @@ var hostPortHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
|
|||||||
}
|
}
|
||||||
w.Header().Set("X-Saw-Close", fmt.Sprint(r.Close))
|
w.Header().Set("X-Saw-Close", fmt.Sprint(r.Close))
|
||||||
w.Write([]byte(r.RemoteAddr))
|
w.Write([]byte(r.RemoteAddr))
|
||||||
|
|
||||||
|
// Include the address of the net.Conn in addition to the RemoteAddr,
|
||||||
|
// in case kernels reuse source ports quickly (see Issue 52450)
|
||||||
|
if c, ok := ResponseWriterConnForTesting(w); ok {
|
||||||
|
fmt.Fprintf(w, ", %T %p", c, c)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// testCloseConn is a net.Conn tracked by a testConnSet.
|
// testCloseConn is a net.Conn tracked by a testConnSet.
|
||||||
@ -240,6 +246,12 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
|
|||||||
connSet.check(t)
|
connSet.check(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestTransportConnectionCloseOnRequest tests that the Transport's doesn't reuse
|
||||||
|
// an underlying TCP connection after making an http.Request with Request.Close set.
|
||||||
|
//
|
||||||
|
// It tests the behavior by making an HTTP request to a server which
|
||||||
|
// describes the source source connection it got (remote port number +
|
||||||
|
// address of its net.Conn).
|
||||||
func TestTransportConnectionCloseOnRequest(t *testing.T) {
|
func TestTransportConnectionCloseOnRequest(t *testing.T) {
|
||||||
defer afterTest(t)
|
defer afterTest(t)
|
||||||
ts := httptest.NewServer(hostPortHandler)
|
ts := httptest.NewServer(hostPortHandler)
|
||||||
@ -250,7 +262,7 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) {
|
|||||||
c := ts.Client()
|
c := ts.Client()
|
||||||
tr := c.Transport.(*Transport)
|
tr := c.Transport.(*Transport)
|
||||||
tr.Dial = testDial
|
tr.Dial = testDial
|
||||||
for _, connectionClose := range []bool{false, true} {
|
for _, reqClose := range []bool{false, true} {
|
||||||
fetch := func(n int) string {
|
fetch := func(n int) string {
|
||||||
req := new(Request)
|
req := new(Request)
|
||||||
var err error
|
var err error
|
||||||
@ -262,29 +274,37 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) {
|
|||||||
req.Proto = "HTTP/1.1"
|
req.Proto = "HTTP/1.1"
|
||||||
req.ProtoMajor = 1
|
req.ProtoMajor = 1
|
||||||
req.ProtoMinor = 1
|
req.ProtoMinor = 1
|
||||||
req.Close = connectionClose
|
req.Close = reqClose
|
||||||
|
|
||||||
res, err := c.Do(req)
|
res, err := c.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
|
t.Fatalf("error in Request.Close=%v, req #%d, Do: %v", reqClose, n, err)
|
||||||
}
|
}
|
||||||
if got, want := res.Header.Get("X-Saw-Close"), fmt.Sprint(connectionClose); got != want {
|
if got, want := res.Header.Get("X-Saw-Close"), fmt.Sprint(reqClose); got != want {
|
||||||
t.Errorf("For connectionClose = %v; handler's X-Saw-Close was %v; want %v",
|
t.Errorf("for Request.Close = %v; handler's X-Saw-Close was %v; want %v",
|
||||||
connectionClose, got, !connectionClose)
|
reqClose, got, !reqClose)
|
||||||
}
|
}
|
||||||
body, err := io.ReadAll(res.Body)
|
body, err := io.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
|
t.Fatalf("for Request.Close=%v, on request %v/2: ReadAll: %v", reqClose, n, err)
|
||||||
}
|
}
|
||||||
return string(body)
|
return string(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
body1 := fetch(1)
|
body1 := fetch(1)
|
||||||
body2 := fetch(2)
|
body2 := fetch(2)
|
||||||
bodiesDiffer := body1 != body2
|
|
||||||
if bodiesDiffer != connectionClose {
|
got := 1
|
||||||
t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
|
if body1 != body2 {
|
||||||
connectionClose, bodiesDiffer, body1, body2)
|
got++
|
||||||
|
}
|
||||||
|
want := 1
|
||||||
|
if reqClose {
|
||||||
|
want = 2
|
||||||
|
}
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("for Request.Close=%v: server saw %v unique connections, wanted %v\n\nbodies were: %q and %q",
|
||||||
|
reqClose, got, want, body1, body2)
|
||||||
}
|
}
|
||||||
|
|
||||||
tr.CloseIdleConnections()
|
tr.CloseIdleConnections()
|
||||||
|
Loading…
Reference in New Issue
Block a user