[WAMP] Cleanup

Removed all Command classes (WAMP and global)
We-wrote WAMP unit tests to match
refs #22
This commit is contained in:
Chris Boden 2012-05-07 20:59:47 -04:00
parent bbea3e8e05
commit d9bc1af385
20 changed files with 208 additions and 645 deletions

View File

@ -90,17 +90,17 @@ class IpBlackListComponent implements MessageComponentInterface {
* {@inheritdoc} * {@inheritdoc}
*/ */
function onClose(ConnectionInterface $conn) { function onClose(ConnectionInterface $conn) {
if ($this->isBlocked($conn->remoteAddress)) { if (!$this->isBlocked($conn->remoteAddress)) {
return null; $this->_decorating->onClose($conn);
} }
return $this->_decorating->onClose($conn);
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
function onError(ConnectionInterface $conn, \Exception $e) { function onError(ConnectionInterface $conn, \Exception $e) {
return $this->_decorating->onError($conn, $e); if (!$this->isBlocked($conn->remoteAddress)) {
$this->_decorating->onError($conn, $e);
}
} }
} }

View File

@ -2,11 +2,6 @@
namespace Ratchet\Component\WAMP; namespace Ratchet\Component\WAMP;
use Ratchet\Component\WebSocket\WebSocketComponentInterface; use Ratchet\Component\WebSocket\WebSocketComponentInterface;
use Ratchet\Resource\ConnectionInterface; use Ratchet\Resource\ConnectionInterface;
use Ratchet\Resource\Command\Composite;
use Ratchet\Resource\Command\CommandInterface;
use Ratchet\Resource\Command\Factory as CmdFactory;
use Ratchet\Component\WAMP\Command\Action\Prefix;
use Ratchet\Component\WAMP\Command\Action\Welcome;
/** /**
* WebSocket Application Messaging Protocol * WebSocket Application Messaging Protocol
@ -45,11 +40,17 @@ class WAMPServerComponent implements WebSocketComponentInterface {
protected $_decorating; protected $_decorating;
/** /**
* Any server to client prefixes are stored here * @var SplObjectStorage
* They're taxied along with the next outgoing message
* @var Ratchet\Resource\Command\Composite
*/ */
protected $_msg_buffer = null; protected $connections;
/**
* @param WAMPServerComponentInterface An class to propagate calls through
*/
public function __construct(WAMPServerComponentInterface $server_component) {
$this->_decorating = $server_component;
$this->connections = new \SplObjectStorage;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
@ -58,43 +59,14 @@ class WAMPServerComponent implements WebSocketComponentInterface {
return 'wamp'; return 'wamp';
} }
/**
* @todo WAMP spec does not say what to do when there is an error with PREFIX...
*/
public function addPrefix(ConnectionInterface $conn, $curie, $uri, $from_server = false) {
// validate uri
// validate curie
// make sure the curie is shorter than the uri
$conn->WAMP->prefixes[$curie] = $uri;
if ($from_server) {
$prefix = new Prefix($conn);
$prefix->setPrefix($curie, $uri);
$this->_msg_buffer->enqueue($prefix);
}
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function onOpen(ConnectionInterface $conn) { public function onOpen(ConnectionInterface $conn) {
$conn->WAMP = new \StdClass; $decor = new WampConnection($conn);
$conn->WAMP->sessionId = uniqid(); $this->connections->attach($conn, $decor);
$conn->WAMP->prefixes = array();
$wamp = $this; $this->_decorating->onOpen($decor);
$conn->WAMP->addPrefix = function($curie, $uri) use ($wamp, $conn) {
$wamp->addPrefix($conn, $curie, $uri, true);
};
$welcome = new Welcome($conn);
$welcome->setWelcome($conn->WAMP->sessionId, \Ratchet\Resource\VERSION);
$this->_msg_buffer->enqueue($welcome);
return $this->attachStack($this->_decorating->onOpen($conn));
} }
/** /**
@ -103,13 +75,16 @@ class WAMPServerComponent implements WebSocketComponentInterface {
* @throws JSONException * @throws JSONException
*/ */
public function onMessage(ConnectionInterface $from, $msg) { public function onMessage(ConnectionInterface $from, $msg) {
$from = $this->connections[$from];
if (null === ($json = @json_decode($msg, true))) { if (null === ($json = @json_decode($msg, true))) {
throw new JSONException; throw new JSONException;
} }
switch ($json[0]) { switch ($json[0]) {
case static::MSG_PREFIX: case static::MSG_PREFIX:
$ret = $this->addPrefix($from, $json[1], $json[2]); $from->WAMP->prefixes[$json[1]] = $json[2];
// $from->WAMP->prefixes($json[1], $json[2]);
break; break;
case static::MSG_CALL: case static::MSG_CALL:
@ -121,74 +96,40 @@ class WAMPServerComponent implements WebSocketComponentInterface {
$json = $json[0]; $json = $json[0];
} }
$ret = $this->_decorating->onCall($from, $callID, $procURI, $json); $this->_decorating->onCall($from, $callID, $procURI, $json);
break; break;
case static::MSG_SUBSCRIBE: case static::MSG_SUBSCRIBE:
$ret = $this->_decorating->onSubscribe($from, $this->getUri($from, $json[1])); $this->_decorating->onSubscribe($from, $from->getUri($json[1]));
break; break;
case static::MSG_UNSUBSCRIBE: case static::MSG_UNSUBSCRIBE:
$ret = $this->_decorating->onUnSubscribe($from, $this->getUri($from, $json[1])); $this->_decorating->onUnSubscribe($from, $from->getUri($json[1]));
break; break;
case static::MSG_PUBLISH: case static::MSG_PUBLISH:
$ret = $this->_decorating->onPublish($from, $this->getUri($from, $json[1]), $json[2]); $this->_decorating->onPublish($from, $from->getUri($json[1]), $json[2]);
break; break;
default: default:
throw new Exception('Invalid message type'); throw new Exception('Invalid message type');
} }
return $this->attachStack($ret);
}
/**
* Get the full request URI from the connection object if a prefix has been established for it
* @param Ratchet\Resource\Connection
* @param ...
* @return string
*/
protected function getUri(ConnectionInterface $conn, $uri) {
return (isset($conn->WAMP->prefixes[$uri]) ? $conn->WAMP->prefixes[$uri] : $uri);
}
/**
* If the developer's application as set some server-to-client prefixes to be set,
* this method ensures those are taxied to the next outgoing message
* @param Ratchet\Resource\Command\CommandInterface|NULL
* @return Ratchet\Resource\Command\Composite
*/
protected function attachStack(CommandInterface $command = null) {
$stack = $this->_msg_buffer;
$stack->enqueue($command);
$this->_msg_buffer = new Composite;
return $stack;
}
/**
* @param WAMPServerComponentInterface An class to propagate calls through
*/
public function __construct(WAMPServerComponentInterface $server_component) {
CmdFactory::registerActionPath(__NAMESPACE__ . '\\Command\\Action');
$this->_decorating = $server_component;
$this->_msg_buffer = new Composite;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function onClose(ConnectionInterface $conn) { public function onClose(ConnectionInterface $conn) {
return $this->_decorating->onClose($conn); $decor = $this->connections[$conn];
$this->connections->detach($conn);
$this->_decorating->onClose($decor);
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function onError(ConnectionInterface $conn, \Exception $e) { public function onError(ConnectionInterface $conn, \Exception $e) {
return $this->_decorating->onError($conn, $e); return $this->_decorating->onError($this->connections[$conn], $e);
} }
} }

View File

@ -1,36 +1,83 @@
<?php <?php
namespace Ratchet\Component\WAMP\Resource; namespace Ratchet\Component\WAMP;
use Ratchet\Resource\ConnectionInterface;
use Ratchet\Resource\AbstractConnectionDecorator; use Ratchet\Resource\AbstractConnectionDecorator;
use Ratchet\Component\WAMP\WAMPServerComponent as WAMP; use Ratchet\Component\WAMP\WAMPServerComponent as WAMP;
/** /**
* @property stdClass $WAMP * @property stdClass $WAMP
*/ */
class Connection extends AbstractConnectionDecorator { class WampConnection extends AbstractConnectionDecorator {
public function __construct() { public function __construct(ConnectionInterface $conn) {
parent::__construct($conn);
$this->WAMP = new \StdClass; $this->WAMP = new \StdClass;
$this->WAMP->sessionId = uniqid(); $this->WAMP->sessionId = uniqid();
$this->WAMP->prefixes = array(); $this->WAMP->prefixes = array();
$this->getConnection()->send(json_encode(array(WAMP::MSG_WELCOME, $this->WAMP->sessionId, 1, \Ratchet\Resource\VERSION))); $this->send(json_encode(array(WAMP::MSG_WELCOME, $this->WAMP->sessionId, 1, \Ratchet\Resource\VERSION)));
} }
public function callResponse() { /**
* @param string The unique ID given by the client to respond to
* @param array An array of data to return to the client
*/
public function callResult($id, array $data = array()) {
$this->send(json_encode(array(WAMP::MSG_CALL_RESULT, $id, $data)));
} }
public function callError() { /**
* @param string The unique ID given by the client to respond to
* @param string The URI given by the client ot respond to
* @param string A developer-oriented description of the error
* @param string|null An optional human readable detail message to send back
*/
public function callError($id, $uri, $desc = '', $details = null) {
$data = array(WAMP::MSG_CALL_ERROR, $id, $uri, $desc);
if (null !== $details) {
$data[] = $details;
} }
public function event() { $this->send(json_encode($data));
} }
public function addPrefix($curie, $uri) { /**
* @param string The URI or CURIE to broadcast to
* @param mixed Data to send with the event. Anything that is json'able
*/
public function event($uri, $msg) {
$this->send(json_encode(array(WAMP::MSG_EVENT, $uri, $msg)));
} }
/**
* @param string
* @param string
*/
public function prefix($curie, $uri) {
$this->WAMP->prefixes[$curie] = $uri;
$this->send(json_encode(array(WAMP::MSG_PREFIX, $curie, $uri)));
}
/**
* Get the full request URI from the connection object if a prefix has been established for it
* @param string
* @return string
*/
public function getUri($uri) {
return (isset($this->WAMP->prefixes[$uri]) ? $this->WAMP->prefixes[$uri] : $uri);
}
/**
* @internal
*/
public function send($data) { public function send($data) {
$this->getConnection()->send($data); $this->getConnection()->send($data);
} }
/**
* {@inheritdoc}
*/
public function close() { public function close() {
$this->getConnection()->close(); $this->getConnection()->close();
} }

View File

@ -138,8 +138,10 @@ class WebSocketComponent implements MessageComponentInterface {
// WS::onOpen is not called when the socket connects, it's call when the handshake is done // WS::onOpen is not called when the socket connects, it's call when the handshake is done
// The socket could close before WS calls onOpen, so we need to check if we've "opened" it for the developer yet // The socket could close before WS calls onOpen, so we need to check if we've "opened" it for the developer yet
if ($this->connections->contains($conn)) { if ($this->connections->contains($conn)) {
$this->_decorating->onClose($this->connections[$conn]); $decor = $this->connections[$conn];
$this->connections->detach($conn); $this->connections->detach($conn);
$this->_decorating->onClose($decor);
} }
} }

View File

@ -1,20 +0,0 @@
<?php
namespace Ratchet\Resource\Command\Action;
use Ratchet\Resource\ConnectionInterface;
use Ratchet\Resource\Command\CommandInterface;
/**
* A single command tied to 1 socket connection
*/
interface ActionInterface extends CommandInterface {
/**
* Pass the Sockets to execute the command on
* @param Ratchet\Resource\Connection
*/
function __construct(ConnectionInterface $conn);
/**
* @return Ratchet\Command\Connection
*/
function getConnection();
}

View File

@ -1,18 +0,0 @@
<?php
namespace Ratchet\Resource\Command\Action;
use Ratchet\Resource\ConnectionInterface;
abstract class ActionTemplate implements ActionInterface {
/**
* @var Ratchet\Resource\Connection
*/
protected $_conn;
public function __construct(ConnectionInterface $conn) {
$this->_conn = $conn;
}
public function getConnection() {
return $this->_conn;
}
}

View File

@ -1,31 +0,0 @@
<?php
namespace Ratchet\Resource\Command\Action;
use Ratchet\Component\ComponentInterface;
use Ratchet\Resource\ConnectionInterface;
use Ratchet\Resource\Command\CommandInterface;
use Ratchet\Resource\Command\Composite;
/**
* Close the connection to the sockets passed in the constructor
*/
class CloseConnection extends ActionTemplate {
function execute(ComponentInterface $scope = null) {
// All this code allows an application to have its onClose method executed before the socket is actually closed
$ret = $scope->onClose($this->getConnection());
if ($ret instanceof CommandInterface) {
$comp = new Composite;
$comp->enqueue($ret);
$rt = new Runtime($this->getConnection());
$rt->setCommand(function(ConnectionInterface $conn, ComponentInterface $scope) {
$conn->getSocket()->close();
});
$comp->enqueue($rt);
return $comp;
}
$this->getConnection()->getSocket()->close();
}
}

View File

@ -1,11 +0,0 @@
<?php
namespace Ratchet\Resource\Command\Action;
use Ratchet\Component\ComponentInterface;
/**
* Null pattern - execution does nothing, used when something needs to be passed back
*/
class Null extends ActionTemplate {
public function execute(ComponentInterface $scope = null) {
}
}

View File

@ -1,31 +0,0 @@
<?php
namespace Ratchet\Resource\Command\Action;
use Ratchet\Component\ComponentInterface;
/**
* This allows you to create a run-time command by using a closure
*/
class Runtime extends ActionTemplate {
/**
* The stored closure command to execude
* @var Closure
*/
protected $_command = null;
/**
* Your closure should accept two parameters (\Ratchet\Resource\Connection, \Ratchet\Component\ComponentInterface) parameter and return a CommandInterface or NULL
* @param Closure Your closure/lambda to execute when the time comes
*/
public function setCommand(\Closure $callback) {
$this->_command = $callback;
}
/**
* {@inheritdoc}
*/
public function execute(ComponentInterface $scope = null) {
$cmd = $this->_command;
return $cmd($this->getConnection(), $scope);
}
}

View File

@ -1,43 +0,0 @@
<?php
namespace Ratchet\Resource\Command\Action;
use Ratchet\Component\ComponentInterface;
/**
* Send text back to the client end of the socket(s)
*/
class SendMessage extends ActionTemplate {
/**
* @var string
*/
protected $_message = '';
/**
* The message to send to the socket(s)
* @param string
* @return SendMessage Fluid interface
*/
public function setMessage($msg) {
$this->_message = (string)$msg;
return $this;
}
/**
* Get the message from setMessage()
* @return string
*/
public function getMessage() {
return $this->_message;
}
/**
* {@inheritdoc}
* @throws \UnexpectedValueException if a message was not set with setMessage()
*/
public function execute(ComponentInterface $scope = null) {
if (empty($this->_message)) {
throw new \UnexpectedValueException("Message is empty");
}
$this->getConnection()->getSocket()->deliver($this->_message);
}
}

View File

@ -1,16 +0,0 @@
<?php
namespace Ratchet\Resource\Command;
use Ratchet\Component\ComponentInterface;
/**
* Socket implementation of the Command Pattern
* User created applications are to return a Command to the server for execution
*/
interface CommandInterface {
/**
* The Server class will call the execution
* @param Ratchet\ComponentInterface Scope to execute the command under
* @return CommandInterface|NULL
*/
function execute(ComponentInterface $scope = null);
}

View File

@ -1,47 +0,0 @@
<?php
namespace Ratchet\Resource\Command;
use Ratchet\Component\ComponentInterface;
class Composite extends \SplQueue implements CommandInterface {
/**
* Add another Command to the stack
* Unlike a true composite the enqueue flattens a composite parameter into leafs
* @param CommandInterface|null
*/
public function enqueue($command) {
if (null === $command) {
return;
}
if (!($command instanceof CommandInterface)) {
throw new \InvalidArgumentException("Parameter MUST implement Ratchet.Component.CommandInterface");
}
if ($command instanceof self) {
foreach ($command as $cmd) {
$this->enqueue($cmd);
}
return;
}
parent::enqueue($command);
}
/**
* {@inheritdoc}
*/
public function execute(ComponentInterface $scope = null) {
$this->setIteratorMode(static::IT_MODE_DELETE);
$recursive = new self;
foreach ($this as $command) {
$recursive->enqueue($command->execute($scope));
}
if (count($recursive) > 0) {
return $recursive;
}
}
}

View File

@ -1,82 +0,0 @@
<?php
namespace Ratchet\Resource\Command;
use Ratchet\Resource\ConnectionInterface;
/**
* A factory pattern class to easily create all the things in the Ratchet\Resource\Command interface
*/
class Factory {
protected $_paths = array();
protected $_mapped_commands = array();
protected static $globalPaths = array();
protected $_ignoreGlobals = false;
/**
* @param bool If set to TRUE this will ignore all the statically registered namespaces
*/
public function __construct($ignoreGlobals = false) {
$this->addActionPath(__NAMESPACE__ . '\\Action');
$this->_ignoreGlobals = (boolean)$ignoreGlobals;
}
/**
* Add a new namespace of which CommandInterfaces reside under to autoload with $this->newCommand()
* @param string
*/
public function addActionPath($namespace) {
$this->_paths[] = $this->slashIt($namespace);
}
public static function registerActionPath($namespace) {
static::$globalPaths[$namespace] = 1;
}
/**
* @return Composite
*/
public function newComposite() {
return new Composite;
}
/**
* @param string
* @return CommandInterface
* @throws UnexpectedValueException
*/
public function newCommand($name, ConnectionInterface $conn) {
if (isset($this->_mapped_commands[$name])) {
$cmd = $this->_mapped_commands[$name];
return new $cmd($conn);
}
foreach ($this->_paths as $path) {
if (class_exists($path . $name)) {
$this->_mapped_commands[$name] = $path . $name;
return $this->newCommand($name, $conn);
}
}
if (false === $this->_ignoreGlobals) {
foreach (static::$globalPaths as $path => $one) {
$path = $this->slashIt($path);
if (class_exists($path . $name)) {
$this->_mapped_commands[$name] = $path . $name;
return $this->newCommand($name, $conn);
}
}
}
throw new \UnexepctedValueException("Command {$name} not found");
}
/**
* @param string
* @return string
*/
protected function slashIt($ns) {
return (substr($ns, -1) == '\\' ? $ns : $ns . '\\');
}
}

View File

@ -1,72 +0,0 @@
<?php
namespace Ratchet\Tests\Component\WAMP\Command\Action;
use Ratchet\Component\WAMP\Command\Action\CallError;
use Ratchet\Tests\Mock\Connection;
/**
* @covers Ratchet\Component\WAMP\Command\Action\CallError
*/
class CallErrorTest extends \PHPUnit_Framework_TestCase {
public function testCallError() {
$error = new CallError(new Connection);
$callId = uniqid();
$uri = 'http://example.com/end/point';
$error->setError($callId, $uri);
$resultString = $error->getMessage();
$this->assertEquals(array(4, $callId, $uri, ''), json_decode($resultString, true));
}
public function testDetailedCallError() {
$error = new CallError(new Connection);
$callId = uniqid();
$uri = 'http://example.com/end/point';
$desc = 'beep boop beep';
$detail = 'Error: Too much awesome';
$error->setError($callId, $uri, $desc, $detail);
$resultString = $error->getMessage();
$this->assertEquals(array(4, $callId, $uri, $desc, $detail), json_decode($resultString, true));
}
public function testGetId() {
$id = uniqid();
$error = new CallError(new Connection);
$error->setError($id, 'http://example.com');
$this->assertEquals($id, $error->getId());
}
public function testGetUri() {
$uri = 'http://example.com/end/point';
$error = new CallError(new Connection);
$error->setError(uniqid(), $uri);
$this->assertEquals($uri, $error->getUri());
}
public function testGetDescription() {
$desc = uniqid();
$error = new CallError(new Connection);
$error->setError(uniqid(), 'curie', $desc);
$this->assertEquals($desc, $error->getDescription());
}
public function testGetDetails() {
$detail = uniqid();
$error = new CallError(new Connection);
$this->assertNull($error->getDetails());
$error->setError(uniqid(), 'http://socketo.me', 'desc', $detail);
$this->assertEquals($detail, $error->getDetails());
}
}

View File

@ -1,46 +0,0 @@
<?php
namespace Ratchet\Tests\Component\WAMP\Command\Action;
use Ratchet\Component\WAMP\Command\Action\CallResult;
use Ratchet\Tests\Mock\Connection;
/**
* @covers Ratchet\Component\WAMP\Command\Action\CallResult
*/
class CallResultTest extends \PHPUnit_Framework_TestCase {
public function testGetMessage() {
$result = new CallResult(new Connection);
$callId = uniqid();
$data = array('hello' => 'world', 'herp' => 'derp');
$result->setResult($callId, $data);
$resultString = $result->getMessage();
$this->assertEquals(array(3, $callId, $data), json_decode($resultString, true));
}
public function testGetId() {
$id = uniqid();
$result = new CallResult(new Connection);
$result->setResult($id, array());
$this->assertEquals($id, $result->getId());
}
public function testGetData() {
$data = array(
'hello' => 'world'
, 'recursive' => array(
'the' => 'quick'
, 'brown' => 'fox'
)
, 'jumps'
);
$result = new CallResult(new Connection);
$result->setResult(uniqid(), $data);
$this->assertEquals($data, $result->getData());
}
}

View File

@ -1,15 +1,14 @@
<?php <?php
namespace Ratchet\Tests\Component\WAMP; namespace Ratchet\Tests\Component\WAMP;
use Ratchet\Component\WAMP\WAMPServerComponent; use Ratchet\Component\WAMP\WAMPServerComponent;
use Ratchet\Component\WAMP\WampConnection;
use Ratchet\Tests\Mock\Connection; use Ratchet\Tests\Mock\Connection;
use Ratchet\Tests\Mock\WAMPComponent as TestComponent; use Ratchet\Tests\Mock\WAMPComponent as TestComponent;
use Ratchet\Component\WAMP\Command\Action\CallResult;
use Ratchet\Component\WAMP\Command\Action\CallError;
use Ratchet\Component\WAMP\Command\Action\Event;
/** /**
* @covers Ratchet\Component\WAMP\WAMPServerComponent * @covers Ratchet\Component\WAMP\WAMPServerComponent
* @covers Ratchet\Component\WAMP\WAMPServerComponentInterface * @covers Ratchet\Component\WAMP\WAMPServerComponentInterface
* @covers Ratchet\Component\WAMP\WampConnection
*/ */
class WAMPServerComponentTest extends \PHPUnit_Framework_TestCase { class WAMPServerComponentTest extends \PHPUnit_Framework_TestCase {
protected $_comp; protected $_comp;
@ -41,18 +40,17 @@ class WAMPServerComponentTest extends \PHPUnit_Framework_TestCase {
public function testInvalidMessages($type) { public function testInvalidMessages($type) {
$this->setExpectedException('\\Ratchet\\Component\\WAMP\\Exception'); $this->setExpectedException('\\Ratchet\\Component\\WAMP\\Exception');
$this->_comp->onMessage($this->newConn(), json_encode(array($type))); $conn = $this->newConn();
$this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, json_encode(array($type)));
} }
/**
* @covers Ratchet\Component\WAMP\Command\Action\Welcome
*/
public function testWelcomeMessage() { public function testWelcomeMessage() {
$conn = new Connection(); $conn = $this->newConn();
$return = $this->_comp->onOpen($conn); $this->_comp->onOpen($conn);
$action = $return->pop();
$message = $action->getMessage(); $message = $conn->last['send'];
$json = json_decode($message); $json = json_decode($message);
$this->assertEquals(4, count($json)); $this->assertEquals(4, count($json));
@ -65,7 +63,10 @@ class WAMPServerComponentTest extends \PHPUnit_Framework_TestCase {
$uri = 'http://example.com'; $uri = 'http://example.com';
$clientMessage = array(5, $uri); $clientMessage = array(5, $uri);
$this->_comp->onMessage($this->newConn(), json_encode($clientMessage)); $conn = $this->newConn();
$this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, json_encode($clientMessage));
$this->assertEquals($uri, $this->_app->last['onSubscribe'][1]); $this->assertEquals($uri, $this->_app->last['onSubscribe'][1]);
} }
@ -74,7 +75,10 @@ class WAMPServerComponentTest extends \PHPUnit_Framework_TestCase {
$uri = 'http://example.com/endpoint'; $uri = 'http://example.com/endpoint';
$clientMessage = array(6, $uri); $clientMessage = array(6, $uri);
$this->_comp->onMessage($this->newConn(), json_encode($clientMessage)); $conn = $this->newConn();
$this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, json_encode($clientMessage));
$this->assertEquals($uri, $this->_app->last['onUnSubscribe'][1]); $this->assertEquals($uri, $this->_app->last['onUnSubscribe'][1]);
} }
@ -103,7 +107,10 @@ class WAMPServerComponentTest extends \PHPUnit_Framework_TestCase {
$id = uniqid(); $id = uniqid();
$clientMessage = array_merge(array(2, $id, $uri), $args); $clientMessage = array_merge(array(2, $id, $uri), $args);
$this->_comp->onMessage($this->newConn(), json_encode($clientMessage)); $conn = $this->newConn();
$this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, json_encode($clientMessage));
$this->assertEquals($id, $this->_app->last['onCall'][1]); $this->assertEquals($id, $this->_app->last['onCall'][1]);
$this->assertEquals($uri, $this->_app->last['onCall'][2]); $this->assertEquals($uri, $this->_app->last['onCall'][2]);
@ -132,67 +139,68 @@ class WAMPServerComponentTest extends \PHPUnit_Framework_TestCase {
/** /**
* @dataProvider eventProvider * @dataProvider eventProvider
* @covers Ratchet\Component\WAMP\Command\Action\Event
*/ */
public function testEvent($topic, $payload) { public function testEvent($topic, $payload) {
$event = new Event($this->newConn()); $conn = new WampConnection($this->newConn());
$event->setEvent($topic, $payload); $conn->event($topic, $payload);
$eventString = $event->getMessage(); $eventString = $conn->last['send'];
$this->assertSame(array(8, $topic, $payload), json_decode($eventString, true)); $this->assertSame(array(8, $topic, $payload), json_decode($eventString, true));
} }
public function testOnClosePropagation() { public function testOnClosePropagation() {
$conn = $this->newConn(); $conn = new Connection;
$this->_comp->onOpen($conn);
$this->_comp->onClose($conn); $this->_comp->onClose($conn);
$this->assertSame($conn, $this->_app->last['onClose'][0]); $class = new \ReflectionClass('\\Ratchet\\Component\\WAMP\\WampConnection');
$method = $class->getMethod('getConnection');
$method->setAccessible(true);
$check = $method->invokeArgs($this->_app->last['onClose'][0], array());
$this->assertSame($conn, $check);
} }
public function testOnErrorPropagation() { public function testOnErrorPropagation() {
$conn = $this->newConn(); $conn = new Connection;
$e = new \Exception('Nope'); $e = new \Exception('Nope');
$this->_comp->onOpen($conn);
$this->_comp->onError($conn, $e); $this->_comp->onError($conn, $e);
$this->assertSame($conn, $this->_app->last['onError'][0]); $class = new \ReflectionClass('\\Ratchet\\Component\\WAMP\\WampConnection');
$method = $class->getMethod('getConnection');
$method->setAccessible(true);
$check = $method->invokeArgs($this->_app->last['onError'][0], array());
$this->assertSame($conn, $check);
$this->assertSame($e, $this->_app->last['onError'][1]); $this->assertSame($e, $this->_app->last['onError'][1]);
} }
/**
* @covers Ratchet\Component\WAMP\Command\Action\Prefix
*/
public function testPrefix() { public function testPrefix() {
$conn = $this->newConn(); $conn = new WampConnection($this->newConn());
$this->_comp->onOpen($conn); $this->_comp->onOpen($conn);
$shortOut = 'outgoing';
$longOut = 'http://example.com/outoing';
$shortIn = 'incoming'; $shortIn = 'incoming';
$shortIn = 'http://example.com/incoming/'; $longIn = 'http://example.com/incoming/';
$this->assertTrue(is_callable($conn->WAMP->addPrefix)); $this->_comp->onMessage($conn, json_encode(array(1, $shortIn, $longIn)));
$cb = $conn->WAMP->addPrefix; $this->assertEquals($longIn, $conn->WAMP->prefixes[$shortIn]);
$cb($shortOut, $longOut); $this->assertEquals($longIn, $conn->getUri($shortIn));
$return = $this->_comp->onMessage($conn, json_encode(array(1, $shortIn, $shortOut)));
$command = $return->pop();
$this->assertInstanceOf('Ratchet\\Component\\WAMP\\Command\\Action\\Prefix', $command);
$this->assertEquals($shortOut, $command->getCurie());
$this->assertEquals($longOut, $command->getUri());
$this->assertEquals(array(1, $shortOut, $longOut), json_decode($command->getMessage()));
} }
public function testMessageMustBeJson() { public function testMessageMustBeJson() {
$this->setExpectedException('\\Ratchet\\Component\\WAMP\\JsonException'); $this->setExpectedException('\\Ratchet\\Component\\WAMP\\JsonException');
$this->_comp->onMessage($this->newConn(), 'Hello World!'); $conn = new Connection;
$this->_comp->onOpen($conn);
$this->_comp->onMessage($conn, 'Hello World!');
} }
} }

View File

@ -0,0 +1,67 @@
<?php
namespace Ratchet\Tests\Component\WAMP;
use Ratchet\Component\WAMP\WampConnection;
use Ratchet\Tests\Mock\Connection;
/**
* @covers Ratchet\Component\WAMP\WampConnection
*/
class WampConnectionTest extends \PHPUnit_Framework_TestCase {
public function testCallResult() {
$conn = new Connection;
$decor = new WampConnection($conn);
$callId = uniqid();
$data = array('hello' => 'world', 'herp' => 'derp');
$decor->callResult($callId, $data);
$resultString = $conn->last['send'];
$this->assertEquals(array(3, $callId, $data), json_decode($resultString, true));
}
public function testCallError() {
$conn = new Connection;
$decor = new WampConnection($conn);
$callId = uniqid();
$uri = 'http://example.com/end/point';
$decor->callError($callId, $uri);
$resultString = $conn->last['send'];
$this->assertEquals(array(4, $callId, $uri, ''), json_decode($resultString, true));
}
public function testDetailedCallError() {
$conn = new Connection;
$decor = new WampConnection($conn);
$callId = uniqid();
$uri = 'http://example.com/end/point';
$desc = 'beep boop beep';
$detail = 'Error: Too much awesome';
$decor->callError($callId, $uri, $desc, $detail);
$resultString = $conn->last['send'];
$this->assertEquals(array(4, $callId, $uri, $desc, $detail), json_decode($resultString, true));
}
public function testPrefix() {
$conn = new WampConnection(new Connection);
$shortOut = 'outgoing';
$longOut = 'http://example.com/outoing';
$conn->prefix($shortOut, $longOut);
}
public function testGetUriWhenNoCurieGiven() {
$conn = new WampConnection(new Connection);
$uri = 'http://example.com/noshort';
$this->assertEquals($uri, $conn->getUri($uri));
}
}

View File

@ -1,22 +0,0 @@
<?php
namespace Ratchet\Tests\Resource\Command\Action;
use Ratchet\Resource\Command\Action\SendMessage;
use Ratchet\Tests\Mock\Connection;
/**
* @covers Ratchet\Resource\Command\Action\SendMessage
*/
class SendMessageTest extends \PHPUnit_Framework_TestCase {
public function testFluentInterface() {
$cmd = new SendMessage(new Connection);
$this->assertInstanceOf('\\Ratchet\\Resource\\Command\\Action\\SendMessage', $cmd->setMessage('Hello World!'));
}
public function testGetMessageMatchesSet() {
$msg = 'The quick brown fox jumps over the lazy dog.';
$cmd = new SendMessage(new Connection);
$cmd->setMessage($msg);
$this->assertEquals($msg, $cmd->getMessage());
}
}

View File

@ -1,63 +0,0 @@
<?php
namespace Ratchet\Tests\Resource\Command;
use Ratchet\Resource\Command\Composite;
use Ratchet\Tests\Mock\Connection;
use Ratchet\Resource\Command\Action\Null as NullAction;
/**
* @covers Ratchet\Resource\Command\Composite
*/
class CompositeTest extends \PHPUnit_Framework_TestCase {
protected $_comp;
public function setUp() {
$this->_comp = new Composite;
}
protected function newNull() {
return new NullAction(new Connection);
}
public function testCanEnqueueNull() {
$count = $this->_comp->count();
$this->_comp->enqueue(null);
$this->assertEquals($count, $this->_comp->count());
}
public function testEnqueueCommand() {
$count = $this->_comp->count();
$this->_comp->enqueue($this->newNull());
$this->assertEquals($count + 1, $this->_comp->count());
}
public function badEnqueueProviders() {
return array(
array(array())
, array('string')
);
}
/**
* @dataProvider badEnqueueProviders
*/
public function testCanNotPassOtherThings($object) {
$this->setExpectedException('InvalidArgumentException');
$this->_comp->enqueue($object);
}
public function testCompositeComposite() {
$compTwo = new Composite;
$compTwo->enqueue($this->newNull());
$compTwo->enqueue($this->newNull());
$this->_comp->enqueue($this->newNull());
$this->_comp->enqueue($compTwo);
$this->assertEquals(3, $this->_comp->count());
}
}