mirror of
https://github.com/golang/go
synced 2024-11-23 22:30:05 -07:00
net/http: add tests for http2 Server WriteTimeout enforcement per stream
Updates #18437 Change-Id: Iaa8a35d18eca8be24763dd151ad9e324ecbf7f7b Reviewed-on: https://go-review.googlesource.com/34726 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
99683483d6
commit
b599c1fe0d
@ -642,6 +642,131 @@ func TestHTTP2WriteDeadlineExtendedOnNewRequest(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// tryTimeouts runs testFunc with increasing timeouts. Test passes on first success,
|
||||
// and fails if all timeouts fail.
|
||||
func tryTimeouts(t *testing.T, testFunc func(timeout time.Duration) error) {
|
||||
tries := []time.Duration{250 * time.Millisecond, 500 * time.Millisecond, 1 * time.Second}
|
||||
for i, timeout := range tries {
|
||||
err := testFunc(timeout)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
t.Logf("failed at %v: %v", timeout, err)
|
||||
if i != len(tries)-1 {
|
||||
t.Logf("retrying at %v ...", tries[i+1])
|
||||
}
|
||||
}
|
||||
t.Fatal("all attempts failed")
|
||||
}
|
||||
|
||||
// Test that the HTTP/2 server RSTs stream on slow write.
|
||||
func TestHTTP2WriteDeadlineEnforcedPerStream(t *testing.T) {
|
||||
t.Skip("disabled until Issue 18437 is fixed")
|
||||
if testing.Short() {
|
||||
t.Skip("skipping in short mode")
|
||||
}
|
||||
setParallel(t)
|
||||
defer afterTest(t)
|
||||
tryTimeouts(t, testHTTP2WriteDeadlineEnforcedPerStream)
|
||||
}
|
||||
|
||||
func testHTTP2WriteDeadlineEnforcedPerStream(timeout time.Duration) error {
|
||||
reqNum := 0
|
||||
ts := httptest.NewUnstartedServer(HandlerFunc(func(res ResponseWriter, req *Request) {
|
||||
reqNum++
|
||||
if reqNum == 1 {
|
||||
return // first request succeeds
|
||||
}
|
||||
time.Sleep(timeout) // second request times out
|
||||
}))
|
||||
ts.Config.WriteTimeout = timeout / 2
|
||||
ts.TLS = &tls.Config{NextProtos: []string{"h2"}}
|
||||
ts.StartTLS()
|
||||
defer ts.Close()
|
||||
|
||||
c := ts.Client()
|
||||
if err := ExportHttp2ConfigureTransport(c.Transport.(*Transport)); err != nil {
|
||||
return fmt.Errorf("ExportHttp2ConfigureTransport: %v", err)
|
||||
}
|
||||
|
||||
req, err := NewRequest("GET", ts.URL, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("NewRequest: %v", err)
|
||||
}
|
||||
r, err := c.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("http2 Get #1: %v", err)
|
||||
}
|
||||
r.Body.Close()
|
||||
if r.ProtoMajor != 2 {
|
||||
return fmt.Errorf("http2 Get expected HTTP/2.0, got %q", r.Proto)
|
||||
}
|
||||
|
||||
req, err = NewRequest("GET", ts.URL, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("NewRequest: %v", err)
|
||||
}
|
||||
r, err = c.Do(req)
|
||||
if err == nil {
|
||||
r.Body.Close()
|
||||
if r.ProtoMajor != 2 {
|
||||
return fmt.Errorf("http2 Get expected HTTP/2.0, got %q", r.Proto)
|
||||
}
|
||||
return fmt.Errorf("http2 Get #2 expected error, got nil")
|
||||
}
|
||||
expected := "stream ID 3; INTERNAL_ERROR" // client IDs are odd, second stream should be 3
|
||||
if !strings.Contains(err.Error(), expected) {
|
||||
return fmt.Errorf("http2 Get #2: expected error to contain %q, got %q", expected, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Test that the HTTP/2 server does not send RST when WriteDeadline not set.
|
||||
func TestHTTP2NoWriteDeadline(t *testing.T) {
|
||||
t.Skip("disabled until Issue 18437 is fixed")
|
||||
if testing.Short() {
|
||||
t.Skip("skipping in short mode")
|
||||
}
|
||||
setParallel(t)
|
||||
defer afterTest(t)
|
||||
tryTimeouts(t, testHTTP2NoWriteDeadline)
|
||||
}
|
||||
|
||||
func testHTTP2NoWriteDeadline(timeout time.Duration) error {
|
||||
reqNum := 0
|
||||
ts := httptest.NewUnstartedServer(HandlerFunc(func(res ResponseWriter, req *Request) {
|
||||
reqNum++
|
||||
if reqNum == 1 {
|
||||
return // first request succeeds
|
||||
}
|
||||
time.Sleep(timeout) // second request timesout
|
||||
}))
|
||||
ts.TLS = &tls.Config{NextProtos: []string{"h2"}}
|
||||
ts.StartTLS()
|
||||
defer ts.Close()
|
||||
|
||||
c := ts.Client()
|
||||
if err := ExportHttp2ConfigureTransport(c.Transport.(*Transport)); err != nil {
|
||||
return fmt.Errorf("ExportHttp2ConfigureTransport: %v", err)
|
||||
}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
req, err := NewRequest("GET", ts.URL, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("NewRequest: %v", err)
|
||||
}
|
||||
r, err := c.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("http2 Get #%d: %v", i, err)
|
||||
}
|
||||
r.Body.Close()
|
||||
if r.ProtoMajor != 2 {
|
||||
return fmt.Errorf("http2 Get expected HTTP/2.0, got %q", r.Proto)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// golang.org/issue/4741 -- setting only a write timeout that triggers
|
||||
// shouldn't cause a handler to block forever on reads (next HTTP
|
||||
// request) that will never happen.
|
||||
|
Loading…
Reference in New Issue
Block a user