package net // Regression: a fatal transport failure (a listener that cannot bind, an // Accept loop that dies outside shutdown) must unblock ListenAndServe with // the error — a server must never sit running with no way in — and a // failure followed by Shutdown must not panic on a double close of done. import ( "fmt" "net" "net/http" "testing" "time" ) func TestTransportFailureStopsListenAndServe(t *testing.T) { ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } defer ln.Close() port := fmt.Sprintf("127.0.0.1:%d", ln.Addr().(*net.TCPAddr).Port) s := &Server{hub: NewHub(), done: make(chan struct{})} s.httpServer = &http.Server{Addr: port, Handler: http.NewServeMux()} result := make(chan error, 1) go func() { go s.serveHTTP() <-s.done result <- s.listenErr }() select { case err := <-result: if err == nil { t.Fatal("transport failure unblocked ListenAndServe without an error") } // Shutdown after a failure must not double-close done. s.Shutdown() case <-time.After(2 * time.Second): t.Fatal("a failed listener left the server running") } }