@@ -2915,3 +2915,58 @@ func TestAuthorityAddr(t *testing.T) {
2915
2915
}
2916
2916
}
2917
2917
}
2918
+
2919
+ // Issue 20448: stop allocating for DATA frames' payload after
2920
+ // Response.Body.Close is called.
2921
+ func TestTransportAllocationsAfterResponseBodyClose (t * testing.T ) {
2922
+ megabyteZero := make ([]byte , 1 << 20 )
2923
+
2924
+ writeErr := make (chan error , 1 )
2925
+
2926
+ st := newServerTester (t , func (w http.ResponseWriter , r * http.Request ) {
2927
+ w .(http.Flusher ).Flush ()
2928
+ var sum int64
2929
+ for i := 0 ; i < 100 ; i ++ {
2930
+ n , err := w .Write (megabyteZero )
2931
+ sum += int64 (n )
2932
+ if err != nil {
2933
+ writeErr <- err
2934
+ return
2935
+ }
2936
+ }
2937
+ t .Logf ("wrote all %d bytes" , sum )
2938
+ writeErr <- nil
2939
+ }, optOnlyServer )
2940
+ defer st .Close ()
2941
+
2942
+ tr := & Transport {TLSClientConfig : tlsConfigInsecure }
2943
+ defer tr .CloseIdleConnections ()
2944
+ c := & http.Client {Transport : tr }
2945
+ res , err := c .Get (st .ts .URL )
2946
+ if err != nil {
2947
+ t .Fatal (err )
2948
+ }
2949
+ var buf [1 ]byte
2950
+ if _ , err := res .Body .Read (buf [:]); err != nil {
2951
+ t .Error (err )
2952
+ }
2953
+ if err := res .Body .Close (); err != nil {
2954
+ t .Error (err )
2955
+ }
2956
+
2957
+ trb , ok := res .Body .(transportResponseBody )
2958
+ if ! ok {
2959
+ t .Fatalf ("res.Body = %T; want transportResponseBody" , res .Body )
2960
+ }
2961
+ if trb .cs .bufPipe .b != nil {
2962
+ // TODO(tombergan,bradfitz): turn this into an error:
2963
+ t .Logf ("response body pipe is still open" )
2964
+ }
2965
+
2966
+ gotErr := <- writeErr
2967
+ if gotErr == nil {
2968
+ t .Errorf ("Handler unexpectedly managed to write its entire response without getting an error" )
2969
+ } else if gotErr != errStreamClosed {
2970
+ t .Errorf ("Handler Write err = %v; want errStreamClosed" , gotErr )
2971
+ }
2972
+ }
0 commit comments