Browse Source

Add tests for classes in the Predis\Protocol\Text namespace.

This was the only namespace containing classes with no tests.
Daniele Alessandri 13 năm trước cách đây
mục cha
commit
6e76ea6c7e

+ 2 - 2
lib/Predis/Protocol/Text/ResponseBulkHandler.php

@@ -36,9 +36,9 @@ class ResponseBulkHandler implements ResponseHandlerInterface
     {
         $length = (int) $lengthString;
 
-        if ($length != $lengthString) {
+        if ("$length" !== $lengthString) {
             Helpers::onCommunicationException(new ProtocolException(
-                $connection, "Cannot parse '$length' as data length"
+                $connection, "Cannot parse '$lengthString' as bulk length"
             ));
         }
 

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

@@ -25,7 +25,7 @@ use Predis\Protocol\ResponseHandlerInterface;
  * @link http://redis.io/topics/protocol
  * @author Daniele Alessandri <suppakilla@gmail.com>
  */
-class ResponseErrorSilentHandler implements ResponseHandlerInterface
+class ResponseErrorHandler implements ResponseHandlerInterface
 {
     /**
      * {@inheritdoc}

+ 2 - 2
lib/Predis/Protocol/Text/ResponseMultiBulkHandler.php

@@ -36,9 +36,9 @@ class ResponseMultiBulkHandler implements ResponseHandlerInterface
     {
         $length = (int) $lengthString;
 
-        if ($length != $lengthString) {
+        if ("$length" !== $lengthString) {
             Helpers::onCommunicationException(new ProtocolException(
-                $connection, "Cannot parse '$length' as data length"
+                $connection, "Cannot parse '$lengthString' as multi-bulk length"
             ));
         }
 

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

@@ -37,9 +37,9 @@ class ResponseMultiBulkStreamHandler implements ResponseHandlerInterface
     {
         $length = (int) $lengthString;
 
-        if ($length != $lengthString) {
+        if ("$length" != $lengthString) {
             Helpers::onCommunicationException(new ProtocolException(
-                $connection, "Cannot parse '$length' as data length"
+                $connection, "Cannot parse '$lengthString' as multi-bulk length"
             ));
         }
 

+ 1 - 1
lib/Predis/Protocol/Text/TextResponseReader.php

@@ -91,7 +91,7 @@ class TextResponseReader implements ResponseReaderInterface
         $prefix = $header[0];
 
         if (!isset($this->handlers[$prefix])) {
-            $this->protocolError($connection, "Unknown prefix '$prefix'");
+            $this->protocolError($connection, "Unknown prefix: '$prefix'");
         }
 
         $handler = $this->handlers[$prefix];

+ 119 - 0
tests/Predis/Protocol/Text/ComposableTextProtocolTest.php

@@ -0,0 +1,119 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class ComposableTextProtocolTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testCustomSerializer()
+    {
+        $serializer = $this->getMock('Predis\Protocol\CommandSerializerInterface');
+
+        $protocol = new ComposableTextProtocol();
+        $protocol->setSerializer($serializer);
+
+        $this->assertSame($serializer, $protocol->getSerializer());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testCustomReader()
+    {
+        $reader = $this->getMock('Predis\Protocol\ResponseReaderInterface');
+
+        $protocol = new ComposableTextProtocol();
+        $protocol->setReader($reader);
+
+        $this->assertSame($reader, $protocol->getReader());
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testConnectionWrite()
+    {
+        $serialized = "*1\r\n$4\r\nPING\r\n";
+
+        $command = $this->getMock('Predis\Command\CommandInterface');
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+        $serializer = $this->getMock('Predis\Protocol\CommandSerializerInterface');
+
+        $protocol = new ComposableTextProtocol();
+        $protocol->setSerializer($serializer);
+
+        $connection->expects($this->once())
+                   ->method('writeBytes')
+                   ->with($this->equalTo($serialized));
+
+        $serializer->expects($this->once())
+                   ->method('serialize')
+                   ->with($command)
+                   ->will($this->returnValue($serialized));
+
+        $protocol->write($connection, $command);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testConnectionRead()
+    {
+        $serialized = "*1\r\n$4\r\nPING\r\n";
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+        $reader = $this->getMock('Predis\Protocol\ResponseReaderInterface');
+
+        $protocol = new ComposableTextProtocol();
+        $protocol->setReader($reader);
+
+        $reader->expects($this->once())
+                   ->method('read')
+                   ->with($connection)
+                   ->will($this->returnValue('bulk'));
+
+        $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);
+    }
+}

+ 91 - 0
tests/Predis/Protocol/Text/ResponseBulkHandlerTest.php

@@ -0,0 +1,91 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class ResponseBulkHandlerTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testZeroLengthBulk()
+    {
+        $handler = new ResponseBulkHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->once())
+                   ->method('readBytes')
+                   ->with($this->equalTo(2))
+                   ->will($this->returnValue("\r\n"));
+
+        $this->assertSame('', $handler->handle($connection, '0'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testBulk()
+    {
+        $bulk = "This is a bulk string.";
+        $bulkLengh = (string) strlen($bulk);
+
+        $handler = new ResponseBulkHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->once())
+                   ->method('readBytes')
+                   ->with($this->equalTo($bulkLengh + 2))
+                   ->will($this->returnValue("$bulk\r\n"));
+
+        $this->assertSame($bulk, $handler->handle($connection, $bulkLengh));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testNull()
+    {
+        $handler = new ResponseBulkHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $this->assertNull($handler->handle($connection, '-1'));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\Protocol\ProtocolException
+     * @expectedExceptionMessage Cannot parse 'invalid' as bulk length
+     */
+    public function testInvalidLength()
+    {
+        $handler = new ResponseBulkHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $handler->handle($connection, 'invalid');
+    }
+}

+ 39 - 0
tests/Predis/Protocol/Text/ResponseErrorHandlerTest.php

@@ -0,0 +1,39 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class ResponseErrorHandlerTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testOk()
+    {
+        $handler = new ResponseErrorHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $message = "ERR Operation against a key holding the wrong kind of value";
+        $response = $handler->handle($connection, $message);
+
+        $this->assertInstanceOf('Predis\ResponseError', $response);
+        $this->assertSame($message, $response->getMessage());
+    }
+}

+ 71 - 0
tests/Predis/Protocol/Text/ResponseIntegerHandlerTest.php

@@ -0,0 +1,71 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+use Predis\ResponseQueued;
+
+/**
+ *
+ */
+class ResponseIntegerHandlerTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testInteger()
+    {
+        $handler = new ResponseIntegerHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $this->assertSame(0, $handler->handle($connection, '0'));
+        $this->assertSame(1, $handler->handle($connection, '1'));
+        $this->assertSame(10, $handler->handle($connection, '10'));
+        $this->assertSame(-10, $handler->handle($connection, '-10'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testNull()
+    {
+        $handler = new ResponseIntegerHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $this->assertNull($handler->handle($connection, 'nil'));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\Protocol\ProtocolException
+     * @expectedExceptionMessage Cannot parse 'invalid' as numeric response
+     */
+    public function testInvalid()
+    {
+        $handler = new ResponseIntegerHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $handler->handle($connection, 'invalid');
+    }
+}

+ 84 - 0
tests/Predis/Protocol/Text/ResponseMultiBulkHandlerTest.php

@@ -0,0 +1,84 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class ResponseMultiBulkHandlerTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testMultiBulk()
+    {
+        $handler = new ResponseMultiBulkHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->once())
+                   ->method('getProtocol')
+                   ->will($this->returnValue(new ComposableTextProtocol()));
+
+        $connection->expects($this->at(1))
+                   ->method('readLine')
+                   ->will($this->returnValue("$3"));
+
+        $connection->expects($this->at(2))
+                   ->method('readBytes')
+                   ->will($this->returnValue("foo\r\n"));
+
+        $connection->expects($this->at(3))
+                   ->method('readLine')
+                   ->will($this->returnValue("$3"));
+
+        $connection->expects($this->at(4))
+                   ->method('readBytes')
+                   ->will($this->returnValue("bar\r\n"));
+
+        $this->assertSame(array('foo', 'bar'), $handler->handle($connection, '2'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testNull()
+    {
+        $handler = new ResponseMultiBulkHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $this->assertNull($handler->handle($connection, '-1'));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\Protocol\ProtocolException
+     * @expectedExceptionMessage Cannot parse 'invalid' as multi-bulk length
+     */
+    public function testInvalid()
+    {
+        $handler = new ResponseMultiBulkHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $handler->handle($connection, 'invalid');
+    }
+}

+ 52 - 0
tests/Predis/Protocol/Text/ResponseMultiBulkStreamHandlerTest.php

@@ -0,0 +1,52 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class ResponseMultiBulkStreamHandlerTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testOk()
+    {
+        $handler = new ResponseMultiBulkStreamHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $this->assertInstanceOf('Predis\Iterator\MultiBulkResponseSimple', $handler->handle($connection, '1'));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\Protocol\ProtocolException
+     * @expectedExceptionMessage Cannot parse 'invalid' as multi-bulk length
+     */
+    public function testInvalid()
+    {
+        $handler = new ResponseMultiBulkStreamHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $handler->handle($connection, 'invalid');
+    }
+}

+ 66 - 0
tests/Predis/Protocol/Text/ResponseStatusHandlerTest.php

@@ -0,0 +1,66 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+use Predis\ResponseQueued;
+
+/**
+ *
+ */
+class ResponseStatusHandlerTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testOk()
+    {
+        $handler = new ResponseStatusHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $this->assertTrue($handler->handle($connection, 'OK'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testQueued()
+    {
+        $handler = new ResponseStatusHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $this->assertInstanceOf('Predis\ResponseQueued', $handler->handle($connection, 'QUEUED'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testPlainString()
+    {
+        $handler = new ResponseStatusHandler();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->never())->method('readLine');
+        $connection->expects($this->never())->method('readBytes');
+
+        $this->assertSame('Background saving started', $handler->handle($connection, 'Background saving started'));
+    }
+}

+ 64 - 0
tests/Predis/Protocol/Text/TextCommandSerializerTest.php

@@ -0,0 +1,64 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class TextCommandSerializerTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testSerializerIdWithNoArguments()
+    {
+        $serializer = new TextCommandSerializer();
+
+        $command = $this->getMock('Predis\Command\CommandInterface');
+
+        $command->expects($this->once())
+                ->method('getId')
+                ->will($this->returnValue('PING'));
+
+        $command->expects($this->once())
+                ->method('getArguments')
+                ->will($this->returnValue(array()));
+
+        $result = $serializer->serialize($command);
+
+        $this->assertSame("*1\r\n$4\r\nPING\r\n", $result);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testSerializerIdWithArguments()
+    {
+        $serializer = new TextCommandSerializer();
+
+        $command = $this->getMock('Predis\Command\CommandInterface');
+
+        $command->expects($this->once())
+                ->method('getId')
+                ->will($this->returnValue('SET'));
+
+        $command->expects($this->once())
+                ->method('getArguments')
+                ->will($this->returnValue(array('key', 'value')));
+
+        $result = $serializer->serialize($command);
+
+        $this->assertSame("*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n", $result);
+    }
+}

+ 120 - 0
tests/Predis/Protocol/Text/TextProtocolTest.php

@@ -0,0 +1,120 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class TextProtocolTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testConnectionWrite()
+    {
+        $serialized = "*1\r\n$4\r\nPING\r\n";
+        $protocol = new TextProtocol();
+
+        $command = $this->getMock('Predis\Command\CommandInterface');
+
+        $command->expects($this->once())
+                ->method('getId')
+                ->will($this->returnValue('PING'));
+
+        $command->expects($this->once())
+                ->method('getArguments')
+                ->will($this->returnValue(array()));
+
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->once())
+                   ->method('writeBytes')
+                   ->with($this->equalTo($serialized));
+
+        $protocol->write($connection, $command);
+    }
+
+    /**
+     * @todo Improve test coverage
+     * @group disconnected
+     */
+    public function testConnectionRead()
+    {
+        $protocol = new TextProtocol();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->at(0))
+                   ->method('readLine')
+                   ->will($this->returnValue("+OK"));
+
+        $connection->expects($this->at(1))
+                   ->method('readLine')
+                   ->will($this->returnValue("-ERR error message"));
+
+        $connection->expects($this->at(2))
+                   ->method('readLine')
+                   ->will($this->returnValue(":2"));
+
+        $connection->expects($this->at(3))
+                   ->method('readLine')
+                   ->will($this->returnValue("$-1"));
+
+        $connection->expects($this->at(4))
+                   ->method('readLine')
+                   ->will($this->returnValue("*-1"));
+
+        $this->assertTrue($protocol->read($connection));
+        $this->assertEquals("ERR error message", $protocol->read($connection));
+        $this->assertSame(2, $protocol->read($connection));
+        $this->assertNull($protocol->read($connection));
+        $this->assertNull($protocol->read($connection));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testIterableMultibulkSupport()
+    {
+        $protocol = new TextProtocol();
+        $protocol->setOption('iterable_multibulk', true);
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->once(4))
+                   ->method('readLine')
+                   ->will($this->returnValue("*1"));
+
+        $this->assertInstanceOf('Predis\Iterator\MultiBulkResponseSimple', $protocol->read($connection));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\Protocol\ProtocolException
+     * @expectedExceptionMessage Unknown prefix: '!'
+     */
+    public function testUnknownResponsePrefix()
+    {
+        $protocol = new TextProtocol();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->once())
+                   ->method('readLine')
+                   ->will($this->returnValue('!'));
+
+        $protocol->read($connection);
+    }
+}

+ 123 - 0
tests/Predis/Protocol/Text/TextResponseReaderTest.php

@@ -0,0 +1,123 @@
+<?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\Text;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+/**
+ *
+ */
+class TextResponseReaderTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testDefaultHandlers()
+    {
+        $reader = new TextResponseReader();
+
+        $this->assertInstanceOf('Predis\Protocol\Text\ResponseStatusHandler', $reader->getHandler('+'));
+        $this->assertInstanceOf('Predis\Protocol\Text\ResponseErrorHandler', $reader->getHandler('-'));
+        $this->assertInstanceOf('Predis\Protocol\Text\ResponseIntegerHandler', $reader->getHandler(':'));
+        $this->assertInstanceOf('Predis\Protocol\Text\ResponseBulkHandler', $reader->getHandler('$'));
+        $this->assertInstanceOf('Predis\Protocol\Text\ResponseMultiBulkHandler', $reader->getHandler('*'));
+
+        $this->assertNull($reader->getHandler('!'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testReplaceHandler()
+    {
+        $handler = $this->getMock('Predis\Protocol\ResponseHandlerInterface');
+
+        $reader = new TextResponseReader();
+        $reader->setHandler('+', $handler);
+
+        $this->assertSame($handler, $reader->getHandler('+'));
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testReadResponse()
+    {
+        $reader = new TextResponseReader();
+
+        $protocol = new ComposableTextProtocol();
+        $protocol->setReader($reader);
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->at(0))
+                   ->method('readLine')
+                   ->will($this->returnValue("+OK"));
+
+        $connection->expects($this->at(1))
+                   ->method('readLine')
+                   ->will($this->returnValue("-ERR error message"));
+
+        $connection->expects($this->at(2))
+                   ->method('readLine')
+                   ->will($this->returnValue(":2"));
+
+        $connection->expects($this->at(3))
+                   ->method('readLine')
+                   ->will($this->returnValue("$-1"));
+
+        $connection->expects($this->at(4))
+                   ->method('readLine')
+                   ->will($this->returnValue("*-1"));
+
+        $this->assertTrue($reader->read($connection));
+        $this->assertEquals("ERR error message", $reader->read($connection));
+        $this->assertSame(2, $reader->read($connection));
+        $this->assertNull($reader->read($connection));
+        $this->assertNull($reader->read($connection));
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\Protocol\ProtocolException
+     * @expectedExceptionMessage Unexpected empty header
+     */
+    public function testEmptyResponseHeader()
+    {
+        $reader = new TextResponseReader();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->once())
+                   ->method('readLine')
+                   ->will($this->returnValue(''));
+
+        $reader->read($connection);
+    }
+    /**
+     * @group disconnected
+     * @expectedException Predis\Protocol\ProtocolException
+     * @expectedExceptionMessage Unknown prefix: '!'
+     */
+    public function testUnknownResponsePrefix()
+    {
+        $reader = new TextResponseReader();
+
+        $connection = $this->getMock('Predis\Connection\ComposableConnectionInterface');
+
+        $connection->expects($this->once())
+                   ->method('readLine')
+                   ->will($this->returnValue('!'));
+
+        $reader->read($connection);
+    }
+}