http2: speed up TestTransportRetryHasLimit

This test takes ~30s to execute with real timers, making it almost
50% of the total execution time of the http2 tests. Use a fake
timer in tests.

Change-Id: I750237c7d3b8f7b87881b8a0a8aff2bf4a3cdd9f
Reviewed-on: https://go-review.googlesource.com/c/net/+/446375
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/http2/transport.go b/http2/transport.go
index 5a179b6..46dda4d 100644
--- a/http2/transport.go
+++ b/http2/transport.go
@@ -502,6 +502,15 @@
 	return net.JoinHostPort(host, port)
 }
 
+var retryBackoffHook func(time.Duration) *time.Timer
+
+func backoffNewTimer(d time.Duration) *time.Timer {
+	if retryBackoffHook != nil {
+		return retryBackoffHook(d)
+	}
+	return time.NewTimer(d)
+}
+
 // RoundTripOpt is like RoundTrip, but takes options.
 func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
 	if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
@@ -527,11 +536,14 @@
 				}
 				backoff := float64(uint(1) << (uint(retry) - 1))
 				backoff += backoff * (0.1 * mathrand.Float64())
+				d := time.Second * time.Duration(backoff)
+				timer := backoffNewTimer(d)
 				select {
-				case <-time.After(time.Second * time.Duration(backoff)):
+				case <-timer.C:
 					t.vlogf("RoundTrip retrying after failure: %v", err)
 					continue
 				case <-req.Context().Done():
+					timer.Stop()
 					err = req.Context().Err()
 				}
 			}
diff --git a/http2/transport_test.go b/http2/transport_test.go
index c738911..9eaf7bf 100644
--- a/http2/transport_test.go
+++ b/http2/transport_test.go
@@ -3881,6 +3881,12 @@
 	if testing.Short() {
 		t.Skip("skipping long test in short mode")
 	}
+	retryBackoffHook = func(d time.Duration) *time.Timer {
+		return time.NewTimer(0) // fires immediately
+	}
+	defer func() {
+		retryBackoffHook = nil
+	}()
 	clientDone := make(chan struct{})
 	ct := newClientTester(t)
 	ct.client = func() error {