@@ -228,9 +228,8 @@ func TestDialerDualStackFDLeak(t *testing.T) {
228
228
// expected to hang until the timeout elapses. These addresses are reserved
229
229
// for benchmarking by RFC 6890.
230
230
const (
231
- slowDst4 = "192.18.0.254"
232
- slowDst6 = "2001:2::254"
233
- slowTimeout = 1 * time .Second
231
+ slowDst4 = "198.18.0.254"
232
+ slowDst6 = "2001:2::254"
234
233
)
235
234
236
235
// In some environments, the slow IPs may be explicitly unreachable, and fail
@@ -239,7 +238,10 @@ const (
239
238
func slowDialTCP (net string , laddr , raddr * TCPAddr , deadline time.Time , cancel <- chan struct {}) (* TCPConn , error ) {
240
239
c , err := dialTCP (net , laddr , raddr , deadline , cancel )
241
240
if ParseIP (slowDst4 ).Equal (raddr .IP ) || ParseIP (slowDst6 ).Equal (raddr .IP ) {
242
- time .Sleep (deadline .Sub (time .Now ()))
241
+ select {
242
+ case <- cancel :
243
+ case <- time .After (deadline .Sub (time .Now ())):
244
+ }
243
245
}
244
246
return c , err
245
247
}
@@ -283,6 +285,9 @@ func TestDialParallel(t *testing.T) {
283
285
if ! supportsIPv4 || ! supportsIPv6 {
284
286
t .Skip ("both IPv4 and IPv6 are required" )
285
287
}
288
+ if runtime .GOOS == "plan9" {
289
+ t .Skip ("skipping on plan9; cannot cancel dialTCP, golang.org/issue/11225" )
290
+ }
286
291
287
292
closedPortDelay , expectClosedPortDelay := dialClosedPort ()
288
293
if closedPortDelay > expectClosedPortDelay {
@@ -388,7 +393,6 @@ func TestDialParallel(t *testing.T) {
388
393
fallbacks := makeAddrs (tt .fallbacks , dss .port )
389
394
d := Dialer {
390
395
FallbackDelay : fallbackDelay ,
391
- Timeout : slowTimeout ,
392
396
}
393
397
ctx := & dialContext {
394
398
Dialer : d ,
@@ -397,7 +401,7 @@ func TestDialParallel(t *testing.T) {
397
401
finalDeadline : d .deadline (time .Now ()),
398
402
}
399
403
startTime := time .Now ()
400
- c , err := dialParallel (ctx , primaries , fallbacks )
404
+ c , err := dialParallel (ctx , primaries , fallbacks , nil )
401
405
elapsed := time .Now ().Sub (startTime )
402
406
403
407
if c != nil {
@@ -417,9 +421,27 @@ func TestDialParallel(t *testing.T) {
417
421
} else if ! (elapsed <= expectElapsedMax ) {
418
422
t .Errorf ("#%d: got %v; want <= %v" , i , elapsed , expectElapsedMax )
419
423
}
424
+
425
+ // Repeat each case, ensuring that it can be canceled quickly.
426
+ cancel := make (chan struct {})
427
+ var wg sync.WaitGroup
428
+ wg .Add (1 )
429
+ go func () {
430
+ time .Sleep (5 * time .Millisecond )
431
+ close (cancel )
432
+ wg .Done ()
433
+ }()
434
+ startTime = time .Now ()
435
+ c , err = dialParallel (ctx , primaries , fallbacks , cancel )
436
+ if c != nil {
437
+ c .Close ()
438
+ }
439
+ elapsed = time .Now ().Sub (startTime )
440
+ if elapsed > 100 * time .Millisecond {
441
+ t .Errorf ("#%d (cancel): got %v; want <= 100ms" , i , elapsed )
442
+ }
443
+ wg .Wait ()
420
444
}
421
- // Wait for any slowDst4/slowDst6 connections to timeout.
422
- time .Sleep (slowTimeout * 3 / 2 )
423
445
}
424
446
425
447
func lookupSlowFast (fn func (string ) ([]IPAddr , error ), host string ) ([]IPAddr , error ) {
@@ -462,8 +484,6 @@ func TestDialerFallbackDelay(t *testing.T) {
462
484
{true , 200 * time .Millisecond , 200 * time .Millisecond },
463
485
// The default is 300ms.
464
486
{true , 0 , 300 * time .Millisecond },
465
- // This case is last, in order to wait for hanging slowDst6 connections.
466
- {false , 0 , slowTimeout },
467
487
}
468
488
469
489
handler := func (dss * dualStackServer , ln Listener ) {
@@ -487,7 +507,7 @@ func TestDialerFallbackDelay(t *testing.T) {
487
507
}
488
508
489
509
for i , tt := range testCases {
490
- d := & Dialer {DualStack : tt .dualstack , FallbackDelay : tt .delay , Timeout : slowTimeout }
510
+ d := & Dialer {DualStack : tt .dualstack , FallbackDelay : tt .delay }
491
511
492
512
startTime := time .Now ()
493
513
c , err := d .Dial ("tcp" , JoinHostPort ("slow6loopback4" , dss .port ))
@@ -508,46 +528,82 @@ func TestDialerFallbackDelay(t *testing.T) {
508
528
}
509
529
}
510
530
511
- func TestDialSerialAsyncSpuriousConnection (t * testing.T ) {
531
+ func TestDialParallelSpuriousConnection (t * testing.T ) {
532
+ if ! supportsIPv4 || ! supportsIPv6 {
533
+ t .Skip ("both IPv4 and IPv6 are required" )
534
+ }
512
535
if runtime .GOOS == "plan9" {
513
- t .Skip ("skipping on plan9; no deadline support, golang.org/issue/11932" )
536
+ t .Skip ("skipping on plan9; cannot cancel dialTCP, golang.org/issue/11225" )
537
+ }
538
+
539
+ var wg sync.WaitGroup
540
+ wg .Add (2 )
541
+ handler := func (dss * dualStackServer , ln Listener ) {
542
+ // Accept one connection per address.
543
+ c , err := ln .Accept ()
544
+ if err != nil {
545
+ t .Fatal (err )
546
+ }
547
+ // The client should close itself, without sending data.
548
+ c .SetReadDeadline (time .Now ().Add (1 * time .Second ))
549
+ var b [1 ]byte
550
+ if _ , err := c .Read (b [:]); err != io .EOF {
551
+ t .Errorf ("got %v; want %v" , err , io .EOF )
552
+ }
553
+ c .Close ()
554
+ wg .Done ()
514
555
}
515
- ln , err := newLocalListener ("tcp" )
556
+ dss , err := newDualStackServer ([]streamListener {
557
+ {network : "tcp4" , address : "127.0.0.1" },
558
+ {network : "tcp6" , address : "::1" },
559
+ })
516
560
if err != nil {
517
561
t .Fatal (err )
518
562
}
519
- defer ln .Close ()
563
+ defer dss .teardown ()
564
+ if err := dss .buildup (handler ); err != nil {
565
+ t .Fatal (err )
566
+ }
567
+
568
+ const fallbackDelay = 100 * time .Millisecond
569
+
570
+ origTestHookDialTCP := testHookDialTCP
571
+ defer func () { testHookDialTCP = origTestHookDialTCP }()
572
+ testHookDialTCP = func (net string , laddr , raddr * TCPAddr , deadline time.Time , cancel <- chan struct {}) (* TCPConn , error ) {
573
+ // Sleep long enough for Happy Eyeballs to kick in, and inhibit cancelation.
574
+ // This forces dialParallel to juggle two successful connections.
575
+ time .Sleep (fallbackDelay * 2 )
576
+ cancel = nil
577
+ return dialTCP (net , laddr , raddr , deadline , cancel )
578
+ }
520
579
521
- d := Dialer {}
580
+ d := Dialer {
581
+ FallbackDelay : fallbackDelay ,
582
+ }
522
583
ctx := & dialContext {
523
584
Dialer : d ,
524
585
network : "tcp" ,
525
586
address : "?" ,
526
587
finalDeadline : d .deadline (time .Now ()),
527
588
}
528
589
529
- results := make (chan dialResult )
530
- cancel := make (chan struct {})
531
-
532
- // Spawn a connection in the background.
533
- go dialSerialAsync (ctx , addrList {ln .Addr ()}, nil , cancel , results )
590
+ makeAddr := func (ip string ) addrList {
591
+ addr , err := ResolveTCPAddr ("tcp" , JoinHostPort (ip , dss .port ))
592
+ if err != nil {
593
+ t .Fatal (err )
594
+ }
595
+ return addrList {addr }
596
+ }
534
597
535
- // Receive it at the server.
536
- c , err := ln . Accept ( )
598
+ // dialParallel returns one connection (and closes the other.)
599
+ c , err := dialParallel ( ctx , makeAddr ( "127.0.0.1" ), makeAddr ( "::1" ), nil )
537
600
if err != nil {
538
601
t .Fatal (err )
539
602
}
540
- defer c .Close ()
541
-
542
- // Tell dialSerialAsync that someone else won the race.
543
- close (cancel )
603
+ c .Close ()
544
604
545
- // The connection should close itself, without sending data.
546
- c .SetReadDeadline (time .Now ().Add (1 * time .Second ))
547
- var b [1 ]byte
548
- if _ , err := c .Read (b [:]); err != io .EOF {
549
- t .Errorf ("got %v; want %v" , err , io .EOF )
550
- }
605
+ // The server should've seen both connections.
606
+ wg .Wait ()
551
607
}
552
608
553
609
func TestDialerPartialDeadline (t * testing.T ) {
@@ -676,7 +732,6 @@ func TestDialerDualStack(t *testing.T) {
676
732
c .Close ()
677
733
}
678
734
}
679
- time .Sleep (timeout * 3 / 2 ) // wait for the dial racers to stop
680
735
}
681
736
682
737
func TestDialerKeepAlive (t * testing.T ) {
0 commit comments