Skip to content

Commit 13e4f4b

Browse files
committed
Merge pull request #7 from clue-labs/cancel
Support Promise cancellation
2 parents 6f5ab3f + 28b6b8e commit 13e4f4b

3 files changed

Lines changed: 53 additions & 14 deletions

File tree

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818
"clue/multicast-react": "~1.0|~0.2.0",
1919
"react/event-loop": "~0.4.0|~0.3.0",
2020
"react/dns": "~0.4.0|~0.3.0",
21-
"react/promise": "~2.0|~1.0"
21+
"react/promise": "^2.1 || ^1.2.1"
2222
}
2323
}

src/MulticastExecutor.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ public function doQuery($nameserver, $queryData, $name)
7272
$parser = $this->parser;
7373
$loop = $this->loop;
7474

75-
$deferred = new Deferred();
75+
$deferred = new Deferred(function ($_, $reject) use (&$conn, &$timer, $name) {
76+
$conn->close();
77+
$timer->cancel();
78+
79+
$reject(new \RuntimeException(sprintf("DNS query for %s cancelled", $name)));
80+
});
7681

7782
$timer = $this->loop->addTimer($this->timeout, function () use (&$conn, $name, $deferred) {
7883
$conn->close();

tests/MulticastExecutorTest.php

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,63 @@
33
use Clue\React\Mdns\MulticastExecutor;
44
use Clue\React\Mdns\Factory;
55
use React\Dns\Query\Query;
6+
67
class MulticastExecutorTest extends TestCase
78
{
8-
public function testA()
9-
{
10-
$nameserver = Factory::DNS;
9+
private $nameserver;
10+
private $loop;
11+
private $parser;
12+
private $dumper;
13+
private $sockets;
1114

12-
$loop = $this->getMock('React\EventLoop\LoopInterface');
13-
$parser = $this->getMock('React\Dns\Protocol\Parser');
14-
$dumper = $this->getMock('React\Dns\Protocol\BinaryDumper');
15-
$sockets = $this->getMockBuilder('Clue\React\Multicast\Factory')->disableOriginalConstructor()->getMock();
15+
public function setUp()
16+
{
17+
$this->nameserver = Factory::DNS;
18+
$this->loop = $this->getMock('React\EventLoop\LoopInterface');
19+
$this->parser = $this->getMock('React\Dns\Protocol\Parser');
20+
$this->dumper = $this->getMock('React\Dns\Protocol\BinaryDumper');
21+
$this->sockets = $this->getMockBuilder('Clue\React\Multicast\Factory')->disableOriginalConstructor()->getMock();
22+
}
1623

17-
$executor = new MulticastExecutor($loop, $parser, $dumper, 5, $sockets);
24+
public function testQueryWillReturnPromise()
25+
{
26+
$executor = new MulticastExecutor($this->loop, $this->parser, $this->dumper, 5, $this->sockets);
1827

1928
$socket = $this->getMock('React\Datagram\SocketInterface');
2029

21-
$dumper->expects($this->once())->method('toBinary')->will($this->returnValue('message'));
22-
$sockets->expects($this->once())->method('createSender')->will($this->returnValue($socket));
30+
$this->dumper->expects($this->once())->method('toBinary')->will($this->returnValue('message'));
31+
$this->sockets->expects($this->once())->method('createSender')->will($this->returnValue($socket));
2332

24-
$socket->expects($this->once())->method('send')->with($this->equalTo('message'), $this->equalTo($nameserver));
33+
$socket->expects($this->once())->method('send')->with($this->equalTo('message'), $this->equalTo($this->nameserver));
2534

2635
$query = new Query('name', 'type', 'class', time());
2736

28-
$ret = $executor->query($nameserver, $query);
37+
$ret = $executor->query($this->nameserver, $query);
2938
$this->assertInstanceOf('React\Promise\PromiseInterface', $ret);
3039
}
40+
41+
public function testCancellingPromiseWillCloseSocketAndReject()
42+
{
43+
$executor = new MulticastExecutor($this->loop, $this->parser, $this->dumper, 5, $this->sockets);
44+
45+
$socket = $this->getMock('React\Datagram\SocketInterface');
46+
$socket->expects($this->once())->method('close');
47+
$socket->expects($this->once())->method('send')->with($this->equalTo('message'), $this->equalTo($this->nameserver));
48+
$this->sockets->expects($this->once())->method('createSender')->will($this->returnValue($socket));
49+
50+
$timer = $this->getMock('React\EventLoop\Timer\TimerInterface');
51+
$timer->expects($this->once())->method('cancel');
52+
$this->loop->expects($this->once())->method('addTimer')->willReturn($timer);
53+
54+
$this->dumper->expects($this->once())->method('toBinary')->will($this->returnValue('message'));
55+
56+
$query = new Query('name', 'type', 'class', time());
57+
58+
$ret = $executor->query($this->nameserver, $query);
59+
$this->assertInstanceOf('React\Promise\CancellablePromiseInterface', $ret);
60+
61+
$ret->cancel();
62+
63+
$ret->then($this->expectCallableNever(), $this->expectCallableOnceParameter('RuntimeException'));
64+
}
3165
}

0 commit comments

Comments
 (0)