Browse Source

Rework the API for external protocol processors.

Daniele Alessandri 11 years ago
parent
commit
16d17af577
30 changed files with 177 additions and 274 deletions
  1. 2 1
      CHANGELOG.md
  2. 0 7
      lib/Predis/Connection/ComposableConnectionInterface.php
  3. 1 13
      lib/Predis/Connection/ComposableStreamConnection.php
  4. 0 50
      lib/Predis/Protocol/ComposableProtocolInterface.php
  5. 1 2
      lib/Predis/Protocol/ProtocolException.php
  6. 8 8
      lib/Predis/Protocol/ProtocolInterface.php
  7. 2 2
      lib/Predis/Protocol/RequestSerializerInterface.php
  8. 4 4
      lib/Predis/Protocol/ResponseHandlerInterface.php
  9. 3 3
      lib/Predis/Protocol/ResponseReaderInterface.php
  10. 29 51
      lib/Predis/Protocol/Text/ComposableTextProtocol.php
  11. 7 11
      lib/Predis/Protocol/Text/ResponseBulkHandler.php
  12. 4 4
      lib/Predis/Protocol/Text/ResponseErrorHandler.php
  13. 8 12
      lib/Predis/Protocol/Text/ResponseIntegerHandler.php
  14. 8 12
      lib/Predis/Protocol/Text/ResponseMultiBulkHandler.php
  15. 11 11
      lib/Predis/Protocol/Text/ResponseMultiBulkStreamHandler.php
  16. 3 2
      lib/Predis/Protocol/Text/ResponseStatusHandler.php
  17. 13 9
      lib/Predis/Protocol/Text/TextProtocol.php
  18. 3 4
      lib/Predis/Protocol/Text/TextRequestSerializer.php
  19. 19 18
      lib/Predis/Protocol/Text/TextResponseReader.php
  20. 1 1
      tests/Predis/Connection/ComposableStreamConnectionTest.php
  21. 1 1
      tests/Predis/Iterator/MultiBulkResponseSimpleTest.php
  22. 1 1
      tests/Predis/Iterator/MultiBulkResponseTupleTest.php
  23. 39 38
      tests/Predis/Protocol/Text/ComposableTextProtocolTest.php
  24. 1 1
      tests/Predis/Protocol/Text/ResponseBulkHandlerTest.php
  25. 1 1
      tests/Predis/Protocol/Text/ResponseIntegerHandlerTest.php
  26. 1 1
      tests/Predis/Protocol/Text/ResponseMultiBulkHandlerTest.php
  27. 1 1
      tests/Predis/Protocol/Text/ResponseMultiBulkStreamHandlerTest.php
  28. 1 1
      tests/Predis/Protocol/Text/TextProtocolTest.php
  29. 3 3
      tests/Predis/Protocol/Text/TextRequestSerializerTest.php
  30. 1 1
      tests/Predis/Protocol/Text/TextResponseReaderTest.php

+ 2 - 1
CHANGELOG.md

@@ -5,7 +5,8 @@ v0.9.0 (201x-xx-xx)
 
 - Dropped support for streamable multibulk responses. Actually we still ship the
   iterator response classes just in case anyone would want to build custom stuff
-  at a level lower than the client abstraction.
+  at a level lower than the client abstraction (our standard and composable text
+  protocol processors still handle them and can be used as an example).
 
 - The `Predis\Option` namespace is now known as `Predis\Configuration` and have
   a fully-reworked `Options` class with the ability to lazily initialize values

+ 0 - 7
lib/Predis/Connection/ComposableConnectionInterface.php

@@ -22,13 +22,6 @@ use Predis\Protocol\ProtocolInterface;
  */
 interface ComposableConnectionInterface extends SingleConnectionInterface
 {
-    /**
-     * Sets the protocol processor used by the connection.
-     *
-     * @param ProtocolInterface $protocol Protocol processor.
-     */
-    public function setProtocol(ProtocolInterface $protocol);
-
     /**
      * Gets the protocol processor used by the connection.
      */

+ 1 - 13
lib/Predis/Connection/ComposableStreamConnection.php

@@ -23,7 +23,7 @@ use Predis\Protocol\Text\TextProtocol;
  */
 class ComposableStreamConnection extends StreamConnection implements ComposableConnectionInterface
 {
-    private $protocol;
+    protected $protocol;
 
     /**
      * @param ConnectionParametersInterface $parameters Parameters used to initialize the connection.
@@ -35,18 +35,6 @@ class ComposableStreamConnection extends StreamConnection implements ComposableC
         $this->protocol = $protocol ?: new TextProtocol();
     }
 
-    /**
-     * {@inheritdoc}
-     */
-    public function setProtocol(ProtocolInterface $protocol)
-    {
-        if ($protocol === null) {
-            throw new \InvalidArgumentException("The protocol instance cannot be a null value");
-        }
-
-        $this->protocol = $protocol;
-    }
-
     /**
      * {@inheritdoc}
      */

+ 0 - 50
lib/Predis/Protocol/ComposableProtocolInterface.php

@@ -1,50 +0,0 @@
-<?php
-
-/*
- * This file is part of the Predis package.
- *
- * (c) Daniele Alessandri <suppakilla@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Predis\Protocol;
-
-/**
- * Interface that defines a customizable protocol processor that serializes
- * Redis commands and parses replies returned by the server to PHP objects
- * using a pluggable set of classes defining the underlying wire protocol.
- *
- * @author Daniele Alessandri <suppakilla@gmail.com>
- */
-interface ComposableProtocolInterface extends ProtocolInterface
-{
-    /**
-     * Sets the command serializer to be used by the protocol processor.
-     *
-     * @param CommandSerializerInterface $serializer Command serializer.
-     */
-    public function setSerializer(CommandSerializerInterface $serializer);
-
-    /**
-     * Returns the command serializer used by the protocol processor.
-     *
-     * @return CommandSerializerInterface
-     */
-    public function getSerializer();
-
-    /**
-     * Sets the response reader to be used by the protocol processor.
-     *
-     * @param ResponseReaderInterface $reader Response reader.
-     */
-    public function setReader(ResponseReaderInterface $reader);
-
-    /**
-     * Returns the response reader used by the protocol processor.
-     *
-     * @return ResponseReaderInterface
-     */
-    public function getReader();
-}

+ 1 - 2
lib/Predis/Protocol/ProtocolException.php

@@ -14,8 +14,7 @@ namespace Predis\Protocol;
 use Predis\CommunicationException;
 
 /**
- * Exception class that identifies errors encountered while
- * handling the Redis wire protocol.
+ * Errors encountered while handling the wire protocol.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */

+ 8 - 8
lib/Predis/Protocol/ProtocolInterface.php

@@ -15,15 +15,15 @@ use Predis\Command\CommandInterface;
 use Predis\Connection\ComposableConnectionInterface;
 
 /**
- * Interface that defines a protocol processor that serializes Redis commands
- * and parses replies returned by the server to PHP objects.
+ * Defines a pluggable protocol processor capable of serializing commands and
+ * deserializing responses into PHP objects directly from a connection.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-interface ProtocolInterface extends ResponseReaderInterface
+interface ProtocolInterface
 {
     /**
-     * Writes a Redis command on the specified connection.
+     * Writes a command to the specified connection.
      *
      * @param ComposableConnectionInterface $connection Connection to Redis.
      * @param CommandInterface $command Redis command.
@@ -31,10 +31,10 @@ interface ProtocolInterface extends ResponseReaderInterface
     public function write(ComposableConnectionInterface $connection, CommandInterface $command);
 
     /**
-     * Sets the options for the protocol processor.
+     * Reads a response from the specified connection and deserializes it.
      *
-     * @param string $option Name of the option.
-     * @param mixed $value Value of the option.
+     * @param ComposableConnectionInterface $connection Connection to Redis.
+     * @return mixed
      */
-    public function setOption($option, $value);
+    public function read(ComposableConnectionInterface $connection);
 }

+ 2 - 2
lib/Predis/Protocol/CommandSerializerInterface.php → lib/Predis/Protocol/RequestSerializerInterface.php

@@ -14,11 +14,11 @@ namespace Predis\Protocol;
 use Predis\Command\CommandInterface;
 
 /**
- * Interface that defines a custom serializer for Redis commands.
+ * Defines a pluggable serializer for Redis commands.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-interface CommandSerializerInterface
+interface RequestSerializerInterface
 {
     /**
      * Serializes a Redis command.

+ 4 - 4
lib/Predis/Protocol/ResponseHandlerInterface.php

@@ -14,18 +14,18 @@ namespace Predis\Protocol;
 use Predis\Connection\ComposableConnectionInterface;
 
 /**
- * Interface that defines an handler able to parse a reply.
+ * Defines a pluggable handler used to parse a particular type of response.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
 interface ResponseHandlerInterface
 {
     /**
-     * Parses a type of reply returned by Redis and reads more data from the
-     * connection if needed.
+     * Deserializes the response returned by Redis and reads more data from the
+     * connection when needed.
      *
      * @param ComposableConnectionInterface $connection Connection to Redis.
-     * @param string $payload Initial payload of the reply.
+     * @param string $payload Raw payload.
      * @return mixed
      */
     function handle(ComposableConnectionInterface $connection, $payload);

+ 3 - 3
lib/Predis/Protocol/ResponseReaderInterface.php

@@ -14,15 +14,15 @@ namespace Predis\Protocol;
 use Predis\Connection\ComposableConnectionInterface;
 
 /**
- * Interface that defines a response reader able to parse replies returned by
- * Redis and deserialize them to PHP objects.
+ * Defines a pluggable reader capable of parsing responses returned by Redis and
+ * deserializing them to PHP objects.
  *
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
 interface ResponseReaderInterface
 {
     /**
-     * Reads replies from a connection to Redis and deserializes them.
+     * Reads responses from the connection.
      *
      * @param ComposableConnectionInterface $connection Connection to Redis.
      * @return mixed

+ 29 - 51
lib/Predis/Protocol/Text/ComposableTextProtocol.php

@@ -13,62 +13,32 @@ namespace Predis\Protocol\Text;
 
 use Predis\Command\CommandInterface;
 use Predis\Connection\ComposableConnectionInterface;
+use Predis\Protocol\RequestSerializerInterface;
+use Predis\Protocol\ProtocolInterface;
 use Predis\Protocol\ResponseReaderInterface;
-use Predis\Protocol\CommandSerializerInterface;
-use Predis\Protocol\ComposableProtocolInterface;
 
 /**
- * Implements a customizable protocol processor that uses the standard Redis
- * wire protocol to serialize Redis commands and parse replies returned by
- * the server using a pluggable set of classes.
+ * Composable protocol processor for the standard Redis wire protocol using
+ * pluggable handlers to serialize requests and deserialize responses.
  *
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-class ComposableTextProtocol implements ComposableProtocolInterface
+class ComposableTextProtocol implements ProtocolInterface
 {
     private $serializer;
     private $reader;
 
     /**
-     * @param array $options Set of options used to initialize the protocol processor.
+     * @param RequestSerializerInterface $serializer Request serializer.
+     * @param ResponseReaderInterface $reader Response reader.
      */
-    public function __construct(Array $options = array())
-    {
-        $this->setSerializer(new TextCommandSerializer());
-        $this->setReader(new TextResponseReader());
-
-        if (count($options) > 0) {
-            $this->initializeOptions($options);
-        }
-    }
-
-    /**
-     * Initializes the protocol processor using a set of options.
-     *
-     * @param array $options Set of options.
-     */
-    private function initializeOptions(Array $options)
-    {
-        foreach ($options as $k => $v) {
-            $this->setOption($k, $v);
-        }
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setOption($option, $value)
-    {
-        switch ($option) {
-            case 'iterable_multibulk':
-                $handler = $value ? new ResponseMultiBulkStreamHandler() : new ResponseMultiBulkHandler();
-                $this->reader->setHandler(TextProtocol::PREFIX_MULTI_BULK, $handler);
-                break;
-
-            default:
-                throw new \InvalidArgumentException("The option $option is not supported by the current protocol");
-        }
+    public function __construct(
+        RequestSerializerInterface $serializer = null,
+        ResponseReaderInterface $reader = null
+    ) {
+        $this->setRequestSerializer($serializer ?: new TextRequestSerializer());
+        $this->setResponseReader($reader ?: new TextResponseReader());
     }
 
     /**
@@ -96,33 +66,41 @@ class ComposableTextProtocol implements ComposableProtocolInterface
     }
 
     /**
-     * {@inheritdoc}
+     * Sets the request serializer used by the protocol processor.
+     *
+     * @param RequestSerializerInterface $serializer Request serializer.
      */
-    public function setSerializer(CommandSerializerInterface $serializer)
+    public function setRequestSerializer(RequestSerializerInterface $serializer)
     {
         $this->serializer = $serializer;
     }
 
     /**
-     * {@inheritdoc}
+     * Returns the request serializer used by the protocol processor.
+     *
+     * @return RequestSerializerInterface
      */
-    public function getSerializer()
+    public function getRequestSerializer()
     {
         return $this->serializer;
     }
 
     /**
-     * {@inheritdoc}
+     * Sets the response reader used by the protocol processor.
+     *
+     * @param ResponseReaderInterface $reader Response reader.
      */
-    public function setReader(ResponseReaderInterface $reader)
+    public function setResponseReader(ResponseReaderInterface $reader)
     {
         $this->reader = $reader;
     }
 
     /**
-     * {@inheritdoc}
+     * Returns the Response reader used by the protocol processor.
+     *
+     * @return ResponseReaderInterface
      */
-    public function getReader()
+    public function getResponseReader()
     {
         return $this->reader;
     }

+ 7 - 11
lib/Predis/Protocol/Text/ResponseBulkHandler.php

@@ -17,8 +17,8 @@ use Predis\Protocol\ProtocolException;
 use Predis\Protocol\ResponseHandlerInterface;
 
 /**
- * Implements a response handler for bulk replies using the standard wire
- * protocol defined by Redis.
+ * Handler for the bulk response type of the standard Redis wire protocol.
+ * It translates the payload to a string or a NULL.
  *
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>
@@ -26,19 +26,15 @@ use Predis\Protocol\ResponseHandlerInterface;
 class ResponseBulkHandler implements ResponseHandlerInterface
 {
     /**
-     * Handles a bulk reply returned by Redis.
-     *
-     * @param ComposableConnectionInterface $connection Connection to Redis.
-     * @param string $lengthString Bytes size of the bulk reply.
-     * @return string
+     * {@inheritdoc}
      */
-    public function handle(ComposableConnectionInterface $connection, $lengthString)
+    public function handle(ComposableConnectionInterface $connection, $payload)
     {
-        $length = (int) $lengthString;
+        $length = (int) $payload;
 
-        if ("$length" !== $lengthString) {
+        if ("$length" !== $payload) {
             CommunicationException::handle(new ProtocolException(
-                $connection, "Cannot parse '$lengthString' as bulk length"
+                $connection, "Cannot parse '$payload' as the length of the bulk response"
             ));
         }
 

+ 4 - 4
lib/Predis/Protocol/Text/ResponseErrorHandler.php

@@ -16,8 +16,8 @@ use Predis\Connection\ComposableConnectionInterface;
 use Predis\Protocol\ResponseHandlerInterface;
 
 /**
- * Implements a response handler for error replies using the standard wire
- * protocol defined by Redis.
+ * Handler for the error response type of the standard Redis wire protocol.
+ * It translates the payload to a complex response object for Predis.
  *
  * This handler returns a reply object to notify the user that an error has
  * occurred on the server.
@@ -30,8 +30,8 @@ class ResponseErrorHandler implements ResponseHandlerInterface
     /**
      * {@inheritdoc}
      */
-    public function handle(ComposableConnectionInterface $connection, $errorMessage)
+    public function handle(ComposableConnectionInterface $connection, $payload)
     {
-        return new ResponseError($errorMessage);
+        return new ResponseError($payload);
     }
 }

+ 8 - 12
lib/Predis/Protocol/Text/ResponseIntegerHandler.php

@@ -17,8 +17,8 @@ use Predis\Protocol\ProtocolException;
 use Predis\Protocol\ResponseHandlerInterface;
 
 /**
- * Implements a response handler for integer replies using the standard wire
- * protocol defined by Redis.
+ * Handler for the integer response type of the standard Redis wire protocol.
+ * It translates the payload an integer or NULL.
  *
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>
@@ -26,21 +26,17 @@ use Predis\Protocol\ResponseHandlerInterface;
 class ResponseIntegerHandler implements ResponseHandlerInterface
 {
     /**
-     * Handles an integer reply returned by Redis.
-     *
-     * @param ComposableConnectionInterface $connection Connection to Redis.
-     * @param string $number String representation of an integer.
-     * @return int
+     * {@inheritdoc}
      */
-    public function handle(ComposableConnectionInterface $connection, $number)
+    public function handle(ComposableConnectionInterface $connection, $payload)
     {
-        if (is_numeric($number)) {
-            return (int) $number;
+        if (is_numeric($payload)) {
+            return (int) $payload;
         }
 
-        if ($number !== 'nil') {
+        if ($payload !== 'nil') {
             CommunicationException::handle(new ProtocolException(
-                $connection, "Cannot parse '$number' as numeric response"
+                $connection, "Cannot parse '$payload' as a numeric response"
             ));
         }
 

+ 8 - 12
lib/Predis/Protocol/Text/ResponseMultiBulkHandler.php

@@ -17,8 +17,8 @@ use Predis\Protocol\ProtocolException;
 use Predis\Protocol\ResponseHandlerInterface;
 
 /**
- * Implements a response handler for multi-bulk replies using the standard
- * wire protocol defined by Redis.
+ * Handler for the multibulk response type of the standard Redis wire protocol.
+ * It returns multibulk responses as PHP arrays.
  *
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>
@@ -26,19 +26,15 @@ use Predis\Protocol\ResponseHandlerInterface;
 class ResponseMultiBulkHandler implements ResponseHandlerInterface
 {
     /**
-     * Handles a multi-bulk reply returned by Redis.
-     *
-     * @param ComposableConnectionInterface $connection Connection to Redis.
-     * @param string $lengthString Number of items in the multi-bulk reply.
-     * @return array
+     * {@inheritdoc}
      */
-    public function handle(ComposableConnectionInterface $connection, $lengthString)
+    public function handle(ComposableConnectionInterface $connection, $payload)
     {
-        $length = (int) $lengthString;
+        $length = (int) $payload;
 
-        if ("$length" !== $lengthString) {
+        if ("$length" !== $payload) {
             CommunicationException::handle(new ProtocolException(
-                $connection, "Cannot parse '$lengthString' as multi-bulk length"
+                $connection, "Cannot parse '$payload' as the length of the multibulk response"
             ));
         }
 
@@ -50,7 +46,7 @@ class ResponseMultiBulkHandler implements ResponseHandlerInterface
 
         if ($length > 0) {
             $handlersCache = array();
-            $reader = $connection->getProtocol()->getReader();
+            $reader = $connection->getProtocol()->getResponseReader();
 
             for ($i = 0; $i < $length; $i++) {
                 $header = $connection->readLine();

+ 11 - 11
lib/Predis/Protocol/Text/ResponseMultiBulkStreamHandler.php

@@ -18,8 +18,12 @@ use Predis\Protocol\ProtocolException;
 use Predis\Protocol\ResponseHandlerInterface;
 
 /**
- * Implements a response handler for iterable multi-bulk replies using the
- * standard wire protocol defined by Redis.
+ * Handler for the multibulk response type of the standard Redis wire protocol.
+ * It returns multibulk responses as iterators that can stream bulk elements.
+ *
+ * Please note that streamable multibulk replies are not globally supported
+ * by the abstractions built-in into Predis such as for transactions or
+ * pipelines. Use them with care!
  *
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>
@@ -27,19 +31,15 @@ use Predis\Protocol\ResponseHandlerInterface;
 class ResponseMultiBulkStreamHandler implements ResponseHandlerInterface
 {
     /**
-     * Handles a multi-bulk reply returned by Redis in a streamable fashion.
-     *
-     * @param ComposableConnectionInterface $connection Connection to Redis.
-     * @param string $lengthString Number of items in the multi-bulk reply.
-     * @return MultiBulkResponseSimple
+     * {@inheritdoc}
      */
-    public function handle(ComposableConnectionInterface $connection, $lengthString)
+    public function handle(ComposableConnectionInterface $connection, $payload)
     {
-        $length = (int) $lengthString;
+        $length = (int) $payload;
 
-        if ("$length" != $lengthString) {
+        if ("$length" != $payload) {
             CommunicationException::handle(new ProtocolException(
-                $connection, "Cannot parse '$lengthString' as multi-bulk length"
+                $connection, "Cannot parse '$payload' as the length of the multibulk response"
             ));
         }
 

+ 3 - 2
lib/Predis/Protocol/Text/ResponseStatusHandler.php

@@ -16,8 +16,9 @@ use Predis\Connection\ComposableConnectionInterface;
 use Predis\Protocol\ResponseHandlerInterface;
 
 /**
- * Implements a response handler for status replies using the standard wire
- * protocol defined by Redis.
+ * Handler for the status response type of the standard Redis wire protocol.
+ * It translates certain classes of status response to PHP objects or just
+ * returns the payload as a string.
  *
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>

+ 13 - 9
lib/Predis/Protocol/Text/TextProtocol.php

@@ -21,7 +21,7 @@ use Predis\Protocol\ProtocolException;
 use Predis\Protocol\ProtocolInterface;
 
 /**
- * Implements a protocol processor for the standard wire protocol defined by Redis.
+ * Protocol processor for the standard Redis wire protocol.
  *
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>
@@ -51,7 +51,7 @@ class TextProtocol implements ProtocolInterface
     public function __construct()
     {
         $this->mbiterable = false;
-        $this->serializer = new TextCommandSerializer();
+        $this->serializer = new TextRequestSerializer();
     }
 
     /**
@@ -123,14 +123,18 @@ class TextProtocol implements ProtocolInterface
     }
 
     /**
-     * {@inheritdoc}
+     * Enables or disables returning multibulk responses as specialized PHP
+     * iterators used to stream bulk elements of a multibulk response instead
+     * returning a plain array.
+     *
+     * Please note that streamable multibulk replies are not globally supported
+     * by the abstractions built-in into Predis such as for transactions or
+     * pipelines. Use them with care!
+     *
+     * @param bool $value Enable or disable streamable multibulk responses.
      */
-    public function setOption($option, $value)
+    public function useIterableMultibulk($value)
     {
-        switch ($option) {
-            case 'iterable_multibulk':
-                $this->mbiterable = (bool) $value;
-                break;
-        }
+        $this->mbiterable = (bool) $value;
     }
 }

+ 3 - 4
lib/Predis/Protocol/Text/TextCommandSerializer.php → lib/Predis/Protocol/Text/TextRequestSerializer.php

@@ -12,16 +12,15 @@
 namespace Predis\Protocol\Text;
 
 use Predis\Command\CommandInterface;
-use Predis\Protocol\CommandSerializerInterface;
+use Predis\Protocol\RequestSerializerInterface;
 
 /**
- * Implements a pluggable command serializer using the standard  wire protocol
- * defined by Redis.
+ * Request serializer for the standard Redis wire protocol.
  *
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-class TextCommandSerializer implements CommandSerializerInterface
+class TextRequestSerializer implements RequestSerializerInterface
 {
     /**
      * {@inheritdoc}

+ 19 - 18
lib/Predis/Protocol/Text/TextResponseReader.php

@@ -18,15 +18,14 @@ use Predis\Protocol\ResponseHandlerInterface;
 use Predis\Protocol\ResponseReaderInterface;
 
 /**
- * Implements a pluggable response reader using the standard wire protocol
- * defined by Redis.
+ * Response reader for the standard Redis wire protocol.
  *
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
 class TextResponseReader implements ResponseReaderInterface
 {
-    private $handlers;
+    protected $handlers;
 
     /**
      *
@@ -37,10 +36,11 @@ class TextResponseReader implements ResponseReaderInterface
     }
 
     /**
-     * Returns the default set of response handlers for all the type of replies
-     * that can be returned by Redis.
+     * Returns the default handlers for the supported type of responses.
+     *
+     * @return array
      */
-    private function getDefaultHandlers()
+    protected function getDefaultHandlers()
     {
         return array(
             TextProtocol::PREFIX_STATUS     => new ResponseStatusHandler(),
@@ -53,10 +53,10 @@ class TextResponseReader implements ResponseReaderInterface
 
     /**
      * Sets a response handler for a certain prefix that identifies a type of
-     * reply that can be returned by Redis.
+     * response that can be returned by Redis.
      *
-     * @param string $prefix Identifier for a type of reply.
-     * @param ResponseHandlerInterface $handler Response handler for the reply.
+     * @param string $prefix Identifier of the type of response.
+     * @param ResponseHandlerInterface $handler Response handler.
      */
     public function setHandler($prefix, ResponseHandlerInterface $handler)
     {
@@ -64,10 +64,9 @@ class TextResponseReader implements ResponseReaderInterface
     }
 
     /**
-     * Returns the response handler associated to a certain type of reply that
-     * can be returned by Redis.
+     * Returns the response handler associated to a certain type of response.
      *
-     * @param string $prefix Identifier for a type of reply.
+     * @param string $prefix Identifier of the type of response.
      * @return ResponseHandlerInterface
      */
     public function getHandler($prefix)
@@ -85,13 +84,13 @@ class TextResponseReader implements ResponseReaderInterface
         $header = $connection->readLine();
 
         if ($header === '') {
-            $this->protocolError($connection, 'Unexpected empty header');
+            $this->onProtocolError($connection, 'Unexpected empty header');
         }
 
         $prefix = $header[0];
 
         if (!isset($this->handlers[$prefix])) {
-            $this->protocolError($connection, "Unknown prefix: '$prefix'");
+            $this->onProtocolError($connection, "Unknown prefix: '$prefix'");
         }
 
         $handler = $this->handlers[$prefix];
@@ -100,14 +99,16 @@ class TextResponseReader implements ResponseReaderInterface
     }
 
     /**
-     * Helper method used to handle a protocol error generated while reading a
-     * reply from a connection to Redis.
+     * Handles protocol errors generated while reading responses from the
+     * connection.
      *
      * @param ComposableConnectionInterface $connection Connection to Redis that generated the error.
      * @param string $message Error message.
      */
-    private function protocolError(ComposableConnectionInterface $connection, $message)
+    protected function onProtocolError(ComposableConnectionInterface $connection, $message)
     {
-        CommunicationException::handle(new ProtocolException($connection, $message));
+        CommunicationException::handle(
+            new ProtocolException($connection, $message)
+        );
     }
 }

+ 1 - 1
tests/Predis/Connection/ComposableStreamConnectionTest.php

@@ -75,7 +75,7 @@ class ComposableStreamConnectionTest extends ConnectionTestCase
     public function testReadsMultibulkRepliesAsIterators()
     {
         $connection = $this->getConnection($profile, true);
-        $connection->getProtocol()->setOption('iterable_multibulk', true);
+        $connection->getProtocol()->useIterableMultibulk(true);
 
         $connection->executeCommand($profile->createCommand('rpush', array('metavars', 'foo', 'hoge', 'lol')));
         $connection->writeCommand($profile->createCommand('lrange', array('metavars', 0, -1)));

+ 1 - 1
tests/Predis/Iterator/MultiBulkResponseSimpleTest.php

@@ -131,7 +131,7 @@ class MultiBulkResponseSimpleTest extends StandardTestCase
         );
 
         $protocol = new TextProtocol();
-        $protocol->setOption('iterable_multibulk', true);
+        $protocol->useIterableMultibulk(true);
 
         $connection = new ComposableStreamConnection($parameters, $protocol);
 

+ 1 - 1
tests/Predis/Iterator/MultiBulkResponseTupleTest.php

@@ -117,7 +117,7 @@ class MultiBulkResponseTupleTest extends StandardTestCase
         );
 
         $protocol = new TextProtocol();
-        $protocol->setOption('iterable_multibulk', true);
+        $protocol->useIterableMultibulk(true);
 
         $connection = new ComposableStreamConnection($parameters, $protocol);
 

+ 39 - 38
tests/Predis/Protocol/Text/ComposableTextProtocolTest.php

@@ -21,27 +21,56 @@ class ComposableTextProtocolTest extends StandardTestCase
     /**
      * @group disconnected
      */
-    public function testCustomSerializer()
+    public function testConstructor()
     {
-        $serializer = $this->getMock('Predis\Protocol\CommandSerializerInterface');
+        $protocol = new ComposableTextProtocol();
+
+        $this->assertInstanceOf(
+            'Predis\Protocol\Text\TextRequestSerializer', $protocol->getRequestSerializer()
+        );
+        $this->assertInstanceOf(
+            'Predis\Protocol\Text\TextResponseReader', $protocol->getResponseReader()
+        );
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testConstructorWithArguments()
+    {
+        $serializer = $this->getMock('Predis\Protocol\RequestSerializerInterface');
+        $reader = $this->getMock('Predis\Protocol\ResponseReaderInterface');
+
+        $protocol = new ComposableTextProtocol($serializer, $reader);
+
+        $this->assertSame($serializer, $protocol->getRequestSerializer());
+        $this->assertSame($reader, $protocol->getResponseReader());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testCustomRequestSerializer()
+    {
+        $serializer = $this->getMock('Predis\Protocol\RequestSerializerInterface');
 
         $protocol = new ComposableTextProtocol();
-        $protocol->setSerializer($serializer);
+        $protocol->setRequestSerializer($serializer);
 
-        $this->assertSame($serializer, $protocol->getSerializer());
+        $this->assertSame($serializer, $protocol->getRequestSerializer());
     }
 
     /**
      * @group disconnected
      */
-    public function testCustomReader()
+    public function testCustomResponseReader()
     {
         $reader = $this->getMock('Predis\Protocol\ResponseReaderInterface');
 
         $protocol = new ComposableTextProtocol();
-        $protocol->setReader($reader);
+        $protocol->setResponseReader($reader);
 
-        $this->assertSame($reader, $protocol->getReader());
+        $this->assertSame($reader, $protocol->getResponseReader());
     }
 
     /**
@@ -53,10 +82,9 @@ class ComposableTextProtocolTest extends StandardTestCase
 
         $command = $this->getMock('Predis\Command\CommandInterface');
         $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
-        $serializer = $this->getMock('Predis\Protocol\CommandSerializerInterface');
+        $serializer = $this->getMock('Predis\Protocol\RequestSerializerInterface');
 
-        $protocol = new ComposableTextProtocol();
-        $protocol->setSerializer($serializer);
+        $protocol = new ComposableTextProtocol($serializer);
 
         $connection->expects($this->once())
                    ->method('writeBytes')
@@ -80,8 +108,7 @@ class ComposableTextProtocolTest extends StandardTestCase
         $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
         $reader = $this->getMock('Predis\Protocol\ResponseReaderInterface');
 
-        $protocol = new ComposableTextProtocol();
-        $protocol->setReader($reader);
+        $protocol = new ComposableTextProtocol(null, $reader);
 
         $reader->expects($this->once())
                    ->method('read')
@@ -90,30 +117,4 @@ class ComposableTextProtocolTest extends StandardTestCase
 
         $this->assertSame('bulk', $protocol->read($connection));
     }
-
-    /**
-     * @group disconnected
-     */
-    public function testSetMultibulkOption()
-    {
-        $protocol = new ComposableTextProtocol();
-        $reader = $protocol->getReader();
-
-        $protocol->setOption('iterable_multibulk', true);
-        $this->assertInstanceOf('Predis\Protocol\Text\ResponseMultiBulkStreamHandler', $reader->getHandler('*'));
-
-        $protocol->setOption('iterable_multibulk', false);
-        $this->assertInstanceOf('Predis\Protocol\Text\ResponseMultiBulkHandler', $reader->getHandler('*'));
-    }
-
-    /**
-     * @group disconnected
-     * @expectedException InvalidArgumentException
-     * @expectedExceptionMessage The option unknown_option is not supported by the current protocol
-     */
-    public function testSetInvalidOption()
-    {
-        $protocol = new ComposableTextProtocol();
-        $protocol->setOption('unknown_option', true);
-    }
 }

+ 1 - 1
tests/Predis/Protocol/Text/ResponseBulkHandlerTest.php

@@ -75,7 +75,7 @@ class ResponseBulkHandlerTest extends StandardTestCase
     /**
      * @group disconnected
      * @expectedException Predis\Protocol\ProtocolException
-     * @expectedExceptionMessage Cannot parse 'invalid' as bulk length
+     * @expectedExceptionMessage Cannot parse 'invalid' as the length of the bulk response
      */
     public function testInvalidLength()
     {

+ 1 - 1
tests/Predis/Protocol/Text/ResponseIntegerHandlerTest.php

@@ -55,7 +55,7 @@ class ResponseIntegerHandlerTest extends StandardTestCase
     /**
      * @group disconnected
      * @expectedException Predis\Protocol\ProtocolException
-     * @expectedExceptionMessage Cannot parse 'invalid' as numeric response
+     * @expectedExceptionMessage Cannot parse 'invalid' as a numeric response
      */
     public function testInvalid()
     {

+ 1 - 1
tests/Predis/Protocol/Text/ResponseMultiBulkHandlerTest.php

@@ -68,7 +68,7 @@ class ResponseMultiBulkHandlerTest extends StandardTestCase
     /**
      * @group disconnected
      * @expectedException Predis\Protocol\ProtocolException
-     * @expectedExceptionMessage Cannot parse 'invalid' as multi-bulk length
+     * @expectedExceptionMessage Cannot parse 'invalid' as the length of the multibulk response
      */
     public function testInvalid()
     {

+ 1 - 1
tests/Predis/Protocol/Text/ResponseMultiBulkStreamHandlerTest.php

@@ -36,7 +36,7 @@ class ResponseMultiBulkStreamHandlerTest extends StandardTestCase
     /**
      * @group disconnected
      * @expectedException Predis\Protocol\ProtocolException
-     * @expectedExceptionMessage Cannot parse 'invalid' as multi-bulk length
+     * @expectedExceptionMessage Cannot parse 'invalid' as the length of the multibulk response
      */
     public function testInvalid()
     {

+ 1 - 1
tests/Predis/Protocol/Text/TextProtocolTest.php

@@ -89,7 +89,7 @@ class TextProtocolTest extends StandardTestCase
     public function testIterableMultibulkSupport()
     {
         $protocol = new TextProtocol();
-        $protocol->setOption('iterable_multibulk', true);
+        $protocol->useIterableMultibulk(true);
 
         $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
 

+ 3 - 3
tests/Predis/Protocol/Text/TextCommandSerializerTest.php → tests/Predis/Protocol/Text/TextRequestSerializerTest.php

@@ -16,14 +16,14 @@ use \PHPUnit_Framework_TestCase as StandardTestCase;
 /**
  *
  */
-class TextCommandSerializerTest extends StandardTestCase
+class TextRequestSerializerTest extends StandardTestCase
 {
     /**
      * @group disconnected
      */
     public function testSerializerIdWithNoArguments()
     {
-        $serializer = new TextCommandSerializer();
+        $serializer = new TextRequestSerializer();
 
         $command = $this->getMock('Predis\Command\CommandInterface');
 
@@ -45,7 +45,7 @@ class TextCommandSerializerTest extends StandardTestCase
      */
     public function testSerializerIdWithArguments()
     {
-        $serializer = new TextCommandSerializer();
+        $serializer = new TextRequestSerializer();
 
         $command = $this->getMock('Predis\Command\CommandInterface');
 

+ 1 - 1
tests/Predis/Protocol/Text/TextResponseReaderTest.php

@@ -55,7 +55,7 @@ class TextResponseReaderTest extends StandardTestCase
         $reader = new TextResponseReader();
 
         $protocol = new ComposableTextProtocol();
-        $protocol->setReader($reader);
+        $protocol->setResponseReader($reader);
 
         $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');