diff --git a/CHANGELOG.md b/CHANGELOG.md index f8c1961a..10faeb7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,11 @@ v1.1.0 (2015-xx-xx) must use either the `tls` or `rediss` scheme. +- __FIX__: prevent failures when `Predis\Connection\StreamConnection` serializes + commands with holes in their arguments (e.g. `[0 => 'key:0', 1 => 'key:1']`). + The same fix has been applied to `Predis\Protocol\Text\RequestSerializer`. + (ISSUE #316). + v1.0.3 (2015-07-30) ================================================================================ diff --git a/src/Connection/StreamConnection.php b/src/Connection/StreamConnection.php index 946e25d6..b1c682c7 100644 --- a/src/Connection/StreamConnection.php +++ b/src/Connection/StreamConnection.php @@ -380,8 +380,7 @@ class StreamConnection extends AbstractConnection $buffer = "*{$reqlen}\r\n\${$cmdlen}\r\n{$commandID}\r\n"; - for ($i = 0, $reqlen--; $i < $reqlen; ++$i) { - $argument = $arguments[$i]; + foreach ($arguments as $argument) { $arglen = strlen($argument); $buffer .= "\${$arglen}\r\n{$argument}\r\n"; } diff --git a/src/Protocol/Text/RequestSerializer.php b/src/Protocol/Text/RequestSerializer.php index c8cbbfbc..859595b1 100644 --- a/src/Protocol/Text/RequestSerializer.php +++ b/src/Protocol/Text/RequestSerializer.php @@ -36,8 +36,7 @@ class RequestSerializer implements RequestSerializerInterface $buffer = "*{$reqlen}\r\n\${$cmdlen}\r\n{$commandID}\r\n"; - for ($i = 0, $reqlen--; $i < $reqlen; ++$i) { - $argument = $arguments[$i]; + foreach ($arguments as $argument) { $arglen = strlen($argument); $buffer .= "\${$arglen}\r\n{$argument}\r\n"; } diff --git a/tests/PHPUnit/PredisConnectionTestCase.php b/tests/PHPUnit/PredisConnectionTestCase.php index 1120b58e..be0e6160 100644 --- a/tests/PHPUnit/PredisConnectionTestCase.php +++ b/tests/PHPUnit/PredisConnectionTestCase.php @@ -241,6 +241,19 @@ abstract class PredisConnectionTestCase extends PredisTestCase $this->assertEquals('PONG', $connection->executeCommand($cmdPing)); } + /** + * @group disconnected + */ + public function testExecutesCommandWithHolesInArguments() + { + $profile = $this->getCurrentProfile(); + $cmdDel = $profile->createCommand('mget', array(0 => 'key:0', 2 => 'key:2')); + + $connection = $this->createConnection(); + + $this->assertSame(array(null, null), $connection->executeCommand($cmdDel)); + } + /** * @group connected */ diff --git a/tests/Predis/Protocol/Text/RequestSerializerTest.php b/tests/Predis/Protocol/Text/RequestSerializerTest.php index 84ce5098..896f3f08 100644 --- a/tests/Predis/Protocol/Text/RequestSerializerTest.php +++ b/tests/Predis/Protocol/Text/RequestSerializerTest.php @@ -61,4 +61,27 @@ class RequestSerializerTest extends PredisTestCase $this->assertSame("*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n", $result); } + + /** + * @group disconnected + */ + public function testSerializerDoesNotBreakOnArgumentsWithHoles() + { + $serializer = new RequestSerializer(); + + $command = $this->getMock('Predis\Command\CommandInterface'); + + $command->expects($this->once()) + ->method('getId') + ->will($this->returnValue('DEL')); + + $command->expects($this->once()) + ->method('getArguments') + ->will($this->returnValue(array(0 => 'key:1', 2 => 'key:2'))); + + $result = $serializer->serialize($command); + + $this->assertSame("*3\r\n$3\r\nDEL\r\n$5\r\nkey:1\r\n$5\r\nkey:2\r\n", $result); + } + }