Browse Source

Merge branch 'master' of github.com:bradfitz/http2

Brad Fitzpatrick 11 years ago
parent
commit
286740e306
2 changed files with 59 additions and 12 deletions
  1. 12 12
      server_test.go
  2. 47 0
      transport_test.go

+ 12 - 12
server_test.go

@@ -40,8 +40,9 @@ type serverTester struct {
 	ts        *httptest.Server
 	fr        *Framer
 	logBuf    *bytes.Buffer
+	logFilter []string   // substrings to filter out
+	scMu      sync.Mutex // guards sc
 	sc        *serverConn
-	logFilter []string // substrings to filter out
 
 	// writing headers:
 	headerBuf bytes.Buffer
@@ -115,15 +116,11 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}
 	if VerboseLogs {
 		t.Logf("Running test server at: %s", ts.URL)
 	}
-	var (
-		mu sync.Mutex
-		sc *serverConn
-	)
 	testHookGetServerConn = func(v *serverConn) {
-		mu.Lock()
-		defer mu.Unlock()
-		sc = v
-		sc.testHookCh = make(chan func())
+		st.scMu.Lock()
+		defer st.scMu.Unlock()
+		st.sc = v
+		st.sc.testHookCh = make(chan func())
 	}
 	log.SetOutput(io.MultiWriter(stderrv, twriter{t: t, st: st}))
 	if !onlyServer {
@@ -135,12 +132,15 @@ func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}
 		st.fr = NewFramer(cc, cc)
 	}
 
-	mu.Lock()
-	st.sc = sc
-	mu.Unlock() // unnecessary, but looks weird without.
 	return st
 }
 
+func (st *serverTester) closeConn() {
+	st.scMu.Lock()
+	defer st.scMu.Unlock()
+	st.sc.conn.Close()
+}
+
 func (st *serverTester) addLogFilter(phrase string) {
 	st.logFilter = append(st.logFilter, phrase)
 }

+ 47 - 0
transport_test.go

@@ -14,6 +14,7 @@ import (
 	"reflect"
 	"strings"
 	"testing"
+	"time"
 )
 
 var (
@@ -119,3 +120,49 @@ func TestTransportReusesConns(t *testing.T) {
 		t.Errorf("first and second responses were on different connections: %q vs %q", first, second)
 	}
 }
+
+func TestTransportAbortClosesPipes(t *testing.T) {
+	shutdown := make(chan struct{})
+	st := newServerTester(t,
+		func(w http.ResponseWriter, r *http.Request) {
+			w.(http.Flusher).Flush()
+			<-shutdown
+		},
+		optOnlyServer,
+	)
+	defer st.Close()
+	defer close(shutdown) // we must shutdown before st.Close() to avoid hanging
+
+	done := make(chan struct{})
+	requestMade := make(chan struct{})
+	go func() {
+		defer close(done)
+		tr := &Transport{
+			InsecureTLSDial: true,
+		}
+		req, err := http.NewRequest("GET", st.ts.URL, nil)
+		if err != nil {
+			t.Fatal(err)
+		}
+		res, err := tr.RoundTrip(req)
+		if err != nil {
+			t.Fatal(err)
+		}
+		defer res.Body.Close()
+		close(requestMade)
+		_, err = ioutil.ReadAll(res.Body)
+		if err == nil {
+			t.Error("expected error from res.Body.Read")
+		}
+	}()
+
+	<-requestMade
+	// Now force the serve loop to end, via closing the connection.
+	st.closeConn()
+	// deadlock? that's a bug.
+	select {
+	case <-done:
+	case <-time.After(3 * time.Second):
+		t.Fatal("timeout")
+	}
+}