@@ -65,6 +65,42 @@ public function testConnectWillRejectWhenBothDnsLookupsReject()
65
65
$ this ->assertEquals ('Connection to tcp://reactphp.org:80 failed during DNS lookup: DNS lookup error ' , $ exception ->getMessage ());
66
66
}
67
67
68
+ public function testConnectWillRejectWhenBothDnsLookupsRejectWithDifferentMessages ()
69
+ {
70
+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
71
+ $ loop ->expects ($ this ->never ())->method ('addTimer ' );
72
+
73
+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
74
+ $ connector ->expects ($ this ->never ())->method ('connect ' );
75
+
76
+ $ deferred = new Deferred ();
77
+ $ resolver = $ this ->getMockBuilder ('React\Dns\Resolver\ResolverInterface ' )->getMock ();
78
+ $ resolver ->expects ($ this ->exactly (2 ))->method ('resolveAll ' )->withConsecutive (
79
+ array ('reactphp.org ' , Message::TYPE_AAAA ),
80
+ array ('reactphp.org ' , Message::TYPE_A )
81
+ )->willReturnOnConsecutiveCalls (
82
+ $ deferred ->promise (),
83
+ \React \Promise \reject (new \RuntimeException ('DNS4 error ' ))
84
+ );
85
+
86
+ $ uri = 'tcp://reactphp.org:80 ' ;
87
+ $ host = 'reactphp.org ' ;
88
+ $ parts = parse_url ($ uri );
89
+
90
+ $ builder = new HappyEyeBallsConnectionBuilder ($ loop , $ connector , $ resolver , $ uri , $ host , $ parts );
91
+
92
+ $ promise = $ builder ->connect ();
93
+ $ deferred ->reject (new \RuntimeException ('DNS6 error ' ));
94
+
95
+ $ exception = null ;
96
+ $ promise ->then (null , function ($ e ) use (&$ exception ) {
97
+ $ exception = $ e ;
98
+ });
99
+
100
+ $ this ->assertInstanceOf ('RuntimeException ' , $ exception );
101
+ $ this ->assertEquals ('Connection to tcp://reactphp.org:80 failed during DNS lookup. Last error for IPv6: DNS6 error. Previous error for IPv4: DNS4 error ' , $ exception ->getMessage ());
102
+ }
103
+
68
104
public function testConnectWillStartDelayTimerWhenIpv4ResolvesAndIpv6IsPending ()
69
105
{
70
106
$ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
@@ -364,7 +400,7 @@ public function testConnectWillStartAndCancelResolutionTimerAndStartAttemptTimer
364
400
$ deferred ->resolve (array ('::1 ' ));
365
401
}
366
402
367
- public function testConnectWillRejectWhenOnlyTcpConnectionRejectsAndCancelNextAttemptTimerImmediately ()
403
+ public function testConnectWillRejectWhenOnlyTcp6ConnectionRejectsAndCancelNextAttemptTimerImmediately ()
368
404
{
369
405
$ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
370
406
$ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
@@ -381,7 +417,81 @@ public function testConnectWillRejectWhenOnlyTcpConnectionRejectsAndCancelNextAt
381
417
array ('reactphp.org ' , Message::TYPE_A )
382
418
)->willReturnOnConsecutiveCalls (
383
419
\React \Promise \resolve (array ('::1 ' )),
384
- \React \Promise \reject (new \RuntimeException ('ignored ' ))
420
+ \React \Promise \reject (new \RuntimeException ('DNS failed ' ))
421
+ );
422
+
423
+ $ uri = 'tcp://reactphp.org:80 ' ;
424
+ $ host = 'reactphp.org ' ;
425
+ $ parts = parse_url ($ uri );
426
+
427
+ $ builder = new HappyEyeBallsConnectionBuilder ($ loop , $ connector , $ resolver , $ uri , $ host , $ parts );
428
+
429
+ $ promise = $ builder ->connect ();
430
+ $ deferred ->reject (new \RuntimeException ('Connection refused ' ));
431
+
432
+ $ exception = null ;
433
+ $ promise ->then (null , function ($ e ) use (&$ exception ) {
434
+ $ exception = $ e ;
435
+ });
436
+
437
+ $ this ->assertInstanceOf ('RuntimeException ' , $ exception );
438
+ $ this ->assertEquals ('Connection to tcp://reactphp.org:80 failed: Last error for IPv6: Connection refused. Previous error for IPv4: DNS failed ' , $ exception ->getMessage ());
439
+ }
440
+
441
+ public function testConnectWillRejectWhenOnlyTcp4ConnectionRejectsAndWillNeverStartNextAttemptTimer ()
442
+ {
443
+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
444
+ $ loop ->expects ($ this ->never ())->method ('addTimer ' );
445
+
446
+ $ deferred = new Deferred ();
447
+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
448
+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('tcp://127.0.0.1:80?hostname=reactphp.org ' )->willReturn ($ deferred ->promise ());
449
+
450
+ $ resolver = $ this ->getMockBuilder ('React\Dns\Resolver\ResolverInterface ' )->getMock ();
451
+ $ resolver ->expects ($ this ->exactly (2 ))->method ('resolveAll ' )->withConsecutive (
452
+ array ('reactphp.org ' , Message::TYPE_AAAA ),
453
+ array ('reactphp.org ' , Message::TYPE_A )
454
+ )->willReturnOnConsecutiveCalls (
455
+ \React \Promise \reject (new \RuntimeException ('DNS failed ' )),
456
+ \React \Promise \resolve (array ('127.0.0.1 ' ))
457
+ );
458
+
459
+ $ uri = 'tcp://reactphp.org:80 ' ;
460
+ $ host = 'reactphp.org ' ;
461
+ $ parts = parse_url ($ uri );
462
+
463
+ $ builder = new HappyEyeBallsConnectionBuilder ($ loop , $ connector , $ resolver , $ uri , $ host , $ parts );
464
+
465
+ $ promise = $ builder ->connect ();
466
+ $ deferred ->reject (new \RuntimeException ('Connection refused ' ));
467
+
468
+ $ exception = null ;
469
+ $ promise ->then (null , function ($ e ) use (&$ exception ) {
470
+ $ exception = $ e ;
471
+ });
472
+
473
+ $ this ->assertInstanceOf ('RuntimeException ' , $ exception );
474
+ $ this ->assertEquals ('Connection to tcp://reactphp.org:80 failed: Last error for IPv4: Connection refused. Previous error for IPv6: DNS failed ' , $ exception ->getMessage ());
475
+ }
476
+
477
+ public function testConnectWillRejectWhenAllConnectionsRejectAndCancelNextAttemptTimerImmediately ()
478
+ {
479
+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
480
+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
481
+ $ loop ->expects ($ this ->once ())->method ('addTimer ' )->with (0.1 , $ this ->anything ())->willReturn ($ timer );
482
+ $ loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
483
+
484
+ $ deferred = new Deferred ();
485
+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
486
+ $ connector ->expects ($ this ->exactly (2 ))->method ('connect ' )->willReturn ($ deferred ->promise ());
487
+
488
+ $ resolver = $ this ->getMockBuilder ('React\Dns\Resolver\ResolverInterface ' )->getMock ();
489
+ $ resolver ->expects ($ this ->exactly (2 ))->method ('resolveAll ' )->withConsecutive (
490
+ array ('reactphp.org ' , Message::TYPE_AAAA ),
491
+ array ('reactphp.org ' , Message::TYPE_A )
492
+ )->willReturnOnConsecutiveCalls (
493
+ \React \Promise \resolve (array ('::1 ' )),
494
+ \React \Promise \resolve (array ('127.0.0.1 ' ))
385
495
);
386
496
387
497
$ uri = 'tcp://reactphp.org:80 ' ;
0 commit comments