diff --git a/src/Ratchet/ConnectionInterface.php b/src/Ratchet/ConnectionInterface.php index 8a8ef34..a098f99 100644 --- a/src/Ratchet/ConnectionInterface.php +++ b/src/Ratchet/ConnectionInterface.php @@ -11,6 +11,7 @@ interface ConnectionInterface { /** * Send data to the connection * @param string + * @return ConnectionInterface */ function send($data); diff --git a/src/Ratchet/Server/IoConnection.php b/src/Ratchet/Server/IoConnection.php index 9eccab2..3fb241d 100644 --- a/src/Ratchet/Server/IoConnection.php +++ b/src/Ratchet/Server/IoConnection.php @@ -13,14 +13,16 @@ class IoConnection implements ConnectionInterface { protected $conn; public function __construct(ReactConn $conn) { - $this->conn = $conn; + $this->conn = $conn; } /** * {@inheritdoc} */ public function send($data) { - return $this->conn->write($data); + $this->conn->write($data); + + return $this; } /** diff --git a/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php b/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php index 51597ca..77bd4ae 100644 --- a/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php +++ b/tests/Ratchet/Tests/Server/FlashPolicyComponentTest.php @@ -17,6 +17,7 @@ class FlashPolicyTest extends \PHPUnit_Framework_TestCase { $this->_policy->setSiteControl('all'); $this->_policy->addAllowedAccess('example.com', '*'); $this->_policy->addAllowedAccess('dev.example.com', '*'); + $this->assertInstanceOf('SimpleXMLElement', $this->_policy->renderPolicy()); } @@ -108,4 +109,32 @@ class FlashPolicyTest extends \PHPUnit_Framework_TestCase { , array(false, '838*') ); } + + public function testAddAllowedAccessOnlyAcceptsValidPorts() { + $this->setExpectedException('UnexpectedValueException'); + + $this->_policy->addAllowedAccess('*', 'nope'); + } + + public function testSetSiteControlThrowsException() { + $this->setExpectedException('UnexpectedValueException'); + + $this->_policy->setSiteControl('nope'); + } + + public function testErrorClosesConnection() { + $conn = $this->getMock('\\Ratchet\\ConnectionInterface'); + $conn->expects($this->once())->method('close'); + + $this->_policy->onError($conn, new \Exception); + } + + public function testOnMessageSendsString() { + $this->_policy->addAllowedAccess('*', '*'); + + $conn = $this->getMock('\\Ratchet\\ConnectionInterface'); + $conn->expects($this->once())->method('send')->with($this->isType('string')); + + $this->_policy->onMessage($conn, ' '); + } } \ No newline at end of file diff --git a/tests/Ratchet/Tests/Server/IoConnectionTest.php b/tests/Ratchet/Tests/Server/IoConnectionTest.php new file mode 100644 index 0000000..d2ff568 --- /dev/null +++ b/tests/Ratchet/Tests/Server/IoConnectionTest.php @@ -0,0 +1,32 @@ +sock = $this->getMock('\\React\\Socket\\ConnectionInterface'); + $this->conn = new IoConnection($this->sock); + } + + public function testCloseBubbles() { + $this->sock->expects($this->once())->method('end'); + $this->conn->close(); + } + + public function testSendBubbles() { + $msg = '6 hour rides are productive'; + + $this->sock->expects($this->once())->method('write')->with($msg); + $this->conn->send($msg); + } + + public function testSendReturnsSelf() { + $this->assertSame($this->conn, $this->conn->send('fluent interface')); + } +} \ No newline at end of file diff --git a/tests/Ratchet/Tests/Server/IoServerTest.php b/tests/Ratchet/Tests/Server/IoServerTest.php index 63e0f51..d375da8 100644 --- a/tests/Ratchet/Tests/Server/IoServerTest.php +++ b/tests/Ratchet/Tests/Server/IoServerTest.php @@ -3,7 +3,6 @@ namespace Ratchet\Tests\Server; use Ratchet\Server\IoServer; use React\EventLoop\StreamSelectLoop; use React\Socket\Server; -use Ratchet\Tests\Mock\Component; /** * @covers Ratchet\Server\IoServer @@ -18,7 +17,7 @@ class IoServerTest extends \PHPUnit_Framework_TestCase { protected $reactor; public function setUp() { - $this->app = new Component; + $this->app = $this->getMock('\\Ratchet\\MessageComponentInterface'); $loop = new StreamSelectLoop; $this->reactor = new Server($loop); @@ -29,18 +28,24 @@ class IoServerTest extends \PHPUnit_Framework_TestCase { } public function testOnOpen() { + $this->app->expects($this->once())->method('onOpen')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface')); + $client = stream_socket_client("tcp://localhost:{$this->port}"); $this->server->loop->tick(); - $this->assertInstanceOf('\\Ratchet\\ConnectionInterface', $this->app->last['onOpen'][0]); - $this->assertTrue(is_string($this->app->last['onOpen'][0]->remoteAddress)); - $this->assertTrue(is_int($this->app->last['onOpen'][0]->resourceId)); + //$this->assertTrue(is_string($this->app->last['onOpen'][0]->remoteAddress)); + //$this->assertTrue(is_int($this->app->last['onOpen'][0]->resourceId)); } public function testOnData() { $msg = 'Hello World!'; + $this->app->expects($this->once())->method('onMessage')->with( + $this->isInstanceOf('\\Ratchet\\ConnectionInterface') + , $msg + ); + $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($client, SOL_SOCKET, SO_REUSEADDR, 1); socket_set_option($client, SOL_SOCKET, SO_SNDBUF, 4096); @@ -56,14 +61,12 @@ class IoServerTest extends \PHPUnit_Framework_TestCase { socket_shutdown($client, 0); socket_close($client); - usleep(5000); - $this->server->loop->tick(); - - $this->assertEquals($msg, $this->app->last['onMessage'][1]); } public function testOnClose() { + $this->app->expects($this->once())->method('onClose')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface')); + $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($client, SOL_SOCKET, SO_REUSEADDR, 1); socket_set_option($client, SOL_SOCKET, SO_SNDBUF, 4096); @@ -77,10 +80,6 @@ class IoServerTest extends \PHPUnit_Framework_TestCase { socket_close($client); $this->server->loop->tick(); - - usleep(5000); - - $this->assertSame($this->app->last['onOpen'][0], $this->app->last['onClose'][0]); } public function testFactory() { @@ -88,10 +87,32 @@ class IoServerTest extends \PHPUnit_Framework_TestCase { } public function testNoLoopProvidedError() { - $loop = new StreamSelectLoop; - $io = new IoServer(new Component, new Server($loop)); - $this->setExpectedException('RuntimeException'); + + $io = new IoServer($this->app, $this->reactor); $io->run(); } + + public function testOnErrorPassesException() { + $conn = $this->getMock('\\React\\Socket\\ConnectionInterface'); + $conn->decor = $this->getMock('\\Ratchet\\ConnectionInterface'); + $err = new \Exception("Nope"); + + $this->app->expects($this->once())->method('onError')->with($conn->decor, $err); + + $this->server->handleError($err, $conn); + } + + public function onErrorCalledWhenExceptionThrown() { + $this->markTestIncomplete("Need to learn how to throw an exception from a mock"); + + $conn = $this->getMock('\\React\\Socket\\ConnectionInterface'); + $this->server->handleConnect($conn); + + $e = new \Exception; + $this->app->expects($this->once())->method('onMessage')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface'), 'f')->will($e); + $this->app->expects($this->once())->method('onError')->with($this->instanceOf('\\Ratchet\\ConnectionInterface', $e)); + + $this->server->handleData('f', $conn); + } } \ No newline at end of file diff --git a/tests/Ratchet/Tests/Server/IpBlackListComponentTest.php b/tests/Ratchet/Tests/Server/IpBlackListComponentTest.php index 2d1f662..c847bce 100644 --- a/tests/Ratchet/Tests/Server/IpBlackListComponentTest.php +++ b/tests/Ratchet/Tests/Server/IpBlackListComponentTest.php @@ -1,29 +1,75 @@ _mock = new MockComponent; - $this->_comp = new IpBlackList($this->_mock); + $this->mock = $this->getMock('\\Ratchet\\MessageComponentInterface'); + $this->blocker = new IpBlackList($this->mock); } - public function testBlockAndCloseOnOpen() { - $conn = new Connection; + public function testOnOpen() { + $this->mock->expects($this->exactly(3))->method('onOpen'); - $this->_comp->blockAddress($conn->remoteAddress); + $conn1 = $this->newConn(); + $conn2 = $this->newConn(); + $conn3 = $this->newConn(); - $ret = $this->_comp->onOpen($conn); + $this->blocker->onOpen($conn1); + $this->blocker->onOpen($conn3); + $this->blocker->onOpen($conn2); + } - $this->assertTrue($conn->last['close']); + public function testBlockDoesNotTriggerOnOpen() { + $conn = $this->newConn(); + + $this->blocker->blockAddress($conn->remoteAddress); + + $this->mock->expects($this->never())->method('onOpen'); + + $ret = $this->blocker->onOpen($conn); + } + + public function testBlockDoesNotTriggerOnClose() { + $conn = $this->newConn(); + + $this->blocker->blockAddress($conn->remoteAddress); + + $this->mock->expects($this->never())->method('onClose'); + + $ret = $this->blocker->onOpen($conn); + } + + public function testOnMessageDecoration() { + $conn = $this->newConn(); + $msg = 'Hello not being blocked'; + + $this->mock->expects($this->once())->method('onMessage')->with($conn, $msg); + + $this->blocker->onMessage($conn, $msg); + } + + public function testOnCloseDecoration() { + $conn = $this->newConn(); + + $this->mock->expects($this->once())->method('onClose')->with($conn); + + $this->blocker->onClose($conn); + } + + public function testBlockClosesConnection() { + $conn = $this->newConn(); + $this->blocker->blockAddress($conn->remoteAddress); + + $conn->expects($this->once())->method('close'); + + $this->blocker->onOpen($conn); } public function testAddAndRemoveWithFluentInterfaces() { @@ -31,42 +77,23 @@ class IpBlackListTest extends \PHPUnit_Framework_TestCase { $blockTwo = '192.168.1.1'; $unblock = '75.119.207.140'; - $this->_comp + $this->blocker ->blockAddress($unblock) ->blockAddress($blockOne) ->unblockAddress($unblock) ->blockAddress($blockTwo) ; - $this->assertEquals(array($blockOne, $blockTwo), $this->_comp->getBlockedAddresses()); + $this->assertEquals(array($blockOne, $blockTwo), $this->blocker->getBlockedAddresses()); } - public function testDecoratingMethods() { - $conn1 = new Connection; - $conn2 = new Connection; - $conn3 = new Connection; + public function testDecoratorPassesErrors() { + $conn = $this->newConn(); + $e = new \Exception('I threw an error'); - $this->_comp->onOpen($conn1); - $this->_comp->onOpen($conn3); - $this->_comp->onOpen($conn2); - $this->assertSame($conn2, $this->_mock->last['onOpen'][0]); + $this->mock->expects($this->once())->method('onError')->with($conn, $e); - $msg = 'Hello World!'; - $this->_comp->onMessage($conn1, $msg); - $this->assertSame($conn1, $this->_mock->last['onMessage'][0]); - $this->assertEquals($msg, $this->_mock->last['onMessage'][1]); - - $this->_comp->onClose($conn3); - $this->assertSame($conn3, $this->_mock->last['onClose'][0]); - - try { - throw new \Exception('I threw an error'); - } catch (\Exception $e) { - } - - $this->_comp->onError($conn2, $e); - $this->assertEquals($conn2, $this->_mock->last['onError'][0]); - $this->assertEquals($e, $this->_mock->last['onError'][1]); + $this->blocker->onError($conn, $e); } public function addressProvider() { @@ -82,10 +109,17 @@ class IpBlackListTest extends \PHPUnit_Framework_TestCase { * @dataProvider addressProvider */ public function testFilterAddress($expected, $input) { - $this->assertEquals($expected, $this->_comp->filterAddress($input)); + $this->assertEquals($expected, $this->blocker->filterAddress($input)); } public function testUnblockingSilentlyFails() { - $this->assertInstanceOf('\\Ratchet\\Server\\IpBlackList', $this->_comp->unblockAddress('localhost')); + $this->assertInstanceOf('\\Ratchet\\Server\\IpBlackList', $this->blocker->unblockAddress('localhost')); + } + + protected function newConn() { + $conn = $this->getMock('\\Ratchet\\ConnectionInterface'); + $conn->remoteAddress = '127.0.0.1'; + + return $conn; } } \ No newline at end of file