Browse Source

[test] Add tests for pipeline executors.

Daniele Alessandri 13 years ago
parent
commit
6638776d85

+ 4 - 6
lib/Predis/Pipeline/MultiExecExecutor.php

@@ -75,13 +75,11 @@ class MultiExecExecutor implements PipelineExecutorInterface
         foreach ($commands as $command) {
             $response = $connection->readResponse($command);
 
-            if (!$response instanceof ResponseQueued) {
-                if ($response instanceof ResponseErrorInterface) {
-                    $cmd = $this->profile->createCommand('discard');
-                    $connection->executeCommand($cmd);
+            if ($response instanceof ResponseErrorInterface) {
+                $cmd = $this->profile->createCommand('discard');
+                $connection->executeCommand($cmd);
 
-                    throw new ServerException($response->getMessage());
-                }
+                throw new ServerException($response->getMessage());
             }
         }
 

+ 87 - 0
tests/Predis/Pipeline/FireAndForgetExecutorTest.php

@@ -0,0 +1,87 @@
+<?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\Pipeline;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+use SplQueue;
+use Predis\Profile\ServerProfile;
+
+/**
+ *
+ */
+class FireAndForgetExecutorTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testExecutorWithSingleConnection()
+    {
+        $executor = new FireAndForgetExecutor();
+        $pipeline = $this->getCommandsQueue();
+
+        $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
+        $connection->expects($this->exactly(3))
+                   ->method('writeCommand');
+        $connection->expects($this->never())
+                   ->method('readResponse');
+
+        $replies = $executor->execute($connection, $pipeline);
+
+        $this->assertTrue($pipeline->isEmpty());
+        $this->assertEmpty($replies);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testExecutorWithReplicationConnection()
+    {
+        $executor = new FireAndForgetExecutor();
+        $pipeline = $this->getCommandsQueue();
+
+        $connection = $this->getMock('Predis\Connection\ReplicationConnectionInterface');
+        $connection->expects($this->once())
+                   ->method('switchTo')
+                   ->with('master');
+        $connection->expects($this->exactly(3))
+                   ->method('writeCommand');
+        $connection->expects($this->never())
+                   ->method('readResponse');
+
+        $replies = $executor->execute($connection, $pipeline);
+
+        $this->assertTrue($pipeline->isEmpty());
+        $this->assertEmpty($replies);
+    }
+
+    // ******************************************************************** //
+    // ---- HELPER METHODS ------------------------------------------------ //
+    // ******************************************************************** //
+
+    /**
+     * Returns a list of queued command instances.
+     *
+     * @return SplQueue
+     */
+    protected function getCommandsQueue()
+    {
+        $profile = ServerProfile::getDevelopment();
+
+        $pipeline = new SplQueue();
+        $pipeline->enqueue($profile->createCommand('ping'));
+        $pipeline->enqueue($profile->createCommand('ping'));
+        $pipeline->enqueue($profile->createCommand('ping'));
+
+        return $pipeline;
+    }
+}

+ 130 - 0
tests/Predis/Pipeline/MultiExecExecutorTest.php

@@ -0,0 +1,130 @@
+<?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\Pipeline;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+use SplQueue;
+use Predis\ResponseError;
+use Predis\ResponseQueued;
+use Predis\Profile\ServerProfile;
+
+/**
+ *
+ */
+class MultiExecExecutorTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testExecutorWithSingleConnection()
+    {
+        $executor = new MultiExecExecutor();
+        $pipeline = $this->getCommandsQueue();
+        $queued = new ResponseQueued();
+
+        $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
+        $connection->expects($this->exactly(2))
+                   ->method('executeCommand')
+                   ->will($this->onConsecutiveCalls(true, array('PONG', 'PONG', 'PONG')));
+        $connection->expects($this->exactly(3))
+                   ->method('writeCommand');
+        $connection->expects($this->at(3))
+                   ->method('readResponse')
+                   ->will($this->onConsecutiveCalls($queued, $queued, $queued));
+
+        $replies = $executor->execute($connection, $pipeline);
+
+        $this->assertTrue($pipeline->isEmpty());
+        $this->assertSame(array(true, true, true), $replies);
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\ClientException
+     * @expectedExceptionMessage The underlying transaction has been aborted by the server
+     */
+    public function testExecutorWithAbortedTransaction()
+    {
+        $executor = new MultiExecExecutor();
+        $pipeline = $this->getCommandsQueue();
+
+        $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
+        $connection->expects($this->exactly(2))
+                   ->method('executeCommand')
+                   ->will($this->onConsecutiveCalls(true, null));
+
+        $executor->execute($connection, $pipeline);
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\ServerException
+     * @expectedExceptionMessage ERR Test error
+     */
+    public function testExecutorWithErrorInTransaction()
+    {
+        $executor = new MultiExecExecutor();
+        $pipeline = $this->getCommandsQueue();
+        $queued = new ResponseQueued();
+        $error = new ResponseError('ERR Test error');
+
+        $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
+        $connection->expects($this->at(0))
+                   ->method('executeCommand')
+                   ->will($this->returnValue(true));
+        $connection->expects($this->exactly(3))
+                   ->method('readResponse')
+                   ->will($this->onConsecutiveCalls($queued, $queued, $error));
+        $connection->expects($this->at(7))
+                   ->method('executeCommand')
+                   ->with($this->isInstanceOf('Predis\Command\TransactionDiscard'));
+
+        $executor->execute($connection, $pipeline);
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\ClientException
+     * @expectedExceptionMessage Predis\Pipeline\MultiExecExecutor can be used only with single connections
+     */
+    public function testExecutorWithAggregatedConnection()
+    {
+        $executor = new MultiExecExecutor();
+        $pipeline = $this->getCommandsQueue();
+
+        $connection = $this->getMock('Predis\Connection\ReplicationConnectionInterface');
+
+        $replies = $executor->execute($connection, $pipeline);
+    }
+
+    // ******************************************************************** //
+    // ---- HELPER METHODS ------------------------------------------------ //
+    // ******************************************************************** //
+
+    /**
+     * Returns a list of queued command instances.
+     *
+     * @return SplQueue
+     */
+    protected function getCommandsQueue()
+    {
+        $profile = ServerProfile::getDevelopment();
+
+        $pipeline = new SplQueue();
+        $pipeline->enqueue($profile->createCommand('ping'));
+        $pipeline->enqueue($profile->createCommand('ping'));
+        $pipeline->enqueue($profile->createCommand('ping'));
+
+        return $pipeline;
+    }
+}

+ 109 - 0
tests/Predis/Pipeline/StandardExecutorTest.php

@@ -0,0 +1,109 @@
+<?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\Pipeline;
+
+use \PHPUnit_Framework_TestCase as StandardTestCase;
+
+use SplQueue;
+use Predis\ResponseError;
+use Predis\Profile\ServerProfile;
+
+/**
+ *
+ */
+class StandardExecutorTest extends StandardTestCase
+{
+    /**
+     * @group disconnected
+     */
+    public function testExecutorWithSingleConnection()
+    {
+        $executor = new StandardExecutor();
+        $pipeline = $this->getCommandsQueue();
+
+        $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
+        $connection->expects($this->exactly(3))
+                   ->method('writeCommand');
+        $connection->expects($this->exactly(3))
+                   ->method('readResponse')
+                   ->will($this->returnValue('PONG'));
+
+        $replies = $executor->execute($connection, $pipeline);
+
+        $this->assertTrue($pipeline->isEmpty());
+        $this->assertSame(array('PONG', 'PONG', 'PONG'), $replies);
+    }
+
+    /**
+     * @group disconnected
+     */
+    public function testExecutorWithReplicationConnection()
+    {
+        $executor = new StandardExecutor();
+        $pipeline = $this->getCommandsQueue();
+
+        $connection = $this->getMock('Predis\Connection\ReplicationConnectionInterface');
+        $connection->expects($this->once())
+                   ->method('switchTo')
+                   ->with('master');
+        $connection->expects($this->exactly(3))
+                   ->method('writeCommand');
+        $connection->expects($this->exactly(3))
+                   ->method('readResponse')
+                   ->will($this->returnValue('PONG'));
+
+        $replies = $executor->execute($connection, $pipeline);
+
+        $this->assertTrue($pipeline->isEmpty());
+        $this->assertSame(array('PONG', 'PONG', 'PONG'), $replies);
+    }
+
+    /**
+     * @group disconnected
+     * @expectedException Predis\ServerException
+     * @expectedExceptionMessage ERR Test error
+     */
+    public function testExecutorCanThrowExceptions()
+    {
+        $executor = new StandardExecutor(true);
+        $pipeline = $this->getCommandsQueue();
+        $error = new ResponseError('ERR Test error');
+
+        $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
+        $connection->expects($this->once())
+                   ->method('readResponse')
+                   ->will($this->returnValue($error));
+
+        $executor->execute($connection, $pipeline);
+    }
+
+    // ******************************************************************** //
+    // ---- HELPER METHODS ------------------------------------------------ //
+    // ******************************************************************** //
+
+    /**
+     * Returns a list of queued command instances.
+     *
+     * @return SplQueue
+     */
+    protected function getCommandsQueue()
+    {
+        $profile = ServerProfile::getDevelopment();
+
+        $pipeline = new SplQueue();
+        $pipeline->enqueue($profile->createCommand('ping'));
+        $pipeline->enqueue($profile->createCommand('ping'));
+        $pipeline->enqueue($profile->createCommand('ping'));
+
+        return $pipeline;
+    }
+}