// Test state transitions from new->active->-idle->closed using an actual // network connection and make sure the waitgroup count is correct at the end. func TestStateTransitionActiveIdleClosed(t *testing.T) { var ( listener net.Listener exitchan chan error ) keyFile, err1 := test_helpers.NewTempFile(test_helpers.Key) certFile, err2 := test_helpers.NewTempFile(test_helpers.Cert) defer keyFile.Unlink() defer certFile.Unlink() if err1 != nil || err2 != nil { t.Fatal("Failed to create temporary files", err1, err2) } for _, withTLS := range []bool{false, true} { server := newServer() wg := test_helpers.NewWaitGroup() statechanged := make(chan http.ConnState) server.wg = wg if withTLS { listener, exitchan = startTLSServer(t, server, certFile.Name(), keyFile.Name(), statechanged) } else { listener, exitchan = startServer(t, server, statechanged) } client := newClient(listener.Addr(), withTLS) client.Run() // wait for client to connect, but don't let it send the request if err := <-client.connected; err != nil { t.Fatal("Client failed to connect to server", err) } client.sendrequest <- true waitForState(t, statechanged, http.StateActive, "Client failed to reach active state") rr := <-client.response if rr.err != nil { t.Fatalf("tls=%t unexpected error from client %s", withTLS, rr.err) } waitForState(t, statechanged, http.StateIdle, "Client failed to reach idle state") // client is now in an idle state close(client.sendrequest) <-client.closed waitForState(t, statechanged, http.StateClosed, "Client failed to reach closed state") server.Close() waiting := <-wg.WaitCalled if waiting != 0 { t.Errorf("Waitcount should be zero, got %d", waiting) } if err := <-exitchan; err != nil { t.Error("Unexpected error during shutdown", err) } } }
// Use the top level functions to instantiate servers and make sure // they all shutdown when Close() is called func TestGlobalShutdown(t *testing.T) { laserr := make(chan error) lastlserr := make(chan error) serveerr := make(chan error) go func() { laserr <- ListenAndServe("127.0.0.1:0", nullHandler) }() go func() { keyFile, _ := test_helpers.NewTempFile(test_helpers.Key) certFile, _ := test_helpers.NewTempFile(test_helpers.Cert) defer keyFile.Unlink() defer certFile.Unlink() lastlserr <- ListenAndServeTLS("127.0.0.1:0", certFile.Name(), keyFile.Name(), nullHandler) }() go func() { l := test_helpers.NewListener() serveerr <- Serve(l, nullHandler) }() // wait for registration expected := 3 var sl int for sl < expected { m.Lock() sl = len(servers) m.Unlock() time.Sleep(time.Millisecond) } Close() for i := 0; i < expected; i++ { select { case err := <-laserr: if err != nil { t.Error("ListenAndServe returned error", err) } laserr = nil case err := <-lastlserr: if err != nil { t.Error("ListenAndServeTLS returned error", err) } lastlserr = nil case err := <-serveerr: if err != nil { t.Error("Serve returned error", err) } serveerr = nil case <-time.After(time.Second): t.Fatal("Timed out waiting for servers to exit") } } }