Skip to content

Commit

Permalink
Add keep alive ping support test
Browse files Browse the repository at this point in the history
  • Loading branch information
kadet1090 committed Feb 28, 2017
1 parent fcee472 commit af9966d
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 5 deletions.
22 changes: 20 additions & 2 deletions Component/PingKeepAlive.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,18 @@

use Kadet\Xmpp\Stanza\Iq;
use Kadet\Xmpp\XmppClient;
use \Kadet\Xmpp\Utils\filter as with;
use React\EventLoop\Timer\TimerInterface;

class PingKeepAlive extends Component
{
/** @var float|int */
private $_interval = 15;
/** @var TimerInterface */
private $_timer;

private $_handler = null;

/**
* PingKeepAlive constructor.
*
Expand All @@ -38,8 +43,11 @@ public function __construct($interval = 15.)
public function setClient(XmppClient $client)
{
parent::setClient($client);

$this->_client->on('state', [$this, 'enable'], \Kadet\Xmpp\Utils\filter\equals('ready'));

$this->_handler = $this->_client->on('iq', function(Iq $iq) {
$this->handleIq($iq);
}, with\iq\query(with\element('ping', 'urn:xmpp:ping')));
}

/**
Expand All @@ -57,7 +65,8 @@ public function enable()
*/
public function disable()
{
$this->_client->connector->getLoop()->cancelTimer($this->_timer);
$this->_timer->cancel();
$this->_client->removeListener('iq', $this->_handler);
}

private function keepAlive()
Expand All @@ -66,4 +75,13 @@ private function keepAlive()

$this->_client->write($ping);
}

private function handleIq(Iq $iq)
{
$response = $iq->response();
$response->type = 'result';
$response->query = new Iq\Query('urn:xmpp:ping', 'ping');

$this->_client->write($response);
}
}
2 changes: 1 addition & 1 deletion Component/Roster.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ private function handleResult(Iq\Query\Roster $query)
{
$this->_client->getLogger()->debug(format('Received roster (version: {version}) update with {no} roster items.', [
'no' => count($query->items),
'version' => $query->version
'version' => $query->version ?: 'no version'
]));

$this->_items = [];
Expand Down
92 changes: 92 additions & 0 deletions Tests/Modules/PingKeepAliveTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
/**
* Nucleus - XMPP Library for PHP
*
* Copyright (C) 2017, Some rights reserved.
*
* @author Kacper "Kadet" Donat <[email protected]>
*
* Contact with author:
* Xmpp: [email protected]
* E-mail: [email protected]
*
* From Kadet with love.
*/

namespace Kadet\Xmpp\Tests\Modules;


use Kadet\Xmpp\Component\PingKeepAlive;
use Kadet\Xmpp\Jid;
use Kadet\Xmpp\Stanza\Iq;
use Kadet\Xmpp\Stanza\Iq\Query;
use Kadet\Xmpp\Tests\Stubs\ConnectorStub;
use Kadet\Xmpp\XmppClient;
use React\EventLoop\LoopInterface;


class PingKeepAliveTest extends \PHPUnit_Framework_TestCase
{
public function testKeepAliveTimer()
{
/** @var LoopInterface|\PHPUnit_Framework_MockObject_MockObject $loop */
$loop = $this->getMockBuilder(LoopInterface::class)->setMethods(['addPeriodicTimer'])->getMockForAbstractClass();
$loop->expects($this->once())->method('addPeriodicTimer')->withConsecutive($this->greaterThan(1.0), $this->callback(function($callback) {
return is_callable($callback);
}));

$this->getMockClient($loop)->emit('state', ['ready']);
}

public function testKeepAliveTick()
{
/** @var LoopInterface|\PHPUnit_Framework_MockObject_MockObject $loop */
$loop = $this->getMockBuilder(LoopInterface::class)->setMethods(['addPeriodicTimer'])->getMockForAbstractClass();

/** @var callable $tick */
$tick = null;
$loop->method('addPeriodicTimer')->willReturnCallback(function($_, $callback) use(&$tick) {
$tick = $callback;
});

$client = $this->getMockClient($loop);
$client->expects($this->once())->method('write')->withConsecutive($this->callback(
\Kadet\Xmpp\Utils\filter\iq\query(\Kadet\Xmpp\Utils\filter\element('ping', 'urn:xmpp:ping'))
));

$client->emit('state', ['ready']);

$tick();
}

public function testPingResponse()
{
$iq = new Iq('get', ['id' => 'testme', 'query' => new Query('urn:xmpp:ping', 'ping')]);

$client = $this->getMockClient();
$client->expects($this->once())->method('write')->withConsecutive(\Kadet\Xmpp\Utils\filter\all(
\Kadet\Xmpp\Utils\filter\stanza\type('result'),
\Kadet\Xmpp\Utils\filter\stanza\id('testme'),
\Kadet\Xmpp\Utils\filter\iq\query(\Kadet\Xmpp\Utils\filter\element('ping', 'urn:xmpp:ping'))
));

$client->emit('element', [ $iq ]);
}

/**
* @param LoopInterface $loop
* @return XmppClient|\PHPUnit_Framework_MockObject_MockObject
*/
private function getMockClient(LoopInterface $loop = null)
{
return $this->getMockBuilder(XmppClient::class)
->setConstructorArgs([new Jid('[email protected]'), [
'connector' => new ConnectorStub(null, $loop),
'default-modules' => false,
'modules' => [
new PingKeepAlive()
]
]])->setMethods(['write'])
->getMock();
}
}
6 changes: 4 additions & 2 deletions Tests/Stubs/ConnectorStub.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ class ConnectorStub implements Connector
/**
* ConnectorStub constructor.
* @param DuplexStreamInterface $stream Stream returned in connect
* @param LoopInterface $loop
*/
public function __construct(DuplexStreamInterface $stream = null)
public function __construct(DuplexStreamInterface $stream = null, LoopInterface $loop = null)
{
$this->_loop = Factory::create();
$this->_loop = $loop ?? Factory::create();

$this->_stream = $stream ?: new CompositeStream(
new ThroughStream(),
new ThroughStream()
Expand Down

0 comments on commit af9966d

Please sign in to comment.