22
33namespace React \Tests \Socket ;
44
5+ use Clue \React \Block ;
56use React \Socket \TimeoutConnector ;
67use React \Promise ;
78use React \EventLoop \Factory ;
9+ use React \Promise \Deferred ;
810
911class TimeoutConnectorTest extends TestCase
1012{
11- public function testRejectsOnTimeout ()
13+ /**
14+ * @expectedException RuntimeException
15+ * @expectedExceptionMessage Connection to google.com:80 timed out after 0.01 seconds
16+ */
17+ public function testRejectsWithTimeoutReasonOnTimeout ()
1218 {
1319 $ promise = new Promise \Promise (function () { });
1420
@@ -19,17 +25,16 @@ public function testRejectsOnTimeout()
1925
2026 $ timeout = new TimeoutConnector ($ connector , 0.01 , $ loop );
2127
22- $ timeout ->connect ('google.com:80 ' )->then (
23- $ this ->expectCallableNever (),
24- $ this ->expectCallableOnce ()
25- );
26-
27- $ loop ->run ();
28+ Block \await ($ timeout ->connect ('google.com:80 ' ), $ loop );
2829 }
2930
30- public function testRejectsWhenConnectorRejects ()
31+ /**
32+ * @expectedException RuntimeException
33+ * @expectedExceptionMessage Failed
34+ */
35+ public function testRejectsWithOriginalReasonWhenConnectorRejects ()
3136 {
32- $ promise = Promise \reject (new \RuntimeException ());
37+ $ promise = Promise \reject (new \RuntimeException (' Failed ' ));
3338
3439 $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
3540 $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('google.com:80 ' )->will ($ this ->returnValue ($ promise ));
@@ -38,12 +43,7 @@ public function testRejectsWhenConnectorRejects()
3843
3944 $ timeout = new TimeoutConnector ($ connector , 5.0 , $ loop );
4045
41- $ timeout ->connect ('google.com:80 ' )->then (
42- $ this ->expectCallableNever (),
43- $ this ->expectCallableOnce ()
44- );
45-
46- $ loop ->run ();
46+ Block \await ($ timeout ->connect ('google.com:80 ' ), $ loop );
4747 }
4848
4949 public function testResolvesWhenConnectorResolves ()
@@ -100,4 +100,51 @@ public function testCancelsPendingPromiseOnCancel()
100100
101101 $ out ->then ($ this ->expectCallableNever (), $ this ->expectCallableOnce ());
102102 }
103+
104+ public function testRejectionDuringConnectionShouldNotCreateAnyGarbageReferences ()
105+ {
106+ if (class_exists ('React\Promise\When ' )) {
107+ $ this ->markTestSkipped ('Not supported on legacy Promise v1 API ' );
108+ }
109+
110+ gc_collect_cycles ();
111+
112+ $ connection = new Deferred ();
113+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
114+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('example.com:80 ' )->willReturn ($ connection ->promise ());
115+
116+ $ loop = Factory::create ();
117+ $ timeout = new TimeoutConnector ($ connector , 0.01 , $ loop );
118+
119+ $ promise = $ timeout ->connect ('example.com:80 ' );
120+ $ connection ->reject (new \RuntimeException ('Connection failed ' ));
121+ unset($ promise , $ connection );
122+
123+ $ this ->assertEquals (0 , gc_collect_cycles ());
124+ }
125+
126+ public function testRejectionDueToTimeoutShouldNotCreateAnyGarbageReferences ()
127+ {
128+ if (class_exists ('React\Promise\When ' )) {
129+ $ this ->markTestSkipped ('Not supported on legacy Promise v1 API ' );
130+ }
131+
132+ gc_collect_cycles ();
133+
134+ $ connection = new Deferred (function () {
135+ throw new \RuntimeException ('Connection cancelled ' );
136+ });
137+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
138+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('example.com:80 ' )->willReturn ($ connection ->promise ());
139+
140+ $ loop = Factory::create ();
141+ $ timeout = new TimeoutConnector ($ connector , 0 , $ loop );
142+
143+ $ promise = $ timeout ->connect ('example.com:80 ' );
144+
145+ $ loop ->run ();
146+ unset($ promise , $ connection );
147+
148+ $ this ->assertEquals (0 , gc_collect_cycles ());
149+ }
103150}
0 commit comments