]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: add tests with zero and negative read/write timeouts
authorAndy Pan <panjf2000@gmail.com>
Sun, 10 Mar 2024 15:08:31 +0000 (23:08 +0800)
committerGopher Robot <gobot@golang.org>
Thu, 21 Mar 2024 09:16:08 +0000 (09:16 +0000)
Change-Id: I38ebd280c200b30692eb35640327034a5e898bd0
Reviewed-on: https://go-review.googlesource.com/c/go/+/570376
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/net/http/serve_test.go

index 1012e44b688fa694ae5938417dd5e61766cc34d2..8998f38367e7deaf4d8fe16e2063553a0dae4d3a 100644 (file)
@@ -792,6 +792,51 @@ func testServerReadTimeout(t *testing.T, mode testMode) {
        }
 }
 
+func TestServerNoReadTimeout(t *testing.T) { run(t, testServerNoReadTimeout) }
+func testServerNoReadTimeout(t *testing.T, mode testMode) {
+       reqBody := "Hello, Gophers!"
+       resBody := "Hi, Gophers!"
+       for _, timeout := range []time.Duration{0, -1} {
+               cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {
+                       ctl := NewResponseController(res)
+                       ctl.EnableFullDuplex()
+                       res.WriteHeader(StatusOK)
+                       // Flush the headers before processing the request body
+                       // to unblock the client from the RoundTrip.
+                       if err := ctl.Flush(); err != nil {
+                               t.Errorf("server flush response: %v", err)
+                               return
+                       }
+                       got, err := io.ReadAll(req.Body)
+                       if string(got) != reqBody || err != nil {
+                               t.Errorf("server read request body: %v; got %q, want %q", err, got, reqBody)
+                       }
+                       res.Write([]byte(resBody))
+               }), func(ts *httptest.Server) {
+                       ts.Config.ReadTimeout = timeout
+                       ts.Config.IdleTimeout = 10 * time.Millisecond
+                       t.Logf("Server.Config.ReadTimeout = %d", timeout)
+               })
+
+               pr, pw := io.Pipe()
+               res, err := cst.c.Post(cst.ts.URL, "text/plain", pr)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               defer res.Body.Close()
+
+               // TODO(panjf2000): sleep is not so robust, maybe find a better way to test this?
+               time.Sleep(10 * time.Millisecond) // stall sending body to server to test server doesn't time out
+               pw.Write([]byte(reqBody))
+               pw.Close()
+
+               got, err := io.ReadAll(res.Body)
+               if string(got) != resBody || err != nil {
+                       t.Errorf("client read response body: %v; got %v, want %q", err, got, resBody)
+               }
+       }
+}
+
 func TestServerWriteTimeout(t *testing.T) { run(t, testServerWriteTimeout) }
 func testServerWriteTimeout(t *testing.T, mode testMode) {
        for timeout := 5 * time.Millisecond; ; timeout *= 2 {
@@ -857,6 +902,29 @@ func testServerWriteTimeout(t *testing.T, mode testMode) {
        }
 }
 
+func TestServerNoWriteTimeout(t *testing.T) { run(t, testServerNoWriteTimeout) }
+func testServerNoWriteTimeout(t *testing.T, mode testMode) {
+       for _, timeout := range []time.Duration{0, -1} {
+               cst := newClientServerTest(t, mode, HandlerFunc(func(res ResponseWriter, req *Request) {
+                       _, err := io.Copy(res, neverEnding('a'))
+                       t.Logf("server write response: %v", err)
+               }), func(ts *httptest.Server) {
+                       ts.Config.WriteTimeout = timeout
+                       t.Logf("Server.Config.WriteTimeout = %d", timeout)
+               })
+
+               res, err := cst.c.Get(cst.ts.URL)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               defer res.Body.Close()
+               n, err := io.CopyN(io.Discard, res.Body, 1<<20) // 1MB should be sufficient to prove the point
+               if n != 1<<20 || err != nil {
+                       t.Errorf("client read response body: %d, %v", n, err)
+               }
+       }
+}
+
 // Test that the HTTP/2 server handles Server.WriteTimeout (Issue 18437)
 func TestWriteDeadlineExtendedOnNewRequest(t *testing.T) {
        run(t, testWriteDeadlineExtendedOnNewRequest)