http2: clearer distinction between test server types

newServerTester is used to create an HTTP/2 server for testing.
It returns a *serverTester, which includes a number of methods
for sending frames to and reading frames from a server connection
under test.

Many tests also use newServerTester to simply start an
*httptest.Server. These tests pass an "optOnlyServer" to
indicate that they don't need a client connection to interact with.
They interact with the *httptest.Server, and use no methods or
fields of *serverTester.

Make a clearer distinction between test types.

Add a newTestServer function which starts and returns
an *httptest.Server.

This function replaces use of newServerTester with optOnlyServer.

Change-Id: Ia590c9b4dcc23c17e530b0cc273b9120965da11a
Reviewed-on: https://go-review.googlesource.com/c/net/+/586155
Reviewed-by: Jonathan Amsterdam <jba@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/http2/server_test.go b/http2/server_test.go
index 0db1a40..9cdd482 100644
--- a/http2/server_test.go
+++ b/http2/server_test.go
@@ -101,12 +101,50 @@
 	testHookOnPanicMu.Unlock()
 }
 
+func newTestServer(t testing.TB, handler http.HandlerFunc, opts ...interface{}) *httptest.Server {
+	ts := httptest.NewUnstartedServer(handler)
+	ts.EnableHTTP2 = true
+	ts.Config.ErrorLog = log.New(twriter{t: t}, "", log.LstdFlags)
+	h2server := new(Server)
+	for _, opt := range opts {
+		switch v := opt.(type) {
+		case func(*httptest.Server):
+			v(ts)
+		case func(*Server):
+			v(h2server)
+		default:
+			t.Fatalf("unknown newTestServer option type %T", v)
+		}
+	}
+	ConfigureServer(ts.Config, h2server)
+
+	// ConfigureServer populates ts.Config.TLSConfig.
+	// Copy it to ts.TLS as well.
+	ts.TLS = ts.Config.TLSConfig
+
+	// Go 1.22 changes the default minimum TLS version to TLS 1.2,
+	// in order to properly test cases where we want to reject low
+	// TLS versions, we need to explicitly configure the minimum
+	// version here.
+	ts.Config.TLSConfig.MinVersion = tls.VersionTLS10
+
+	ts.StartTLS()
+	t.Cleanup(func() {
+		ts.CloseClientConnections()
+		ts.Close()
+	})
+
+	return ts
+}
+
 type serverTesterOpt string
 
-var optOnlyServer = serverTesterOpt("only_server")
-var optQuiet = serverTesterOpt("quiet_logging")
 var optFramerReuseFrames = serverTesterOpt("frame_reuse_frames")
 
+var optQuiet = func(ts *httptest.Server) {
+	ts.Config.ErrorLog = log.New(io.Discard, "", 0)
+}
+
 func newServerTester(t testing.TB, handler http.HandlerFunc, opts ...interface{}) *serverTester {
 	resetHooks()
 
@@ -117,7 +155,7 @@
 		NextProtos:         []string{NextProtoTLS},
 	}
 
-	var onlyServer, quiet, framerReuseFrames bool
+	var framerReuseFrames bool
 	h2server := new(Server)
 	for _, opt := range opts {
 		switch v := opt.(type) {
@@ -129,10 +167,6 @@
 			v(h2server)
 		case serverTesterOpt:
 			switch v {
-			case optOnlyServer:
-				onlyServer = true
-			case optQuiet:
-				quiet = true
 			case optFramerReuseFrames:
 				framerReuseFrames = true
 			}
@@ -159,9 +193,7 @@
 	st.hpackDec = hpack.NewDecoder(initialHeaderTableSize, st.onHeaderField)
 
 	ts.TLS = ts.Config.TLSConfig // the httptest.Server has its own copy of this TLS config
-	if quiet {
-		ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
-	} else {
+	if ts.Config.ErrorLog == nil {
 		ts.Config.ErrorLog = log.New(io.MultiWriter(stderrv(), twriter{t: t, st: st}, &st.serverLogBuf), "", log.LstdFlags)
 	}
 	ts.StartTLS()
@@ -175,32 +207,30 @@
 		st.sc = v
 	}
 	log.SetOutput(io.MultiWriter(stderrv(), twriter{t: t, st: st}))
-	if !onlyServer {
-		cc, err := tls.Dial("tcp", ts.Listener.Addr().String(), tlsConfig)
-		if err != nil {
-			t.Fatal(err)
+	cc, err := tls.Dial("tcp", ts.Listener.Addr().String(), tlsConfig)
+	if err != nil {
+		t.Fatal(err)
+	}
+	st.cc = cc
+	st.fr = NewFramer(cc, cc)
+	if framerReuseFrames {
+		st.fr.SetReuseFrames()
+	}
+	if !logFrameReads && !logFrameWrites {
+		st.fr.debugReadLoggerf = func(m string, v ...interface{}) {
+			m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n"
+			st.frameReadLogMu.Lock()
+			fmt.Fprintf(&st.frameReadLogBuf, m, v...)
+			st.frameReadLogMu.Unlock()
 		}
-		st.cc = cc
-		st.fr = NewFramer(cc, cc)
-		if framerReuseFrames {
-			st.fr.SetReuseFrames()
+		st.fr.debugWriteLoggerf = func(m string, v ...interface{}) {
+			m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n"
+			st.frameWriteLogMu.Lock()
+			fmt.Fprintf(&st.frameWriteLogBuf, m, v...)
+			st.frameWriteLogMu.Unlock()
 		}
-		if !logFrameReads && !logFrameWrites {
-			st.fr.debugReadLoggerf = func(m string, v ...interface{}) {
-				m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n"
-				st.frameReadLogMu.Lock()
-				fmt.Fprintf(&st.frameReadLogBuf, m, v...)
-				st.frameReadLogMu.Unlock()
-			}
-			st.fr.debugWriteLoggerf = func(m string, v ...interface{}) {
-				m = time.Now().Format("2006-01-02 15:04:05.999999999 ") + strings.TrimPrefix(m, "http2: ") + "\n"
-				st.frameWriteLogMu.Lock()
-				fmt.Fprintf(&st.frameWriteLogBuf, m, v...)
-				st.frameWriteLogMu.Unlock()
-			}
-			st.fr.logReads = true
-			st.fr.logWrites = true
-		}
+		st.fr.logReads = true
+		st.fr.logWrites = true
 	}
 	return st
 }
@@ -3067,16 +3097,15 @@
 func TestServerWritesUndeclaredTrailers(t *testing.T) {
 	const trailer = "Trailer-Header"
 	const value = "hi1"
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set(http.TrailerPrefix+trailer, value)
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
 	cl := &http.Client{Transport: tr}
-	resp, err := cl.Get(st.ts.URL)
+	resp, err := cl.Get(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -3731,7 +3760,7 @@
 	doRead := make(chan bool, 1)
 	defer close(doRead) // fallback cleanup
 
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		io.WriteString(w, msg)
 		w.(http.Flusher).Flush()
 
@@ -3740,14 +3769,12 @@
 		r.Body.Read(make([]byte, 10))
 
 		io.WriteString(w, msg2)
-
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
-	req, _ := http.NewRequest("POST", st.ts.URL, io.LimitReader(neverEnding('A'), 2<<20))
+	req, _ := http.NewRequest("POST", ts.URL, io.LimitReader(neverEnding('A'), 2<<20))
 	req.Header.Set("Expect", "100-continue")
 
 	res, err := tr.RoundTrip(req)
@@ -3808,14 +3835,13 @@
 			unblock := make(chan bool, 1)
 			defer close(unblock)
 
-			st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+			ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 				// Don't read the 16KB request body. Wait until the client's
 				// done sending it and then return. This should cause the Server
 				// to then return those 16KB of flow control to the client.
 				tt.reqFn(r)
 				<-unblock
-			}, optOnlyServer)
-			defer st.Close()
+			})
 
 			tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 			defer tr.CloseIdleConnections()
@@ -3833,7 +3859,7 @@
 						return 0, io.EOF
 					}),
 				)
-				req, _ := http.NewRequest("POST", st.ts.URL, body)
+				req, _ := http.NewRequest("POST", ts.URL, body)
 				res, err := tr.RoundTrip(req)
 				if err != nil {
 					t.Fatal(tt.name, err)
@@ -3949,22 +3975,21 @@
 		itemCount = 100
 	)
 
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		for i := 0; i < itemCount; i++ {
 			_, err := w.Write(make([]byte, itemSize))
 			if err != nil {
 				return
 			}
 		}
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 	cl := &http.Client{Transport: tr}
 
 	for i := 0; i < 1000; i++ {
-		resp, err := cl.Get(st.ts.URL)
+		resp, err := cl.Get(ts.URL)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -4241,26 +4266,25 @@
 
 	for _, tt := range resps {
 		t.Run(tt.name, func(t *testing.T) {
-			st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+			ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 				if tt.contentEncoding != nil {
 					w.Header().Set("Content-Encoding", tt.contentEncoding.(string))
 				}
 				w.Write(tt.body)
-			}, optOnlyServer)
-			defer st.Close()
+			})
 
 			tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 			defer tr.CloseIdleConnections()
 
-			req, _ := http.NewRequest("GET", st.ts.URL, nil)
+			req, _ := http.NewRequest("GET", ts.URL, nil)
 			res, err := tr.RoundTrip(req)
 			if err != nil {
-				t.Fatalf("GET %s: %v", st.ts.URL, err)
+				t.Fatalf("GET %s: %v", ts.URL, err)
 			}
 			defer res.Body.Close()
 
 			g := res.Header.Get("Content-Encoding")
-			t.Logf("%s: Content-Encoding: %s", st.ts.URL, g)
+			t.Logf("%s: Content-Encoding: %s", ts.URL, g)
 
 			if w := tt.contentEncoding; g != w {
 				if w != nil { // The case where contentEncoding was set explicitly.
@@ -4274,7 +4298,7 @@
 			if w := tt.wantContentType; g != w {
 				t.Errorf("Content-Type mismatch\n\tgot:  %q\n\twant: %q", g, w)
 			}
-			t.Logf("%s: Content-Type: %s", st.ts.URL, g)
+			t.Logf("%s: Content-Type: %s", ts.URL, g)
 		})
 	}
 }
@@ -4606,7 +4630,7 @@
 // We should not access the slice after this point.
 func TestServerWriteDoesNotRetainBufferAfterReturn(t *testing.T) {
 	donec := make(chan struct{})
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		defer close(donec)
 		buf := make([]byte, 1<<20)
 		var i byte
@@ -4620,13 +4644,12 @@
 				return
 			}
 		}
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
-	req, _ := http.NewRequest("GET", st.ts.URL, nil)
+	req, _ := http.NewRequest("GET", ts.URL, nil)
 	res, err := tr.RoundTrip(req)
 	if err != nil {
 		t.Fatal(err)
@@ -4642,7 +4665,7 @@
 // We should not access the slice after this point.
 func TestServerWriteDoesNotRetainBufferAfterServerClose(t *testing.T) {
 	donec := make(chan struct{}, 1)
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		donec <- struct{}{}
 		defer close(donec)
 		buf := make([]byte, 1<<20)
@@ -4657,20 +4680,19 @@
 				return
 			}
 		}
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
-	req, _ := http.NewRequest("GET", st.ts.URL, nil)
+	req, _ := http.NewRequest("GET", ts.URL, nil)
 	res, err := tr.RoundTrip(req)
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer res.Body.Close()
 	<-donec
-	st.ts.Config.Close()
+	ts.Config.Close()
 	<-donec
 }
 
diff --git a/http2/transport_test.go b/http2/transport_test.go
index 927f799..7c53f7b 100644
--- a/http2/transport_test.go
+++ b/http2/transport_test.go
@@ -220,15 +220,14 @@
 
 func TestTransport(t *testing.T) {
 	const body = "sup"
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		io.WriteString(w, body)
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
-	u, err := url.Parse(st.ts.URL)
+	u, err := url.Parse(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -275,26 +274,27 @@
 }
 
 func testTransportReusesConns(t *testing.T, useClient, wantSame bool, modReq func(*http.Request)) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		io.WriteString(w, r.RemoteAddr)
-	}, optOnlyServer, func(c net.Conn, st http.ConnState) {
-		t.Logf("conn %v is now state %v", c.RemoteAddr(), st)
+	}, func(ts *httptest.Server) {
+		ts.Config.ConnState = func(c net.Conn, st http.ConnState) {
+			t.Logf("conn %v is now state %v", c.RemoteAddr(), st)
+		}
 	})
-	defer st.Close()
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	if useClient {
 		tr.ConnPool = noDialClientConnPool{new(clientConnPool)}
 	}
 	defer tr.CloseIdleConnections()
 	get := func() string {
-		req, err := http.NewRequest("GET", st.ts.URL, nil)
+		req, err := http.NewRequest("GET", ts.URL, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
 		modReq(req)
 		var res *http.Response
 		if useClient {
-			c := st.ts.Client()
+			c := ts.Client()
 			ConfigureTransports(c.Transport.(*http.Transport))
 			res, err = c.Do(req)
 		} else {
@@ -358,15 +358,12 @@
 func TestTransportGetGotConnHooks_Client(t *testing.T) { testTransportGetGotConnHooks(t, true) }
 
 func testTransportGetGotConnHooks(t *testing.T, useClient bool) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		io.WriteString(w, r.RemoteAddr)
-	}, func(s *httptest.Server) {
-		s.EnableHTTP2 = true
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
-	client := st.ts.Client()
+	client := ts.Client()
 	ConfigureTransports(client.Transport.(*http.Transport))
 
 	var (
@@ -389,7 +386,7 @@
 				}
 			},
 		}
-		req, err := http.NewRequest("GET", st.ts.URL, nil)
+		req, err := http.NewRequest("GET", ts.URL, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -432,9 +429,8 @@
 // Tests that the Transport only keeps one pending dial open per destination address.
 // https://golang.org/issue/13397
 func TestTransportGroupsPendingDials(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
-	}, optOnlyServer)
-	defer st.Close()
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
+	})
 	var (
 		mu         sync.Mutex
 		dialCount  int
@@ -463,7 +459,7 @@
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
-			req, err := http.NewRequest("GET", st.ts.URL, nil)
+			req, err := http.NewRequest("GET", ts.URL, nil)
 			if err != nil {
 				t.Error(err)
 				return
@@ -500,21 +496,19 @@
 
 func TestTransportAbortClosesPipes(t *testing.T) {
 	shutdown := make(chan struct{})
-	st := newServerTester(t,
+	ts := newTestServer(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
 
 	errCh := make(chan error)
 	go func() {
 		defer close(errCh)
 		tr := &Transport{TLSClientConfig: tlsConfigInsecure}
-		req, err := http.NewRequest("GET", st.ts.URL, nil)
+		req, err := http.NewRequest("GET", ts.URL, nil)
 		if err != nil {
 			errCh <- err
 			return
@@ -525,7 +519,7 @@
 			return
 		}
 		defer res.Body.Close()
-		st.closeConn()
+		ts.CloseClientConnections()
 		_, err = ioutil.ReadAll(res.Body)
 		if err == nil {
 			errCh <- errors.New("expected error from res.Body.Read")
@@ -548,13 +542,11 @@
 // could be a table-driven test with extra goodies.
 func TestTransportPath(t *testing.T) {
 	gotc := make(chan *url.URL, 1)
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {
 			gotc <- r.URL
 		},
-		optOnlyServer,
 	)
-	defer st.Close()
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
@@ -562,7 +554,7 @@
 		path  = "/testpath"
 		query = "q=1"
 	)
-	surl := st.ts.URL + path + "?" + query
+	surl := ts.URL + path + "?" + query
 	req, err := http.NewRequest("POST", surl, nil)
 	if err != nil {
 		t.Fatal(err)
@@ -656,7 +648,7 @@
 		err   error
 	}
 	gotc := make(chan reqInfo, 1)
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {
 			slurp, err := ioutil.ReadAll(r.Body)
 			if err != nil {
@@ -665,9 +657,7 @@
 				gotc <- reqInfo{req: r, slurp: slurp}
 			}
 		},
-		optOnlyServer,
 	)
-	defer st.Close()
 
 	for i, tt := range bodyTests {
 		tr := &Transport{TLSClientConfig: tlsConfigInsecure}
@@ -677,7 +667,7 @@
 		if tt.noContentLen {
 			body = struct{ io.Reader }{body} // just a Reader, hiding concrete type and other methods
 		}
-		req, err := http.NewRequest("POST", st.ts.URL, body)
+		req, err := http.NewRequest("POST", ts.URL, body)
 		if err != nil {
 			t.Fatalf("#%d: %v", i, err)
 		}
@@ -717,15 +707,13 @@
 	var mu sync.Mutex // guards following
 	var gotReq, didDial bool
 
-	ts := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {
 			mu.Lock()
 			gotReq = true
 			mu.Unlock()
 		},
-		optOnlyServer,
 	)
-	defer ts.Close()
 	tr := &Transport{
 		DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
 			mu.Lock()
@@ -741,7 +729,7 @@
 	}
 	defer tr.CloseIdleConnections()
 	client := &http.Client{Transport: tr}
-	res, err := client.Get(ts.ts.URL)
+	res, err := client.Get(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -776,14 +764,13 @@
 	}
 
 	// And does it work?
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		io.WriteString(w, r.Proto)
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	t1.TLSClientConfig.InsecureSkipVerify = true
 	c := &http.Client{Transport: t1}
-	res, err := c.Get(st.ts.URL)
+	res, err := c.Get(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -902,20 +889,19 @@
 
 // See golang.org/issue/13444
 func TestTransportFullDuplex(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(200) // redundant but for clarity
 		w.(http.Flusher).Flush()
 		io.Copy(flushWriter{w}, capitalizeReader{r.Body})
 		fmt.Fprintf(w, "bye.\n")
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 	c := &http.Client{Transport: tr}
 
 	pr, pw := io.Pipe()
-	req, err := http.NewRequest("PUT", st.ts.URL, ioutil.NopCloser(pr))
+	req, err := http.NewRequest("PUT", ts.URL, ioutil.NopCloser(pr))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -953,12 +939,11 @@
 
 func TestTransportConnectRequest(t *testing.T) {
 	gotc := make(chan *http.Request, 1)
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		gotc <- r
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
-	u, err := url.Parse(st.ts.URL)
+	u, err := url.Parse(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1413,7 +1398,7 @@
 }
 
 func TestTransportChecksRequestHeaderListSize(t *testing.T) {
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {
 			// Consume body & force client to send
 			// trailers before writing response.
@@ -1427,10 +1412,8 @@
 		func(ts *httptest.Server) {
 			ts.Config.MaxHeaderBytes = 16 << 10
 		},
-		optOnlyServer,
 		optQuiet,
 	)
-	defer st.Close()
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
@@ -1438,7 +1421,7 @@
 	checkRoundTrip := func(req *http.Request, wantErr error, desc string) {
 		// Make an arbitrary request to ensure we get the server's
 		// settings frame and initialize peerMaxHeaderListSize.
-		req0, err := http.NewRequest("GET", st.ts.URL, nil)
+		req0, err := http.NewRequest("GET", ts.URL, nil)
 		if err != nil {
 			t.Fatalf("newRequest: NewRequest: %v", err)
 		}
@@ -1501,13 +1484,29 @@
 	newRequest := func() *http.Request {
 		// Body must be non-nil to enable writing trailers.
 		body := strings.NewReader("hello")
-		req, err := http.NewRequest("POST", st.ts.URL, body)
+		req, err := http.NewRequest("POST", ts.URL, body)
 		if err != nil {
 			t.Fatalf("newRequest: NewRequest: %v", err)
 		}
 		return req
 	}
 
+	var (
+		scMu sync.Mutex
+		sc   *serverConn
+	)
+	testHookGetServerConn = func(v *serverConn) {
+		scMu.Lock()
+		defer scMu.Unlock()
+		if sc != nil {
+			panic("testHookGetServerConn called multiple times")
+		}
+		sc = v
+	}
+	defer func() {
+		testHookGetServerConn = nil
+	}()
+
 	// Validate peerMaxHeaderListSize.
 	req := newRequest()
 	checkRoundTrip(req, nil, "Initial request")
@@ -1519,16 +1518,16 @@
 	cc.mu.Lock()
 	peerSize := cc.peerMaxHeaderListSize
 	cc.mu.Unlock()
-	st.scMu.Lock()
-	wantSize := uint64(st.sc.maxHeaderListSize())
-	st.scMu.Unlock()
+	scMu.Lock()
+	wantSize := uint64(sc.maxHeaderListSize())
+	scMu.Unlock()
 	if peerSize != wantSize {
 		t.Errorf("peerMaxHeaderListSize = %v; want %v", peerSize, wantSize)
 	}
 
 	// Sanity check peerSize. (*serverConn) maxHeaderListSize adds
 	// 320 bytes of padding.
-	wantHeaderBytes := uint64(st.ts.Config.MaxHeaderBytes) + 320
+	wantHeaderBytes := uint64(ts.Config.MaxHeaderBytes) + 320
 	if peerSize != wantHeaderBytes {
 		t.Errorf("peerMaxHeaderListSize = %v; want %v.", peerSize, wantHeaderBytes)
 	}
@@ -1653,22 +1652,20 @@
 // a stream error, but others like cancel should be similar)
 func TestTransportBodyReadErrorType(t *testing.T) {
 	doPanic := make(chan bool, 1)
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {
 			w.(http.Flusher).Flush() // force headers out
 			<-doPanic
 			panic("boom")
 		},
-		optOnlyServer,
 		optQuiet,
 	)
-	defer st.Close()
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 	c := &http.Client{Transport: tr}
 
-	res, err := c.Get(st.ts.URL)
+	res, err := c.Get(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1692,7 +1689,7 @@
 		conn net.Conn // to close if set
 	)
 
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {
 			mu.Lock()
 			defer mu.Unlock()
@@ -1700,9 +1697,7 @@
 				conn.Close()
 			}
 		},
-		optOnlyServer,
 	)
-	defer st.Close()
 
 	tr := &Transport{
 		TLSClientConfig: tlsConfigInsecure,
@@ -1719,20 +1714,18 @@
 	}
 	defer tr.CloseIdleConnections()
 	c := &http.Client{Transport: tr}
-	c.Get(st.ts.URL)
+	c.Get(ts.URL)
 }
 
 // Test that the http1 Transport.DisableKeepAlives option is respected
 // and connections are closed as soon as idle.
 // See golang.org/issue/14008
 func TestTransportDisableKeepAlives(t *testing.T) {
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {
 			io.WriteString(w, "hi")
 		},
-		optOnlyServer,
 	)
-	defer st.Close()
 
 	connClosed := make(chan struct{}) // closed on tls.Conn.Close
 	tr := &Transport{
@@ -1749,7 +1742,7 @@
 		},
 	}
 	c := &http.Client{Transport: tr}
-	res, err := c.Get(st.ts.URL)
+	res, err := c.Get(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1770,14 +1763,12 @@
 // but when things are totally idle, it still needs to close.
 func TestTransportDisableKeepAlives_Concurrency(t *testing.T) {
 	const D = 25 * time.Millisecond
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {
 			time.Sleep(D)
 			io.WriteString(w, "hi")
 		},
-		optOnlyServer,
 	)
-	defer st.Close()
 
 	var dials int32
 	var conns sync.WaitGroup
@@ -1812,7 +1803,7 @@
 		}
 		go func() {
 			defer reqs.Done()
-			res, err := c.Get(st.ts.URL)
+			res, err := c.Get(ts.URL)
 			if err != nil {
 				t.Error(err)
 				return
@@ -1908,15 +1899,14 @@
 
 func TestTransportDisableCompression(t *testing.T) {
 	const body = "sup"
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		want := http.Header{
 			"User-Agent": []string{"Go-http-client/2.0"},
 		}
 		if !reflect.DeepEqual(r.Header, want) {
 			t.Errorf("request headers = %v; want %v", r.Header, want)
 		}
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{
 		TLSClientConfig: tlsConfigInsecure,
@@ -1926,7 +1916,7 @@
 	}
 	defer tr.CloseIdleConnections()
 
-	req, err := http.NewRequest("GET", st.ts.URL, nil)
+	req, err := http.NewRequest("GET", ts.URL, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1939,15 +1929,14 @@
 
 // RFC 7540 section 8.1.2.2
 func TestTransportRejectsConnHeaders(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		var got []string
 		for k := range r.Header {
 			got = append(got, k)
 		}
 		sort.Strings(got)
 		w.Header().Set("Got-Header", strings.Join(got, ","))
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
@@ -2035,7 +2024,7 @@
 	}
 
 	for _, tt := range tests {
-		req, _ := http.NewRequest("GET", st.ts.URL, nil)
+		req, _ := http.NewRequest("GET", ts.URL, nil)
 		req.Header[tt.key] = tt.value
 		res, err := tr.RoundTrip(req)
 		var got string
@@ -2089,14 +2078,13 @@
 	for _, tt := range tests {
 		tt := tt
 		t.Run(tt.name, func(t *testing.T) {
-			st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+			ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 				w.Header().Set("Content-Length", tt.cl[0])
-			}, optOnlyServer)
-			defer st.Close()
+			})
 			tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 			defer tr.CloseIdleConnections()
 
-			req, _ := http.NewRequest("HEAD", st.ts.URL, nil)
+			req, _ := http.NewRequest("HEAD", ts.URL, nil)
 			res, err := tr.RoundTrip(req)
 
 			var got string
@@ -2117,15 +2105,14 @@
 // golang.org/issue/14048
 // golang.org/issue/64766
 func TestTransportFailsOnInvalidHeadersAndTrailers(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		var got []string
 		for k := range r.Header {
 			got = append(got, k)
 		}
 		sort.Strings(got)
 		w.Header().Set("Got-Header", strings.Join(got, ","))
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tests := [...]struct {
 		h       http.Header
@@ -2162,7 +2149,7 @@
 	defer tr.CloseIdleConnections()
 
 	for i, tt := range tests {
-		req, _ := http.NewRequest("GET", st.ts.URL, nil)
+		req, _ := http.NewRequest("GET", ts.URL, nil)
 		req.Header = tt.h
 		req.Trailer = tt.t
 		res, err := tr.RoundTrip(req)
@@ -2372,11 +2359,10 @@
 // runs out of flow control tokens)
 func TestTransportHandlerBodyClose(t *testing.T) {
 	const bodySize = 10 << 20
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		r.Body.Close()
 		io.Copy(w, io.LimitReader(neverEnding('A'), bodySize))
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
@@ -2385,7 +2371,7 @@
 
 	const numReq = 10
 	for i := 0; i < numReq; i++ {
-		req, err := http.NewRequest("POST", st.ts.URL, struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)})
+		req, err := http.NewRequest("POST", ts.URL, struct{ io.Reader }{io.LimitReader(neverEnding('A'), bodySize)})
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -2418,7 +2404,7 @@
 	}
 
 	var wrote int64 // updated atomically
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		b := make([]byte, bufLen)
 		for wrote < total {
 			n, err := w.Write(b)
@@ -2429,11 +2415,11 @@
 			}
 			w.(http.Flusher).Flush()
 		}
-	}, optOnlyServer)
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
-	req, err := http.NewRequest("GET", st.ts.URL, nil)
+	req, err := http.NewRequest("GET", ts.URL, nil)
 	if err != nil {
 		t.Fatal("NewRequest error:", err)
 	}
@@ -2755,16 +2741,15 @@
 // which returns (non-0, io.EOF) and also needs to set the ContentLength
 // explicitly.
 func TestTransportBodyDoubleEndStream(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		// Nothing.
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
 	for i := 0; i < 2; i++ {
-		req, _ := http.NewRequest("POST", st.ts.URL, byteAndEOFReader('a'))
+		req, _ := http.NewRequest("POST", ts.URL, byteAndEOFReader('a'))
 		req.ContentLength = 1
 		res, err := tr.RoundTrip(req)
 		if err != nil {
@@ -2926,12 +2911,11 @@
 }
 
 func TestClientConnPing(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}, optOnlyServer)
-	defer st.Close()
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {})
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 	ctx := context.Background()
-	cc, err := tr.dialClientConn(ctx, st.ts.Listener.Addr().String(), false)
+	cc, err := tr.dialClientConn(ctx, ts.Listener.Addr().String(), false)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -2949,7 +2933,7 @@
 	clientGotResponse := make(chan bool, 1)
 
 	const msg = "Hello."
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		if strings.Contains(r.URL.Path, "/hello") {
 			time.Sleep(50 * time.Millisecond)
 			io.WriteString(w, msg)
@@ -2964,14 +2948,13 @@
 			}
 			time.Sleep(10 * time.Millisecond)
 		}
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
 	c := &http.Client{Transport: tr}
-	req, _ := http.NewRequest("GET", st.ts.URL, nil)
+	req, _ := http.NewRequest("GET", ts.URL, nil)
 	req.Cancel = cancel
 	res, err := c.Do(req)
 	clientGotResponse <- true
@@ -2982,7 +2965,7 @@
 		t.Fatal("unexpected success")
 	}
 
-	res, err = c.Get(st.ts.URL + "/hello")
+	res, err = c.Get(ts.URL + "/hello")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -2998,16 +2981,15 @@
 // Issue 21316: It should be safe to reuse an http.Request after the
 // request has completed.
 func TestTransportNoRaceOnRequestObjectAfterRequestComplete(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(200)
 		io.WriteString(w, "body")
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
-	req, _ := http.NewRequest("GET", st.ts.URL, nil)
+	req, _ := http.NewRequest("GET", ts.URL, nil)
 	resp, err := tr.RoundTrip(req)
 	if err != nil {
 		t.Fatal(err)
@@ -3045,11 +3027,9 @@
 }
 
 func TestTransportPingWriteBlocks(t *testing.T) {
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {},
-		optOnlyServer,
 	)
-	defer st.Close()
 	tr := &Transport{
 		TLSClientConfig: tlsConfigInsecure,
 		DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
@@ -3068,7 +3048,7 @@
 	}
 	defer tr.CloseIdleConnections()
 	c := &http.Client{Transport: tr}
-	_, err := c.Get(st.ts.URL)
+	_, err := c.Get(ts.URL)
 	if err == nil {
 		t.Fatalf("Get = nil, want error")
 	}
@@ -3419,11 +3399,10 @@
 }
 
 func TestTransportRequestsLowServerLimit(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
-	}, optOnlyServer, func(s *Server) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
+	}, func(s *Server) {
 		s.MaxConcurrentStreams = 1
 	})
-	defer st.Close()
 
 	var (
 		connCountMu sync.Mutex
@@ -3442,7 +3421,7 @@
 
 	const reqCount = 3
 	for i := 0; i < reqCount; i++ {
-		req, err := http.NewRequest("GET", st.ts.URL, nil)
+		req, err := http.NewRequest("GET", ts.URL, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -3609,7 +3588,7 @@
 
 	writeErr := make(chan error, 1)
 
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.(http.Flusher).Flush()
 		var sum int64
 		for i := 0; i < 100; i++ {
@@ -3622,13 +3601,12 @@
 		}
 		t.Logf("wrote all %d bytes", sum)
 		writeErr <- nil
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 	c := &http.Client{Transport: tr}
-	res, err := c.Get(st.ts.URL)
+	res, err := c.Get(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -3682,22 +3660,20 @@
 func benchSimpleRoundTrip(b *testing.B, nReqHeaders, nResHeader int) {
 	defer disableGoroutineTracking()()
 	b.ReportAllocs()
-	st := newServerTester(b,
+	ts := newTestServer(b,
 		func(w http.ResponseWriter, r *http.Request) {
 			for i := 0; i < nResHeader; i++ {
 				name := fmt.Sprint("A-", i)
 				w.Header().Set(name, "*")
 			}
 		},
-		optOnlyServer,
 		optQuiet,
 	)
-	defer st.Close()
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
-	req, err := http.NewRequest("GET", st.ts.URL, nil)
+	req, err := http.NewRequest("GET", ts.URL, nil)
 	if err != nil {
 		b.Fatal(err)
 	}
@@ -3733,16 +3709,15 @@
 // Issue 20521: it is not an error to receive a response and end stream
 // from the server without the body being consumed.
 func TestTransportResponseAndResetWithoutConsumingBodyRace(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusOK)
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
 	// The request body needs to be big enough to trigger flow control.
-	req, _ := http.NewRequest("PUT", st.ts.URL, infiniteReader{})
+	req, _ := http.NewRequest("PUT", ts.URL, infiniteReader{})
 	res, err := tr.RoundTrip(req)
 	if err != nil {
 		t.Fatal(err)
@@ -3873,7 +3848,7 @@
 	closeDone := make(chan struct{})
 	beforeHeader := func() {}
 	bodyWrite := func(w http.ResponseWriter) {}
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		defer close(handlerDone)
 		beforeHeader()
 		w.WriteHeader(http.StatusOK)
@@ -3890,13 +3865,12 @@
 				t.Error("expected connection closed by client")
 			}
 		}
-	}, optOnlyServer)
-	defer st.Close()
+	})
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 	ctx := context.Background()
-	cc, err := tr.dialClientConn(ctx, st.ts.Listener.Addr().String(), false)
-	req, err := http.NewRequest("GET", st.ts.URL, nil)
+	cc, err := tr.dialClientConn(ctx, ts.Listener.Addr().String(), false)
+	req, err := http.NewRequest("GET", ts.URL, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -4217,15 +4191,14 @@
 }
 
 func testTransportBodyLargerThanSpecifiedContentLength(t *testing.T, body *chunkReader, contentLen int64) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		r.Body.Read(make([]byte, 6))
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
-	req, _ := http.NewRequest("POST", st.ts.URL, body)
+	req, _ := http.NewRequest("POST", ts.URL, body)
 	req.ContentLength = contentLen
 	_, err := tr.RoundTrip(req)
 	if err != errReqBodyTooLong {
@@ -4305,13 +4278,12 @@
 	if err != nil {
 		t.Fatal(err)
 	}
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {}, optOnlyServer)
-	defer st.Close()
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 	ctx := context.Background()
-	cc, err := tr.dialClientConn(ctx, st.ts.Listener.Addr().String(), false)
+	cc, err := tr.dialClientConn(ctx, ts.Listener.Addr().String(), false)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -4338,12 +4310,11 @@
 // already. If the request body has started to be sent, one must wait until it
 // is completed.
 func TestTransportBodyRewindRace(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Connection", "close")
 		w.WriteHeader(http.StatusOK)
 		return
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &http.Transport{
 		TLSClientConfig: tlsConfigInsecure,
@@ -4362,7 +4333,7 @@
 	var wg sync.WaitGroup
 	wg.Add(clients)
 	for i := 0; i < clients; i++ {
-		req, err := http.NewRequest("POST", st.ts.URL, bytes.NewBufferString("abcdef"))
+		req, err := http.NewRequest("POST", ts.URL, bytes.NewBufferString("abcdef"))
 		if err != nil {
 			t.Fatalf("unexpect new request error: %v", err)
 		}
@@ -4382,11 +4353,10 @@
 // Issue 42498: A request with a body will never be sent if the stream is
 // reset prior to sending any data.
 func TestTransportServerResetStreamAtHeaders(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(http.StatusUnauthorized)
 		return
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &http.Transport{
 		TLSClientConfig:       tlsConfigInsecure,
@@ -4402,7 +4372,7 @@
 		Transport: tr,
 	}
 
-	req, err := http.NewRequest("POST", st.ts.URL, errorReader{io.EOF})
+	req, err := http.NewRequest("POST", ts.URL, errorReader{io.EOF})
 	if err != nil {
 		t.Fatalf("unexpect new request error: %v", err)
 	}
@@ -4430,15 +4400,14 @@
 }
 
 func TestTransportExpectContinue(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		switch r.URL.Path {
 		case "/reject":
 			w.WriteHeader(403)
 		default:
 			io.Copy(io.Discard, r.Body)
 		}
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &http.Transport{
 		TLSClientConfig:       tlsConfigInsecure,
@@ -4481,7 +4450,7 @@
 		t.Run(tc.Name, func(t *testing.T) {
 			startTime := time.Now()
 
-			req, err := http.NewRequest("POST", st.ts.URL+tc.Path, tc.Body)
+			req, err := http.NewRequest("POST", ts.URL+tc.Path, tc.Body)
 			if err != nil {
 				t.Fatal(err)
 			}
@@ -4593,7 +4562,7 @@
 func TestTransportFrameBufferReuse(t *testing.T) {
 	filler := hex.EncodeToString([]byte(randString(2048)))
 
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		if got, want := r.Header.Get("Big"), filler; got != want {
 			t.Errorf(`r.Header.Get("Big") = %q, want %q`, got, want)
 		}
@@ -4607,8 +4576,7 @@
 		if got, want := r.Trailer.Get("Big"), filler; got != want {
 			t.Errorf(`r.Trailer.Get("Big") = %q, want %q`, got, want)
 		}
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
@@ -4619,7 +4587,7 @@
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
-			req, err := http.NewRequest("POST", st.ts.URL, strings.NewReader(filler))
+			req, err := http.NewRequest("POST", ts.URL, strings.NewReader(filler))
 			if err != nil {
 				t.Error(err)
 				return
@@ -4685,7 +4653,7 @@
 	}} {
 		test := test
 		t.Run(test.name, func(t *testing.T) {
-			st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+			ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 				if v := r.Header.Get("Big"); v != "" && v != filler {
 					t.Errorf("request header mismatch")
 				}
@@ -4695,10 +4663,9 @@
 				if v := r.Trailer.Get("Big"); v != "" && v != filler {
 					t.Errorf("request trailer mismatch\ngot:  %q\nwant: %q", string(v), filler)
 				}
-			}, optOnlyServer, func(s *Server) {
+			}, func(s *Server) {
 				s.MaxConcurrentStreams = 1
 			})
-			defer st.Close()
 
 			// This Transport creates connections that block on writes after 1024 bytes.
 			connc := make(chan *blockingWriteConn, 1)
@@ -4720,7 +4687,7 @@
 
 			// Request 1: A small request to ensure we read the server MaxConcurrentStreams.
 			{
-				req, err := http.NewRequest("POST", st.ts.URL, nil)
+				req, err := http.NewRequest("POST", ts.URL, nil)
 				if err != nil {
 					t.Fatal(err)
 				}
@@ -4740,7 +4707,7 @@
 			reqc := make(chan struct{})
 			go func() {
 				defer close(reqc)
-				req, err := test.req(st.ts.URL)
+				req, err := test.req(ts.URL)
 				if err != nil {
 					t.Error(err)
 					return
@@ -4756,7 +4723,7 @@
 			// Request 3: A small request that is sent on a new connection, since request 2
 			// is hogging the only available stream on the previous connection.
 			{
-				req, err := http.NewRequest("POST", st.ts.URL, nil)
+				req, err := http.NewRequest("POST", ts.URL, nil)
 				if err != nil {
 					t.Fatal(err)
 				}
@@ -4791,15 +4758,14 @@
 
 func TestTransportCloseRequestBody(t *testing.T) {
 	var statusCode int
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(statusCode)
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 	ctx := context.Background()
-	cc, err := tr.dialClientConn(ctx, st.ts.Listener.Addr().String(), false)
+	cc, err := tr.dialClientConn(ctx, ts.Listener.Addr().String(), false)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -4976,10 +4942,9 @@
 
 func TestTransportContentLengthWithoutBody(t *testing.T) {
 	contentLength := ""
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set("Content-Length", contentLength)
-	}, optOnlyServer)
-	defer st.Close()
+	})
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
@@ -5006,7 +4971,7 @@
 		t.Run(test.name, func(t *testing.T) {
 			contentLength = test.contentLength
 
-			req, _ := http.NewRequest("GET", st.ts.URL, nil)
+			req, _ := http.NewRequest("GET", ts.URL, nil)
 			res, err := tr.RoundTrip(req)
 			if err != nil {
 				t.Fatal(err)
@@ -5028,18 +4993,17 @@
 }
 
 func TestTransportCloseResponseBodyWhileRequestBodyHangs(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(200)
 		w.(http.Flusher).Flush()
 		io.Copy(io.Discard, r.Body)
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
 	pr, pw := net.Pipe()
-	req, err := http.NewRequest("GET", st.ts.URL, pr)
+	req, err := http.NewRequest("GET", ts.URL, pr)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -5055,19 +5019,18 @@
 func TestTransport300ResponseBody(t *testing.T) {
 	reqc := make(chan struct{})
 	body := []byte("response body")
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
 		w.WriteHeader(300)
 		w.(http.Flusher).Flush()
 		<-reqc
 		w.Write(body)
-	}, optOnlyServer)
-	defer st.Close()
+	})
 
 	tr := &Transport{TLSClientConfig: tlsConfigInsecure}
 	defer tr.CloseIdleConnections()
 
 	pr, pw := net.Pipe()
-	req, err := http.NewRequest("GET", st.ts.URL, pr)
+	req, err := http.NewRequest("GET", ts.URL, pr)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -5088,11 +5051,9 @@
 }
 
 func TestTransportWriteByteTimeout(t *testing.T) {
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {},
-		optOnlyServer,
 	)
-	defer st.Close()
 	tr := &Transport{
 		TLSClientConfig: tlsConfigInsecure,
 		DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
@@ -5104,7 +5065,7 @@
 	defer tr.CloseIdleConnections()
 	c := &http.Client{Transport: tr}
 
-	_, err := c.Get(st.ts.URL)
+	_, err := c.Get(ts.URL)
 	if !errors.Is(err, os.ErrDeadlineExceeded) {
 		t.Fatalf("Get on unresponsive connection: got %q; want ErrDeadlineExceeded", err)
 	}
@@ -5132,11 +5093,9 @@
 }
 
 func TestTransportSlowWrites(t *testing.T) {
-	st := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {},
-		optOnlyServer,
 	)
-	defer st.Close()
 	tr := &Transport{
 		TLSClientConfig: tlsConfigInsecure,
 		DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
@@ -5150,7 +5109,7 @@
 	c := &http.Client{Transport: tr}
 
 	const bodySize = 1 << 20
-	resp, err := c.Post(st.ts.URL, "text/foo", io.LimitReader(neverEnding('A'), bodySize))
+	resp, err := c.Post(ts.URL, "text/foo", io.LimitReader(neverEnding('A'), bodySize))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -5218,11 +5177,10 @@
 }
 
 func TestTransportSlowClose(t *testing.T) {
-	st := newServerTester(t, func(w http.ResponseWriter, r *http.Request) {
-	}, optOnlyServer)
-	defer st.Close()
+	ts := newTestServer(t, func(w http.ResponseWriter, r *http.Request) {
+	})
 
-	client := st.ts.Client()
+	client := ts.Client()
 	body := &slowCloser{
 		closing: make(chan struct{}),
 		closed:  make(chan struct{}),
@@ -5231,7 +5189,7 @@
 	reqc := make(chan struct{})
 	go func() {
 		defer close(reqc)
-		res, err := client.Post(st.ts.URL, "text/plain", body)
+		res, err := client.Post(ts.URL, "text/plain", body)
 		if err != nil {
 			t.Error(err)
 		}
@@ -5244,7 +5202,7 @@
 
 	<-body.closing // wait for POST request to call body.Close
 	// This GET request should not be blocked by the in-progress POST.
-	res, err := client.Get(st.ts.URL)
+	res, err := client.Get(ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -5260,12 +5218,10 @@
 			ClientAuth: tls.RequestClientCert,
 		}
 	}
-	ts := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {},
-		optOnlyServer,
 		serverTLSConfigFunc,
 	)
-	defer ts.Close()
 	tr := &Transport{
 		TLSClientConfig: &tls.Config{
 			GetClientCertificate: func(cri *tls.CertificateRequestInfo) (*tls.Certificate, error) {
@@ -5279,7 +5235,7 @@
 		},
 	}
 	defer tr.CloseIdleConnections()
-	req, err := http.NewRequest(http.MethodGet, ts.ts.URL, nil)
+	req, err := http.NewRequest(http.MethodGet, ts.URL, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -5324,12 +5280,10 @@
 			ClientAuth: tls.RequestClientCert,
 		}
 	}
-	ts := newServerTester(t,
+	ts := newTestServer(t,
 		func(w http.ResponseWriter, r *http.Request) {},
-		optOnlyServer,
 		serverTLSConfigFunc,
 	)
-	defer ts.Close()
 	tr := &Transport{
 		TLSClientConfig: &tls.Config{
 			GetClientCertificate: func(cri *tls.CertificateRequestInfo) (*tls.Certificate, error) {
@@ -5347,7 +5301,7 @@
 		},
 	}
 	defer tr.CloseIdleConnections()
-	req, err := http.NewRequest(http.MethodGet, ts.ts.URL, nil)
+	req, err := http.NewRequest(http.MethodGet, ts.URL, nil)
 	if err != nil {
 		t.Fatal(err)
 	}