@@ -217,6 +217,77 @@ public function testConnectWillStartConnectingWithAttemptTimerButWithoutResoluti
217
217
$ deferred ->reject (new \RuntimeException ());
218
218
}
219
219
220
+ public function testConnectWillStartConnectingWithAttemptTimerWhenIpv6AndIpv4ResolvesAndWillStartNextConnectionAttemptWithoutAttemptTimerImmediatelyWhenFirstConnectionAttemptFails ()
221
+ {
222
+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
223
+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
224
+ $ loop ->expects ($ this ->once ())->method ('addTimer ' )->with (0.1 , $ this ->anything ())->willReturn ($ timer );
225
+ $ loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
226
+
227
+ $ deferred = new Deferred ();
228
+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
229
+ $ connector ->expects ($ this ->exactly (2 ))->method ('connect ' )->withConsecutive (
230
+ array ('tcp://[::1]:80?hostname=reactphp.org ' ),
231
+ array ('tcp://127.0.0.1:80?hostname=reactphp.org ' )
232
+ )->willReturnOnConsecutiveCalls (
233
+ $ deferred ->promise (),
234
+ new Promise (function () { })
235
+ );
236
+
237
+ $ resolver = $ this ->getMockBuilder ('React\Dns\Resolver\ResolverInterface ' )->getMock ();
238
+ $ resolver ->expects ($ this ->exactly (2 ))->method ('resolveAll ' )->withConsecutive (
239
+ array ('reactphp.org ' , Message::TYPE_AAAA ),
240
+ array ('reactphp.org ' , Message::TYPE_A )
241
+ )->willReturnOnConsecutiveCalls (
242
+ \React \Promise \resolve (array ('::1 ' )),
243
+ \React \Promise \resolve (array ('127.0.0.1 ' ))
244
+ );
245
+
246
+ $ uri = 'tcp://reactphp.org:80 ' ;
247
+ $ host = 'reactphp.org ' ;
248
+ $ parts = parse_url ($ uri );
249
+
250
+ $ builder = new HappyEyeBallsConnectionBuilder ($ loop , $ connector , $ resolver , $ uri , $ host , $ parts );
251
+
252
+ $ builder ->connect ();
253
+
254
+ $ deferred ->reject (new \RuntimeException ());
255
+ }
256
+
257
+ public function testConnectWillStartConnectingWithAttemptTimerWhenOnlyIpv6ResolvesAndWillStartNextConnectionAttemptWithoutAttemptTimerImmediatelyWhenFirstConnectionAttemptFails ()
258
+ {
259
+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
260
+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
261
+ $ loop ->expects ($ this ->once ())->method ('addTimer ' )->with (0.1 , $ this ->anything ())->willReturn ($ timer );
262
+ $ loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
263
+
264
+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
265
+ $ connector ->expects ($ this ->exactly (2 ))->method ('connect ' )->withConsecutive (
266
+ array ('tcp://[::1]:80?hostname=reactphp.org ' ),
267
+ array ('tcp://[::2]:80?hostname=reactphp.org ' )
268
+ )->willReturnOnConsecutiveCalls (
269
+ \React \Promise \reject (new \RuntimeException ()),
270
+ new Promise (function () { })
271
+ );
272
+
273
+ $ resolver = $ this ->getMockBuilder ('React\Dns\Resolver\ResolverInterface ' )->getMock ();
274
+ $ resolver ->expects ($ this ->exactly (2 ))->method ('resolveAll ' )->withConsecutive (
275
+ array ('reactphp.org ' , Message::TYPE_AAAA ),
276
+ array ('reactphp.org ' , Message::TYPE_A )
277
+ )->willReturnOnConsecutiveCalls (
278
+ \React \Promise \resolve (array ('::1 ' , '::2 ' )),
279
+ \React \Promise \reject (new \RuntimeException ())
280
+ );
281
+
282
+ $ uri = 'tcp://reactphp.org:80 ' ;
283
+ $ host = 'reactphp.org ' ;
284
+ $ parts = parse_url ($ uri );
285
+
286
+ $ builder = new HappyEyeBallsConnectionBuilder ($ loop , $ connector , $ resolver , $ uri , $ host , $ parts );
287
+
288
+ $ builder ->connect ();
289
+ }
290
+
220
291
public function testConnectWillStartConnectingAndWillStartNextConnectionWithoutNewAttemptTimerWhenNextAttemptTimerFiresAfterIpv4Rejected ()
221
292
{
222
293
$ timer = null ;
@@ -492,4 +563,89 @@ public function testAttemptConnectionWillConnectViaConnectorToGivenIpv6WithAllUr
492
563
493
564
$ builder ->attemptConnection ('::1 ' );
494
565
}
566
+
567
+ public function testCheckCallsRejectFunctionImmediateWithoutLeavingDanglingPromiseWhenConnectorRejectsImmediately ()
568
+ {
569
+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
570
+
571
+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
572
+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('tcp://[::1]:80/path?test=yes&hostname=reactphp.org#start ' )->willReturn (\React \Promise \reject (new \RuntimeException ()));
573
+
574
+ $ resolver = $ this ->getMockBuilder ('React\Dns\Resolver\ResolverInterface ' )->getMock ();
575
+ $ resolver ->expects ($ this ->never ())->method ('resolveAll ' );
576
+
577
+ $ uri = 'tcp://reactphp.org:80/path?test=yes#start ' ;
578
+ $ host = 'reactphp.org ' ;
579
+ $ parts = parse_url ($ uri );
580
+
581
+ $ builder = new HappyEyeBallsConnectionBuilder ($ loop , $ connector , $ resolver , $ uri , $ host , $ parts );
582
+
583
+ $ ref = new \ReflectionProperty ($ builder , 'connectQueue ' );
584
+ $ ref ->setAccessible (true );
585
+ $ ref ->setValue ($ builder , array ('::1 ' ));
586
+
587
+ $ builder ->check ($ this ->expectCallableNever (), function () { });
588
+
589
+ $ ref = new \ReflectionProperty ($ builder , 'connectionPromises ' );
590
+ $ ref ->setAccessible (true );
591
+ $ promises = $ ref ->getValue ($ builder );
592
+
593
+ $ this ->assertEquals (array (), $ promises );
594
+ }
595
+
596
+ public function testCleanUpCancelsAllPendingConnectionAttempts ()
597
+ {
598
+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
599
+
600
+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
601
+ $ connector ->expects ($ this ->exactly (2 ))->method ('connect ' )->with ('tcp://[::1]:80/path?test=yes&hostname=reactphp.org#start ' )->willReturnOnConsecutiveCalls (
602
+ new Promise (function () { }, $ this ->expectCallableOnce ()),
603
+ new Promise (function () { }, $ this ->expectCallableOnce ())
604
+ );
605
+
606
+ $ resolver = $ this ->getMockBuilder ('React\Dns\Resolver\ResolverInterface ' )->getMock ();
607
+ $ resolver ->expects ($ this ->never ())->method ('resolveAll ' );
608
+
609
+ $ uri = 'tcp://reactphp.org:80/path?test=yes#start ' ;
610
+ $ host = 'reactphp.org ' ;
611
+ $ parts = parse_url ($ uri );
612
+
613
+ $ builder = new HappyEyeBallsConnectionBuilder ($ loop , $ connector , $ resolver , $ uri , $ host , $ parts );
614
+
615
+ $ ref = new \ReflectionProperty ($ builder , 'connectQueue ' );
616
+ $ ref ->setAccessible (true );
617
+ $ ref ->setValue ($ builder , array ('::1 ' , '::1 ' ));
618
+
619
+ $ builder ->check ($ this ->expectCallableNever (), function () { });
620
+ $ builder ->check ($ this ->expectCallableNever (), function () { });
621
+
622
+ $ builder ->cleanUp ();
623
+ }
624
+
625
+ public function testCleanUpCancelsAllPendingConnectionAttemptsWithoutStartingNewAttemptsDueToCancellationRejection ()
626
+ {
627
+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
628
+
629
+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
630
+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('tcp://[::1]:80/path?test=yes&hostname=reactphp.org#start ' )->willReturn (new Promise (function () { }, function () {
631
+ throw new \RuntimeException ();
632
+ }));
633
+
634
+ $ resolver = $ this ->getMockBuilder ('React\Dns\Resolver\ResolverInterface ' )->getMock ();
635
+ $ resolver ->expects ($ this ->never ())->method ('resolveAll ' );
636
+
637
+ $ uri = 'tcp://reactphp.org:80/path?test=yes#start ' ;
638
+ $ host = 'reactphp.org ' ;
639
+ $ parts = parse_url ($ uri );
640
+
641
+ $ builder = new HappyEyeBallsConnectionBuilder ($ loop , $ connector , $ resolver , $ uri , $ host , $ parts );
642
+
643
+ $ ref = new \ReflectionProperty ($ builder , 'connectQueue ' );
644
+ $ ref ->setAccessible (true );
645
+ $ ref ->setValue ($ builder , array ('::1 ' , '::1 ' ));
646
+
647
+ $ builder ->check ($ this ->expectCallableNever (), function () { });
648
+
649
+ $ builder ->cleanUp ();
650
+ }
495
651
}
0 commit comments