@@ -134,8 +134,6 @@ public function testQueryWillRejectWithExceptionMessagesConcatenatedInFullWhenPr
134134
135135 public function testCancelQueryWillReturnRejectedPromiseWithoutCallingSecondaryExecutorWhenPrimaryExecutorIsStillPending ()
136136 {
137- $ this ->markTestIncomplete ();
138-
139137 $ query = new Query ('reactphp.org ' , Message::TYPE_A , Message::CLASS_IN );
140138
141139 $ primary = $ this ->getMockBuilder ('React\Dns\Query\ExecutorInterface ' )->getMock ();
@@ -152,4 +150,75 @@ public function testCancelQueryWillReturnRejectedPromiseWithoutCallingSecondaryE
152150 $ this ->assertInstanceOf ('React\Promise\PromiseInterface ' , $ promise );
153151 $ promise ->then ($ this ->expectCallableNever (), $ this ->expectCallableOnce ());
154152 }
153+
154+ public function testCancelQueryWillReturnRejectedPromiseWhenPrimaryExecutorRejectsAndSecondaryExecutorIsStillPending ()
155+ {
156+ $ query = new Query ('reactphp.org ' , Message::TYPE_A , Message::CLASS_IN );
157+
158+ $ primary = $ this ->getMockBuilder ('React\Dns\Query\ExecutorInterface ' )->getMock ();
159+ $ primary ->expects ($ this ->once ())->method ('query ' )->with ($ query )->willReturn (\React \Promise \reject (new \RuntimeException ()));
160+
161+ $ secondary = $ this ->getMockBuilder ('React\Dns\Query\ExecutorInterface ' )->getMock ();
162+ $ secondary ->expects ($ this ->once ())->method ('query ' )->with ($ query )->willReturn (new Promise (function () { }, function () { throw new \RuntimeException (); }));
163+
164+ $ executor = new FallbackExecutor ($ primary , $ secondary );
165+
166+ $ promise = $ executor ->query ($ query );
167+ $ promise ->cancel ();
168+
169+ $ this ->assertInstanceOf ('React\Promise\PromiseInterface ' , $ promise );
170+ $ promise ->then ($ this ->expectCallableNever (), $ this ->expectCallableOnce ());
171+ }
172+
173+ public function testCancelQueryShouldNotCauseGarbageReferencesWhenCancellingPrimaryExecutor ()
174+ {
175+ if (class_exists ('React\Promise\When ' )) {
176+ $ this ->markTestSkipped ('Not supported on legacy Promise v1 API ' );
177+ }
178+
179+ $ primary = $ this ->getMockBuilder ('React\Dns\Query\ExecutorInterface ' )->getMock ();
180+ $ primary ->expects ($ this ->once ())->method ('query ' )->willReturn (new Promise (function () { }, function () { throw new \RuntimeException (); }));
181+
182+ $ secondary = $ this ->getMockBuilder ('React\Dns\Query\ExecutorInterface ' )->getMock ();
183+ $ secondary ->expects ($ this ->never ())->method ('query ' );
184+
185+ $ executor = new FallbackExecutor ($ primary , $ secondary );
186+
187+ gc_collect_cycles ();
188+ gc_collect_cycles (); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on
189+
190+ $ query = new Query ('reactphp.org ' , Message::TYPE_A , Message::CLASS_IN );
191+
192+ $ promise = $ executor ->query ($ query );
193+ $ promise ->cancel ();
194+ $ promise = null ;
195+
196+ $ this ->assertEquals (0 , gc_collect_cycles ());
197+ }
198+
199+ public function testCancelQueryShouldNotCauseGarbageReferencesWhenCancellingSecondaryExecutor ()
200+ {
201+ if (class_exists ('React\Promise\When ' )) {
202+ $ this ->markTestSkipped ('Not supported on legacy Promise v1 API ' );
203+ }
204+
205+ $ primary = $ this ->getMockBuilder ('React\Dns\Query\ExecutorInterface ' )->getMock ();
206+ $ primary ->expects ($ this ->once ())->method ('query ' )->willReturn (\React \Promise \reject (new \RuntimeException ()));
207+
208+ $ secondary = $ this ->getMockBuilder ('React\Dns\Query\ExecutorInterface ' )->getMock ();
209+ $ secondary ->expects ($ this ->once ())->method ('query ' )->willReturn (new Promise (function () { }, function () { throw new \RuntimeException (); }));
210+
211+ $ executor = new FallbackExecutor ($ primary , $ secondary );
212+
213+ gc_collect_cycles ();
214+ gc_collect_cycles (); // clear twice to avoid leftovers in PHP 7.4 with ext-xdebug and code coverage turned on
215+
216+ $ query = new Query ('reactphp.org ' , Message::TYPE_A , Message::CLASS_IN );
217+
218+ $ promise = $ executor ->query ($ query );
219+ $ promise ->cancel ();
220+ $ promise = null ;
221+
222+ $ this ->assertEquals (0 , gc_collect_cycles ());
223+ }
155224}
0 commit comments