33namespace React \Tests \Socket ;
44
55use React \EventLoop \Loop ;
6- use React \Promise ;
76use React \Promise \Deferred ;
7+ use React \Promise \Promise ;
88use React \Socket \TimeoutConnector ;
99
1010class TimeoutConnectorTest extends TestCase
@@ -22,90 +22,175 @@ public function testConstructWithoutLoopAssignsLoopAutomatically()
2222 $ this ->assertInstanceOf ('React\EventLoop\LoopInterface ' , $ loop );
2323 }
2424
25- public function testRejectsWithTimeoutReasonOnTimeout ()
25+ public function testRejectsPromiseWithoutStartingTimerWhenWrappedConnectorReturnsRejectedPromise ()
2626 {
27- $ promise = new Promise \Promise (function () { });
27+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
28+ $ loop ->expects ($ this ->never ())->method ('addTimer ' );
29+ $ loop ->expects ($ this ->never ())->method ('cancelTimer ' );
2830
2931 $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
30- $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('google .com:80 ' )->will ( $ this -> returnValue ( $ promise ));
32+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('example .com:80 ' )->willReturn ( \ React \ Promise \reject ( new \ RuntimeException ( ' Failed ' , 42 ) ));
3133
32- $ timeout = new TimeoutConnector ($ connector , 0.01 );
34+ $ timeout = new TimeoutConnector ($ connector , 5.0 , $ loop );
3335
34- $ promise = $ timeout ->connect ('google.com:80 ' );
35- Loop::run ();
36+ $ promise = $ timeout ->connect ('example.com:80 ' );
37+
38+ $ exception = null ;
39+ $ promise ->then (null , function ($ reason ) use (&$ exception ) {
40+ $ exception = $ reason ;
41+ });
3642
37- $ this ->setExpectedException (
38- 'RuntimeException ' ,
39- 'Connection to google.com:80 timed out after 0.01 seconds (ETIMEDOUT) ' ,
40- \defined ('SOCKET_ETIMEDOUT ' ) ? \SOCKET_ETIMEDOUT : 110
41- );
42- \React \Async \await ($ promise );
43+ assert ($ exception instanceof \RuntimeException);
44+ $ this ->assertEquals ('Failed ' , $ exception ->getMessage ());
45+ $ this ->assertEquals (42 , $ exception ->getCode ());
4346 }
4447
45- public function testRejectsWithOriginalReasonWhenConnectorRejects ()
48+ public function testRejectsPromiseAfterCancellingTimerWhenWrappedConnectorReturnsPendingPromiseThatRejects ()
4649 {
47- $ promise = Promise \reject (new \RuntimeException ('Failed ' , 42 ));
50+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
51+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
52+ $ loop ->expects ($ this ->once ())->method ('addTimer ' )->with (5.0 , $ this ->anything ())->willReturn ($ timer );
53+ $ loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
4854
55+ $ deferred = new Deferred ();
4956 $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
50- $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('google .com:80 ' )->will ( $ this -> returnValue ( $ promise ));
57+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('example .com:80 ' )->willReturn ( $ deferred -> promise ( ));
5158
52- $ timeout = new TimeoutConnector ($ connector , 5.0 );
59+ $ timeout = new TimeoutConnector ($ connector , 5.0 , $ loop );
60+
61+ $ promise = $ timeout ->connect ('example.com:80 ' );
62+
63+ $ deferred ->reject (new \RuntimeException ('Failed ' , 42 ));
64+
65+ $ exception = null ;
66+ $ promise ->then (null , function ($ reason ) use (&$ exception ) {
67+ $ exception = $ reason ;
68+ });
5369
54- $ this ->setExpectedException (
55- 'RuntimeException ' ,
56- 'Failed ' ,
57- 42
58- );
59- \React \Async \await ($ timeout ->connect ('google.com:80 ' ));
70+ assert ($ exception instanceof \RuntimeException);
71+ $ this ->assertEquals ('Failed ' , $ exception ->getMessage ());
72+ $ this ->assertEquals (42 , $ exception ->getCode ());
6073 }
6174
62- public function testResolvesWhenConnectorResolves ()
75+ public function testResolvesPromiseWithoutStartingTimerWhenWrappedConnectorReturnsResolvedPromise ()
6376 {
64- $ promise = Promise \resolve (null );
77+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
78+ $ loop ->expects ($ this ->never ())->method ('addTimer ' );
79+ $ loop ->expects ($ this ->never ())->method ('cancelTimer ' );
6580
81+ $ connection = $ this ->getMockBuilder ('React\Socket\ConnectionInterface ' )->getMock ();
6682 $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
67- $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('google .com:80 ' )->will ( $ this -> returnValue ( $ promise ));
83+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('example .com:80 ' )->willReturn ( \ React \ Promise \resolve ( $ connection ));
6884
69- $ timeout = new TimeoutConnector ($ connector , 5.0 );
85+ $ timeout = new TimeoutConnector ($ connector , 5.0 , $ loop );
7086
71- $ timeout ->connect ('google.com:80 ' )->then (
72- $ this ->expectCallableOnce (),
73- $ this ->expectCallableNever ()
74- );
87+ $ promise = $ timeout ->connect ('example.com:80 ' );
7588
76- Loop::run ();
89+ $ resolved = null ;
90+ $ promise ->then (function ($ value ) use (&$ resolved ) {
91+ $ resolved = $ value ;
92+ });
93+
94+ $ this ->assertSame ($ connection , $ resolved );
7795 }
7896
79- public function testRejectsAndCancelsPendingPromiseOnTimeout ()
97+ public function testResolvesPromiseAfterCancellingTimerWhenWrappedConnectorReturnsPendingPromiseThatResolves ()
8098 {
81- $ promise = new Promise \Promise (function () { }, $ this ->expectCallableOnce ());
99+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
100+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
101+ $ loop ->expects ($ this ->once ())->method ('addTimer ' )->with (5.0 , $ this ->anything ())->willReturn ($ timer );
102+ $ loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
82103
104+ $ deferred = new Deferred ();
83105 $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
84- $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('google .com:80 ' )->will ( $ this -> returnValue ( $ promise ));
106+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('example .com:80 ' )->willReturn ( $ deferred -> promise ( ));
85107
86- $ timeout = new TimeoutConnector ($ connector , 0.01 );
108+ $ timeout = new TimeoutConnector ($ connector , 5.0 , $ loop );
87109
88- $ timeout ->connect ('google.com:80 ' )->then (
89- $ this ->expectCallableNever (),
90- $ this ->expectCallableOnce ()
91- );
110+ $ promise = $ timeout ->connect ('example.com:80 ' );
92111
93- Loop::run ();
112+ $ connection = $ this ->getMockBuilder ('React\Socket\ConnectionInterface ' )->getMock ();
113+ $ deferred ->resolve ($ connection );
114+
115+ $ resolved = null ;
116+ $ promise ->then (function ($ value ) use (&$ resolved ) {
117+ $ resolved = $ value ;
118+ });
119+
120+ $ this ->assertSame ($ connection , $ resolved );
94121 }
95122
96- public function testCancelsPendingPromiseOnCancel ()
123+ public function testRejectsPromiseAndCancelsPendingConnectionWhenTimeoutTriggers ()
97124 {
98- $ promise = new Promise \Promise (function () { }, function () { throw new \Exception (); });
125+ $ timerCallback = null ;
126+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
127+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
128+ $ loop ->expects ($ this ->once ())->method ('addTimer ' )->with (0.01 , $ this ->callback (function ($ callback ) use (&$ timerCallback ) {
129+ $ timerCallback = $ callback ;
130+ return true ;
131+ }))->willReturn ($ timer );
132+ $ loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
133+
134+ $ cancelled = 0 ;
135+ $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
136+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('example.com:80 ' )->willReturn (new Promise (function () { }, function () use (&$ cancelled ) {
137+ ++$ cancelled ;
138+ throw new \RuntimeException ();
139+ }));
140+
141+ $ timeout = new TimeoutConnector ($ connector , 0.01 , $ loop );
142+
143+ $ promise = $ timeout ->connect ('example.com:80 ' );
144+
145+ $ this ->assertEquals (0 , $ cancelled );
146+
147+ $ this ->assertNotNull ($ timerCallback );
148+ $ timerCallback ();
149+
150+ $ this ->assertEquals (1 , $ cancelled );
151+
152+ $ exception = null ;
153+ $ promise ->then (null , function ($ reason ) use (&$ exception ) {
154+ $ exception = $ reason ;
155+ });
156+
157+ assert ($ exception instanceof \RuntimeException);
158+ $ this ->assertEquals ('Connection to example.com:80 timed out after 0.01 seconds (ETIMEDOUT) ' , $ exception ->getMessage ());
159+ $ this ->assertEquals (\defined ('SOCKET_ETIMEDOUT ' ) ? \SOCKET_ETIMEDOUT : 110 , $ exception ->getCode ());
160+ }
161+
162+ public function testCancellingPromiseWillCancelPendingConnectionAndRejectPromise ()
163+ {
164+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
165+ $ loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
166+ $ loop ->expects ($ this ->once ())->method ('addTimer ' )->with (0.01 , $ this ->anything ())->willReturn ($ timer );
167+ $ loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
99168
169+ $ cancelled = 0 ;
100170 $ connector = $ this ->getMockBuilder ('React\Socket\ConnectorInterface ' )->getMock ();
101- $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('google.com:80 ' )->will ($ this ->returnValue ($ promise ));
171+ $ connector ->expects ($ this ->once ())->method ('connect ' )->with ('example.com:80 ' )->willReturn (new Promise (function () { }, function () use (&$ cancelled ) {
172+ ++$ cancelled ;
173+ throw new \RuntimeException ('Cancelled ' );
174+ }));
102175
103- $ timeout = new TimeoutConnector ($ connector , 0.01 );
176+ $ timeout = new TimeoutConnector ($ connector , 0.01 , $ loop );
177+
178+ $ promise = $ timeout ->connect ('example.com:80 ' );
179+
180+ $ this ->assertEquals (0 , $ cancelled );
181+
182+ assert (method_exists ($ promise , 'cancel ' ));
183+ $ promise ->cancel ();
104184
105- $ out = $ timeout ->connect ('google.com:80 ' );
106- $ out ->cancel ();
185+ $ this ->assertEquals (1 , $ cancelled );
186+
187+ $ exception = null ;
188+ $ promise ->then (null , function ($ reason ) use (&$ exception ) {
189+ $ exception = $ reason ;
190+ });
107191
108- $ out ->then ($ this ->expectCallableNever (), $ this ->expectCallableOnce ());
192+ assert ($ exception instanceof \RuntimeException);
193+ $ this ->assertEquals ('Cancelled ' , $ exception ->getMessage ());
109194 }
110195
111196 public function testRejectionDuringConnectionShouldNotCreateAnyGarbageReferences ()
0 commit comments