}
func TestCloseNotifier(t *testing.T) {
+ defer afterTest(t)
gotReq := make(chan bool, 1)
sawClose := make(chan bool, 1)
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
ts.Close()
}
+func TestCloseNotifierChanLeak(t *testing.T) {
+ defer afterTest(t)
+ req := []byte(strings.Replace(`GET / HTTP/1.0
+Host: golang.org
+
+`, "\n", "\r\n", -1))
+ for i := 0; i < 20; i++ {
+ var output bytes.Buffer
+ conn := &rwTestConn{
+ Reader: bytes.NewReader(req),
+ Writer: &output,
+ closec: make(chan bool, 1),
+ }
+ ln := &oneConnListener{conn: conn}
+ handler := HandlerFunc(func(rw ResponseWriter, r *Request) {
+ // Ignore the return value and never read from
+ // it, testing that we don't leak goroutines
+ // on the sending side:
+ _ = rw.(CloseNotifier).CloseNotify()
+ })
+ go Serve(ln, handler)
+ <-conn.closec
+ }
+}
+
func TestOptions(t *testing.T) {
uric := make(chan string, 2) // only expect 1, but leave space for 2
mux := NewServeMux()
c.mu.Lock()
defer c.mu.Unlock()
if c.closeNotifyc == nil {
- c.closeNotifyc = make(chan bool)
+ c.closeNotifyc = make(chan bool, 1)
if c.hijackedv {
// to obey the function signature, even though
// it'll never receive a value.
"created by net/http/httptest.(*Server).Start": "an httptest.Server",
"timeoutHandler": "a TimeoutHandler",
"net.(*netFD).connect(": "a timing out dial",
+ ").noteClientGone(": "a closenotifier sender",
}
var stacks string
for i := 0; i < 4; i++ {