}
r := bufio.NewReader(conn)
- _, err = ReadResponse(r, &Request{Method: "GET"})
+ res, err := ReadResponse(r, &Request{Method: "GET"})
if err != nil {
t.Fatal("ReadResponse error:", err)
}
- success := make(chan bool)
+ didReadAll := make(chan bool, 1)
go func() {
select {
case <-time.After(5 * time.Second):
- t.Fatal("body not closed after 5s")
- case <-success:
+ t.Error("body not closed after 5s")
+ return
+ case <-didReadAll:
}
}()
if err != nil {
t.Fatal("read error:", err)
}
+ didReadAll <- true
- success <- true
+ if !res.Close {
+ t.Errorf("Response.Close = false; want true")
+ }
}
// TestServeHTTP10Close verifies that HTTP/1.0 requests won't be kept alive.
t *Transport
cacheKey string // its connectMethod.String()
conn net.Conn
+ closed bool // whether conn has been closed
br *bufio.Reader // from conn
bw *bufio.Writer // to conn
reqch chan requestAndChan // written by roundTrip(); read by readLoop()
if alive && !pc.t.putIdleConn(pc) {
alive = false
}
+ if !alive {
+ pc.close()
+ }
waitForBodyRead <- true
}
}
func (pc *persistConn) closeLocked() {
pc.broken = true
- pc.conn.Close()
+ if !pc.closed {
+ pc.conn.Close()
+ pc.closed = true
+ }
pc.mutateHeaderFunc = nil
}
w.Write([]byte(r.RemoteAddr))
})
+// testCloseConn is a net.Conn tracked by a testConnSet.
type testCloseConn struct {
net.Conn
set *testConnSet
}
-func (conn *testCloseConn) Close() error {
- conn.set.remove(conn)
- return conn.Conn.Close()
+func (c *testCloseConn) Close() error {
+ c.set.remove(c)
+ return c.Conn.Close()
}
+// testConnSet tracks a set of TCP connections and whether they've
+// been closed.
type testConnSet struct {
+ t *testing.T
closed map[net.Conn]bool
list []net.Conn // in order created
mutex sync.Mutex
}
// some tests use this to manage raw tcp connections for later inspection
-func makeTestDial() (*testConnSet, func(n, addr string) (net.Conn, error)) {
+func makeTestDial(t *testing.T) (*testConnSet, func(n, addr string) (net.Conn, error)) {
connSet := &testConnSet{
+ t: t,
closed: make(map[net.Conn]bool),
}
dial := func(n, addr string) (net.Conn, error) {
for i, c := range tcs.list {
if !tcs.closed[c] {
- // TODO(bradfitz,gustavo): make the following
- // line an Errorf, not Logf, once issue 3540
- // is fixed again.
- t.Logf("TCP connection #%d (of %d total) was not closed", i+1, len(tcs.list))
+ t.Errorf("TCP connection #%d, %p (of %d total) was not closed", i+1, c, len(tcs.list))
}
}
}
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
- connSet, testDial := makeTestDial()
+ connSet, testDial := makeTestDial(t)
for _, connectionClose := range []bool{false, true} {
tr := &Transport{
ts := httptest.NewServer(hostPortHandler)
defer ts.Close()
- connSet, testDial := makeTestDial()
+ connSet, testDial := makeTestDial(t)
for _, connectionClose := range []bool{false, true} {
tr := &Transport{