@@ -6290,10 +6290,11 @@ func TestTransportRejectsSignInContentLength(t *testing.T) {
6290
6290
// Test that a new request which uses the connection of an active request
6291
6291
// cannot cause it to be canceled as well.
6292
6292
func TestCancelRequestWhenSharingConnection (t * testing.T ) {
6293
- if testing .Short () {
6294
- t .Skip ("skipping in short mode" )
6295
- }
6293
+ reqc := make (chan chan struct {}, 2 )
6296
6294
ts := httptest .NewServer (HandlerFunc (func (w ResponseWriter , req * Request ) {
6295
+ ch := make (chan struct {}, 1 )
6296
+ reqc <- ch
6297
+ <- ch
6297
6298
w .Header ().Add ("Content-Length" , "0" )
6298
6299
}))
6299
6300
defer ts .Close ()
@@ -6305,34 +6306,58 @@ func TestCancelRequestWhenSharingConnection(t *testing.T) {
6305
6306
6306
6307
var wg sync.WaitGroup
6307
6308
6308
- ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
6309
+ wg .Add (1 )
6310
+ putidlec := make (chan chan struct {})
6311
+ go func () {
6312
+ defer wg .Done ()
6313
+ ctx := httptrace .WithClientTrace (context .Background (), & httptrace.ClientTrace {
6314
+ PutIdleConn : func (error ) {
6315
+ // Signal that the idle conn has been returned to the pool,
6316
+ // and wait for the order to proceed.
6317
+ ch := make (chan struct {})
6318
+ putidlec <- ch
6319
+ <- ch
6320
+ },
6321
+ })
6322
+ req , _ := NewRequestWithContext (ctx , "GET" , ts .URL , nil )
6323
+ res , err := client .Do (req )
6324
+ if err == nil {
6325
+ res .Body .Close ()
6326
+ }
6327
+ if err != nil {
6328
+ t .Errorf ("request 1: got err %v, want nil" , err )
6329
+ }
6330
+ }()
6309
6331
6310
- for i := 0 ; i < 10 ; i ++ {
6311
- wg .Add (1 )
6312
- go func () {
6313
- defer wg .Done ()
6314
- for ctx .Err () == nil {
6315
- reqctx , reqcancel := context .WithCancel (ctx )
6316
- go reqcancel ()
6317
- req , _ := NewRequestWithContext (reqctx , "GET" , ts .URL , nil )
6318
- res , err := client .Do (req )
6319
- if err == nil {
6320
- res .Body .Close ()
6321
- }
6322
- }
6323
- }()
6324
- }
6332
+ // Wait for the first request to receive a response and return the
6333
+ // connection to the idle pool.
6334
+ r1c := <- reqc
6335
+ close (r1c )
6336
+ idlec := <- putidlec
6325
6337
6326
- for ctx .Err () == nil {
6327
- req , _ := NewRequest ("GET" , ts .URL , nil )
6328
- if res , err := client .Do (req ); err != nil {
6329
- t .Errorf ("unexpected: %p %v" , req , err )
6330
- break
6331
- } else {
6338
+ wg .Add (1 )
6339
+ cancelctx , cancel := context .WithCancel (context .Background ())
6340
+ go func () {
6341
+ defer wg .Done ()
6342
+ req , _ := NewRequestWithContext (cancelctx , "GET" , ts .URL , nil )
6343
+ res , err := client .Do (req )
6344
+ if err == nil {
6332
6345
res .Body .Close ()
6333
6346
}
6334
- }
6347
+ if ! errors .Is (err , context .Canceled ) {
6348
+ t .Errorf ("request 2: got err %v, want Canceled" , err )
6349
+ }
6350
+ }()
6335
6351
6352
+ // Wait for the second request to arrive at the server, and then cancel
6353
+ // the request context.
6354
+ r2c := <- reqc
6336
6355
cancel ()
6356
+
6357
+ // Give the cancelation a moment to take effect, and then unblock the first request.
6358
+ time .Sleep (1 * time .Millisecond )
6359
+ close (idlec )
6360
+
6361
+ close (r2c )
6337
6362
wg .Wait ()
6338
6363
}
0 commit comments