@@ -15,6 +15,7 @@ class TimeoutExecutorTest extends TestCase
15
15
{
16
16
private $ wrapped ;
17
17
private $ executor ;
18
+ private $ loop ;
18
19
19
20
/**
20
21
* @before
@@ -23,7 +24,9 @@ public function setUpExecutor()
23
24
{
24
25
$ this ->wrapped = $ this ->getMockBuilder ('React\Dns\Query\ExecutorInterface ' )->getMock ();
25
26
26
- $ this ->executor = new TimeoutExecutor ($ this ->wrapped , 5.0 );
27
+ $ this ->loop = $ this ->getMockBuilder ('React\EventLoop\LoopInterface ' )->getMock ();
28
+
29
+ $ this ->executor = new TimeoutExecutor ($ this ->wrapped , 5.0 , $ this ->loop );
27
30
}
28
31
29
32
public function testCtorWithoutLoopShouldAssignDefaultLoop ()
@@ -39,6 +42,10 @@ public function testCtorWithoutLoopShouldAssignDefaultLoop()
39
42
40
43
public function testCancellingPromiseWillCancelWrapped ()
41
44
{
45
+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
46
+ $ this ->loop ->expects ($ this ->once ())->method ('addTimer ' )->with (5.0 , $ this ->anything ())->willReturn ($ timer );
47
+ $ this ->loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
48
+
42
49
$ cancelled = 0 ;
43
50
44
51
$ this ->wrapped
@@ -63,8 +70,11 @@ public function testCancellingPromiseWillCancelWrapped()
63
70
$ promise ->then ($ this ->expectCallableNever (), $ this ->expectCallableOnce ());
64
71
}
65
72
66
- public function testResolvesPromiseWhenWrappedResolves ()
73
+ public function testResolvesPromiseWithoutStartingTimerWhenWrappedReturnsResolvedPromise ()
67
74
{
75
+ $ this ->loop ->expects ($ this ->never ())->method ('addTimer ' );
76
+ $ this ->loop ->expects ($ this ->never ())->method ('cancelTimer ' );
77
+
68
78
$ this ->wrapped
69
79
->expects ($ this ->once ())
70
80
->method ('query ' )
@@ -76,8 +86,31 @@ public function testResolvesPromiseWhenWrappedResolves()
76
86
$ promise ->then ($ this ->expectCallableOnce (), $ this ->expectCallableNever ());
77
87
}
78
88
79
- public function testRejectsPromiseWhenWrappedRejects ()
89
+ public function testResolvesPromiseAfterCancellingTimerWhenWrappedReturnsPendingPromiseThatResolves ()
90
+ {
91
+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
92
+ $ this ->loop ->expects ($ this ->once ())->method ('addTimer ' )->with (5.0 , $ this ->anything ())->willReturn ($ timer );
93
+ $ this ->loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
94
+
95
+ $ deferred = new Deferred ();
96
+ $ this ->wrapped
97
+ ->expects ($ this ->once ())
98
+ ->method ('query ' )
99
+ ->willReturn ($ deferred ->promise ());
100
+
101
+ $ query = new Query ('igor.io ' , Message::TYPE_A , Message::CLASS_IN );
102
+ $ promise = $ this ->executor ->query ($ query );
103
+
104
+ $ deferred ->resolve ('0.0.0.0 ' );
105
+
106
+ $ promise ->then ($ this ->expectCallableOnce (), $ this ->expectCallableNever ());
107
+ }
108
+
109
+ public function testRejectsPromiseWithoutStartingTimerWhenWrappedReturnsRejectedPromise ()
80
110
{
111
+ $ this ->loop ->expects ($ this ->never ())->method ('addTimer ' );
112
+ $ this ->loop ->expects ($ this ->never ())->method ('cancelTimer ' );
113
+
81
114
$ this ->wrapped
82
115
->expects ($ this ->once ())
83
116
->method ('query ' )
@@ -89,9 +122,35 @@ public function testRejectsPromiseWhenWrappedRejects()
89
122
$ promise ->then ($ this ->expectCallableNever (), $ this ->expectCallableOnceWith (new \RuntimeException ()));
90
123
}
91
124
92
- public function testWrappedWillBeCancelledOnTimeout ()
125
+ public function testRejectsPromiseAfterCancellingTimerWhenWrappedReturnsPendingPromiseThatRejects ()
126
+ {
127
+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
128
+ $ this ->loop ->expects ($ this ->once ())->method ('addTimer ' )->with (5.0 , $ this ->anything ())->willReturn ($ timer );
129
+ $ this ->loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
130
+
131
+ $ deferred = new Deferred ();
132
+ $ this ->wrapped
133
+ ->expects ($ this ->once ())
134
+ ->method ('query ' )
135
+ ->willReturn ($ deferred ->promise ());
136
+
137
+ $ query = new Query ('igor.io ' , Message::TYPE_A , Message::CLASS_IN );
138
+ $ promise = $ this ->executor ->query ($ query );
139
+
140
+ $ deferred ->reject (new \RuntimeException ());
141
+
142
+ $ promise ->then ($ this ->expectCallableNever (), $ this ->expectCallableOnceWith (new \RuntimeException ()));
143
+ }
144
+
145
+ public function testRejectsPromiseAndCancelsPendingQueryWhenTimeoutTriggers ()
93
146
{
94
- $ this ->executor = new TimeoutExecutor ($ this ->wrapped , 0 );
147
+ $ timerCallback = null ;
148
+ $ timer = $ this ->getMockBuilder ('React\EventLoop\TimerInterface ' )->getMock ();
149
+ $ this ->loop ->expects ($ this ->once ())->method ('addTimer ' )->with (5.0 , $ this ->callback (function ($ callback ) use (&$ timerCallback ) {
150
+ $ timerCallback = $ callback ;
151
+ return true ;
152
+ }))->willReturn ($ timer );
153
+ $ this ->loop ->expects ($ this ->once ())->method ('cancelTimer ' )->with ($ timer );
95
154
96
155
$ cancelled = 0 ;
97
156
@@ -112,14 +171,18 @@ public function testWrappedWillBeCancelledOnTimeout()
112
171
113
172
$ this ->assertEquals (0 , $ cancelled );
114
173
115
- try {
116
- \React \Async \await (\React \Promise \Timer \sleep (0 ));
117
- \React \Async \await ($ promise );
118
- $ this ->fail ();
119
- } catch (TimeoutException $ exception ) {
120
- $ this ->assertEquals ('DNS query for igor.io (A) timed out ' , $ exception ->getMessage ());
121
- }
174
+ $ this ->assertNotNull ($ timerCallback );
175
+ $ timerCallback ();
122
176
123
177
$ this ->assertEquals (1 , $ cancelled );
178
+
179
+ $ exception = null ;
180
+ $ promise ->then (null , function ($ reason ) use (&$ exception ) {
181
+ $ exception = $ reason ;
182
+ });
183
+
184
+ assert ($ exception instanceof TimeoutException);
185
+ $ this ->assertInstanceOf ('React\Dns\Query\TimeoutException ' , $ exception );
186
+ $ this ->assertEquals ('DNS query for igor.io (A) timed out ' , $ exception ->getMessage ());
124
187
}
125
188
}
0 commit comments