Skip to content

Commit 92bbecc

Browse files
committed
net/http: deflake TestRequestBodyLimit
This test can return with a Transport still processing an in-flight request, resulting in a test failure due to the leaked Transport. Avoid this by waiting for the Transport to close the request body before returning. Fixes #60264 Change-Id: I8d8b54f633c2e28da2b1bf1bc01ce09dd77769de Reviewed-on: https://go-review.googlesource.com/c/go/+/522695 Reviewed-by: Bryan Mills <[email protected]> Auto-Submit: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Damien Neil <[email protected]>
1 parent 611c3af commit 92bbecc

File tree

1 file changed

+38
-11
lines changed

1 file changed

+38
-11
lines changed

src/net/http/serve_test.go

+38-11
Original file line numberDiff line numberDiff line change
@@ -2967,15 +2967,36 @@ func (b neverEnding) Read(p []byte) (n int, err error) {
29672967
return len(p), nil
29682968
}
29692969

2970-
type countReader struct {
2971-
r io.Reader
2972-
n *int64
2970+
type bodyLimitReader struct {
2971+
mu sync.Mutex
2972+
count int
2973+
limit int
2974+
closed chan struct{}
29732975
}
29742976

2975-
func (cr countReader) Read(p []byte) (n int, err error) {
2976-
n, err = cr.r.Read(p)
2977-
atomic.AddInt64(cr.n, int64(n))
2978-
return
2977+
func (r *bodyLimitReader) Read(p []byte) (int, error) {
2978+
r.mu.Lock()
2979+
defer r.mu.Unlock()
2980+
select {
2981+
case <-r.closed:
2982+
return 0, errors.New("closed")
2983+
default:
2984+
}
2985+
if r.count > r.limit {
2986+
return 0, errors.New("at limit")
2987+
}
2988+
r.count += len(p)
2989+
for i := range p {
2990+
p[i] = 'a'
2991+
}
2992+
return len(p), nil
2993+
}
2994+
2995+
func (r *bodyLimitReader) Close() error {
2996+
r.mu.Lock()
2997+
defer r.mu.Unlock()
2998+
close(r.closed)
2999+
return nil
29793000
}
29803001

29813002
func TestRequestBodyLimit(t *testing.T) { run(t, testRequestBodyLimit) }
@@ -2999,8 +3020,11 @@ func testRequestBodyLimit(t *testing.T, mode testMode) {
29993020
}
30003021
}))
30013022

3002-
nWritten := new(int64)
3003-
req, _ := NewRequest("POST", cst.ts.URL, io.LimitReader(countReader{neverEnding('a'), nWritten}, limit*200))
3023+
body := &bodyLimitReader{
3024+
closed: make(chan struct{}),
3025+
limit: limit * 200,
3026+
}
3027+
req, _ := NewRequest("POST", cst.ts.URL, body)
30043028

30053029
// Send the POST, but don't care it succeeds or not. The
30063030
// remote side is going to reply and then close the TCP
@@ -3015,10 +3039,13 @@ func testRequestBodyLimit(t *testing.T, mode testMode) {
30153039
if err == nil {
30163040
resp.Body.Close()
30173041
}
3042+
// Wait for the Transport to finish writing the request body.
3043+
// It will close the body when done.
3044+
<-body.closed
30183045

3019-
if atomic.LoadInt64(nWritten) > limit*100 {
3046+
if body.count > limit*100 {
30203047
t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
3021-
limit, nWritten)
3048+
limit, body.count)
30223049
}
30233050
}
30243051

0 commit comments

Comments
 (0)