3
3
namespace React \Tests \Socket ;
4
4
5
5
use React \EventLoop \Loop ;
6
- use React \Promise ;
7
6
use React \Promise \Deferred ;
7
+ use React \Promise \Promise ;
8
8
use React \Socket \TimeoutConnector ;
9
9
10
10
class TimeoutConnectorTest extends TestCase
@@ -22,90 +22,175 @@ public function testConstructWithoutLoopAssignsLoopAutomatically()
22
22
$ this ->assertInstanceOf ('React\EventLoop\LoopInterface ' , $ loop );
23
23
}
24
24
25
- public function testRejectsWithTimeoutReasonOnTimeout ()
25
+ public function testRejectsPromiseWithoutStartingTimerWhenWrappedConnectorReturnsRejectedPromise ()
26
26
{
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 ' );
28
30
29
31
$ 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 ) ));
31
33
32
- $ timeout = new TimeoutConnector ($ connector , 0.01 );
34
+ $ timeout = new TimeoutConnector ($ connector , 5.0 , $ loop );
33
35
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
+ });
36
42
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 ());
43
46
}
44
47
45
- public function testRejectsWithOriginalReasonWhenConnectorRejects ()
48
+ public function testRejectsPromiseAfterCancellingTimerWhenWrappedConnectorReturnsPendingPromiseThatRejects ()
46
49
{
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 );
48
54
55
+ $ deferred = new Deferred ();
49
56
$ 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 ( ));
51
58
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
+ });
53
69
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 ());
60
73
}
61
74
62
- public function testResolvesWhenConnectorResolves ()
75
+ public function testResolvesPromiseWithoutStartingTimerWhenWrappedConnectorReturnsResolvedPromise ()
63
76
{
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 ' );
65
80
81
+ $ connection = $ this ->getMockBuilder ('React\Socket\ConnectionInterface ' )->getMock ();
66
82
$ 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 ));
68
84
69
- $ timeout = new TimeoutConnector ($ connector , 5.0 );
85
+ $ timeout = new TimeoutConnector ($ connector , 5.0 , $ loop );
70
86
71
- $ timeout ->connect ('google.com:80 ' )->then (
72
- $ this ->expectCallableOnce (),
73
- $ this ->expectCallableNever ()
74
- );
87
+ $ promise = $ timeout ->connect ('example.com:80 ' );
75
88
76
- Loop::run ();
89
+ $ resolved = null ;
90
+ $ promise ->then (function ($ value ) use (&$ resolved ) {
91
+ $ resolved = $ value ;
92
+ });
93
+
94
+ $ this ->assertSame ($ connection , $ resolved );
77
95
}
78
96
79
- public function testRejectsAndCancelsPendingPromiseOnTimeout ()
97
+ public function testResolvesPromiseAfterCancellingTimerWhenWrappedConnectorReturnsPendingPromiseThatResolves ()
80
98
{
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 );
82
103
104
+ $ deferred = new Deferred ();
83
105
$ 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 ( ));
85
107
86
- $ timeout = new TimeoutConnector ($ connector , 0.01 );
108
+ $ timeout = new TimeoutConnector ($ connector , 5.0 , $ loop );
87
109
88
- $ timeout ->connect ('google.com:80 ' )->then (
89
- $ this ->expectCallableNever (),
90
- $ this ->expectCallableOnce ()
91
- );
110
+ $ promise = $ timeout ->connect ('example.com:80 ' );
92
111
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 );
94
121
}
95
122
96
- public function testCancelsPendingPromiseOnCancel ()
123
+ public function testRejectsPromiseAndCancelsPendingConnectionWhenTimeoutTriggers ()
97
124
{
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 );
99
168
169
+ $ cancelled = 0 ;
100
170
$ 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
+ }));
102
175
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 ();
104
184
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
+ });
107
191
108
- $ out ->then ($ this ->expectCallableNever (), $ this ->expectCallableOnce ());
192
+ assert ($ exception instanceof \RuntimeException);
193
+ $ this ->assertEquals ('Cancelled ' , $ exception ->getMessage ());
109
194
}
110
195
111
196
public function testRejectionDuringConnectionShouldNotCreateAnyGarbageReferences ()
0 commit comments