Quellcode durchsuchen

Backported changes from the mainline library to the PHP 5.2 branch (up to commit 17f83a5)

Daniele Alessandri vor 14 Jahren
Ursprung
Commit
ada8878295

+ 36 - 0
CHANGELOG

@@ -1,3 +1,39 @@
+v0.6.6 (2011-xx-xx)
+  * Switched to Redis 2.2 as the default server profile (there are no changes 
+    that would break compatibility with previous releases). Long command names 
+    are no more supported by default but if you need them you can still require 
+    Predis_Compatibility.php to avoid breaking compatibility.
+
+  * Added a VERSION constant to Predis\Client.
+
+  * Some performance improvements for multibulk replies (parsing them is about 
+    16% faster than the previous version). A few core classes have been heavily 
+    optimized to reduce overhead when creating new instances.
+
+  * Predis now uses by default a new protocol reader, more lightweight and 
+    faster than the default handler-based one. Users can revert to the old 
+    protocol reader with the 'reader' client option set to 'composable'.
+    This client option can also accept custom reader classes implementing the 
+    new Predis\IResponseReader interface.
+
+  * Added support for connecting to Redis using UNIX domain sockets (ISSUE #25).
+
+  * The "read_write_timeout" connection parameter can now be set to 0 or false 
+    to disable read and write timeouts on connections. The old behaviour of -1 
+    is still intact.
+
+  * ZUNIONSTORE and ZINTERSTORE can accept an array to specify a list of the 
+    source keys to be used to populate the destination key.
+
+  * MGET, SINTER, SUNION and SDIFF can accept an array to specify the list of 
+    keys. SINTERSTORE, SUNIONSTORE and SDIFFSTORE can also accept an array to 
+    specify the list of source keys.
+
+  * SUBSCRIBE and PSUBSCRIBE can accept a list of channels for subscription.
+
+  * FIX: some client-side clean-ups for MULTI/EXEC were handled incorrectly in 
+    a couple of corner cases. See also ISSUE #27.
+
 v0.6.5 (2011-02-12)
 v0.6.5 (2011-02-12)
   * FIX: due to an untested internal change introduced in v0.6.4, a wrong
   * FIX: due to an untested internal change introduced in v0.6.4, a wrong
     handling of bulk reads of zero-length values was producing protocol
     handling of bulk reads of zero-length values was producing protocol

+ 1 - 0
README.markdown

@@ -22,6 +22,7 @@ to be implemented soon in Predis.
 - Command pipelining on single and multiple connections (transparent).
 - Command pipelining on single and multiple connections (transparent).
 - Abstraction for Redis transactions (>= 2.0) with support for CAS operations (>= 2.2).
 - Abstraction for Redis transactions (>= 2.0) with support for CAS operations (>= 2.2).
 - Lazy connections (connections to Redis instances are only established just in time).
 - Lazy connections (connections to Redis instances are only established just in time).
+- Ability to connect to Redis using TCP/IP or UNIX domain sockets.
 - Flexible system to define and register your own set of commands to a client instance.
 - Flexible system to define and register your own set of commands to a client instance.
 
 
 
 

+ 1 - 1
VERSION

@@ -1 +1 @@
-0.6.5
+0.6.6-dev

+ 1 - 1
examples/CustomDistributionStrategy.php

@@ -3,7 +3,7 @@ require_once 'SharedConfigurations.php';
 
 
 // Developers can customize the distribution strategy used by the client 
 // Developers can customize the distribution strategy used by the client 
 // to distribute keys among a cluster of servers simply by creating a class 
 // to distribute keys among a cluster of servers simply by creating a class 
-// that implements the Predis_Distribution_IDistributionAlgorithm interface.
+// that implements the Predis_Distribution_IDistributionStrategy interface.
 
 
 class NaiveDistributionStrategy
 class NaiveDistributionStrategy
     implements Predis_Distribution_IDistributionStrategy {
     implements Predis_Distribution_IDistributionStrategy {

+ 1 - 1
examples/PubSubContext.php

@@ -5,7 +5,7 @@ require_once 'SharedConfigurations.php';
 // events published on certain channels (PUBSUB).
 // events published on certain channels (PUBSUB).
 
 
 // Create a client and disable r/w timeout on the socket
 // Create a client and disable r/w timeout on the socket
-$redis  = new Predis_Client($single_server + array('read_write_timeout' => -1));
+$redis  = new Predis_Client($single_server + array('read_write_timeout' => 0));
 
 
 // Initialize a new pubsub context
 // Initialize a new pubsub context
 $pubsub = $redis->pubSubContext();
 $pubsub = $redis->pubSubContext();

Datei-Diff unterdrückt, da er zu groß ist
+ 585 - 281
lib/Predis.php


+ 239 - 0
lib/Predis_Compatibility.php

@@ -1,5 +1,8 @@
 <?php
 <?php
+
 Predis_RedisServerProfile::registerProfile('Predis_RedisServer_v1_0', '1.0');
 Predis_RedisServerProfile::registerProfile('Predis_RedisServer_v1_0', '1.0');
+Predis_RedisServerProfile::registerProfile('Predis_RedisServer_v1_2_LongNames', '1.2');
+Predis_RedisServerProfile::registerProfile('Predis_RedisServer_v2_0_LongNames', '2.0');
 
 
 class Predis_RedisServer_v1_0 extends Predis_RedisServerProfile {
 class Predis_RedisServer_v1_0 extends Predis_RedisServerProfile {
     public function getVersion() { return '1.0'; }
     public function getVersion() { return '1.0'; }
@@ -131,6 +134,242 @@ class Predis_RedisServer_v1_0 extends Predis_RedisServerProfile {
     }
     }
 }
 }
 
 
+class Predis_RedisServer_v1_2_LongNames extends Predis_RedisServerProfile {
+    public function getVersion() { return '1.2'; }
+    public function getSupportedCommands() {
+        return array(
+            /* miscellaneous commands */
+            'ping'      => 'Predis_Commands_Ping',
+            'echo'      => 'Predis_Commands_DoEcho',
+            'auth'      => 'Predis_Commands_Auth',
+
+            /* connection handling */
+            'quit'      => 'Predis_Commands_Quit',
+
+            /* commands operating on string values */
+            'set'                     => 'Predis_Commands_Set',
+            'setnx'                   => 'Predis_Commands_SetPreserve',
+                'setPreserve'         => 'Predis_Commands_SetPreserve',
+            'mset'                    => 'Predis_Commands_SetMultiple',
+                'setMultiple'         => 'Predis_Commands_SetMultiple',
+            'msetnx'                  => 'Predis_Commands_SetMultiplePreserve',
+                'setMultiplePreserve' => 'Predis_Commands_SetMultiplePreserve',
+            'get'                     => 'Predis_Commands_Get',
+            'mget'                    => 'Predis_Commands_GetMultiple',
+                'getMultiple'         => 'Predis_Commands_GetMultiple',
+            'getset'                  => 'Predis_Commands_GetSet',
+                'getSet'              => 'Predis_Commands_GetSet',
+            'incr'                    => 'Predis_Commands_Increment',
+                'increment'           => 'Predis_Commands_Increment',
+            'incrby'                  => 'Predis_Commands_IncrementBy',
+                'incrementBy'         => 'Predis_Commands_IncrementBy',
+            'decr'                    => 'Predis_Commands_Decrement',
+                'decrement'           => 'Predis_Commands_Decrement',
+            'decrby'                  => 'Predis_Commands_DecrementBy',
+                'decrementBy'         => 'Predis_Commands_DecrementBy',
+            'exists'                  => 'Predis_Commands_Exists',
+            'del'                     => 'Predis_Commands_Delete',
+                'delete'              => 'Predis_Commands_Delete',
+            'type'                    => 'Predis_Commands_Type',
+
+            /* commands operating on the key space */
+            'keys'               => 'Predis_Commands_Keys_v1_2',
+            'randomkey'          => 'Predis_Commands_RandomKey',
+                'randomKey'      => 'Predis_Commands_RandomKey',
+            'rename'             => 'Predis_Commands_Rename',
+            'renamenx'           => 'Predis_Commands_RenamePreserve',
+                'renamePreserve' => 'Predis_Commands_RenamePreserve',
+            'expire'             => 'Predis_Commands_Expire',
+            'expireat'           => 'Predis_Commands_ExpireAt',
+                'expireAt'       => 'Predis_Commands_ExpireAt',
+            'dbsize'             => 'Predis_Commands_DatabaseSize',
+                'databaseSize'   => 'Predis_Commands_DatabaseSize',
+            'ttl'                => 'Predis_Commands_TimeToLive',
+                'timeToLive'     => 'Predis_Commands_TimeToLive',
+
+            /* commands operating on lists */
+            'rpush'            => 'Predis_Commands_ListPushTail',
+                'pushTail'     => 'Predis_Commands_ListPushTail',
+            'lpush'            => 'Predis_Commands_ListPushHead',
+                'pushHead'     => 'Predis_Commands_ListPushHead',
+            'llen'             => 'Predis_Commands_ListLength',
+                'listLength'   => 'Predis_Commands_ListLength',
+            'lrange'           => 'Predis_Commands_ListRange',
+                'listRange'    => 'Predis_Commands_ListRange',
+            'ltrim'            => 'Predis_Commands_ListTrim',
+                'listTrim'     => 'Predis_Commands_ListTrim',
+            'lindex'           => 'Predis_Commands_ListIndex',
+                'listIndex'    => 'Predis_Commands_ListIndex',
+            'lset'             => 'Predis_Commands_ListSet',
+                'listSet'      => 'Predis_Commands_ListSet',
+            'lrem'             => 'Predis_Commands_ListRemove',
+                'listRemove'   => 'Predis_Commands_ListRemove',
+            'lpop'             => 'Predis_Commands_ListPopFirst',
+                'popFirst'     => 'Predis_Commands_ListPopFirst',
+            'rpop'             => 'Predis_Commands_ListPopLast',
+                'popLast'      => 'Predis_Commands_ListPopLast',
+            'rpoplpush'        => 'Predis_Commands_ListPopLastPushHead',
+                'listPopLastPushHead'  => 'Predis_Commands_ListPopLastPushHead',
+
+            /* commands operating on sets */
+            'sadd'                      => 'Predis_Commands_SetAdd',
+                'setAdd'                => 'Predis_Commands_SetAdd',
+            'srem'                      => 'Predis_Commands_SetRemove',
+                'setRemove'             => 'Predis_Commands_SetRemove',
+            'spop'                      => 'Predis_Commands_SetPop',
+                'setPop'                => 'Predis_Commands_SetPop',
+            'smove'                     => 'Predis_Commands_SetMove',
+                'setMove'               => 'Predis_Commands_SetMove',
+            'scard'                     => 'Predis_Commands_SetCardinality',
+                'setCardinality'        => 'Predis_Commands_SetCardinality',
+            'sismember'                 => 'Predis_Commands_SetIsMember',
+                'setIsMember'           => 'Predis_Commands_SetIsMember',
+            'sinter'                    => 'Predis_Commands_SetIntersection',
+                'setIntersection'       => 'Predis_Commands_SetIntersection',
+            'sinterstore'               => 'Predis_Commands_SetIntersectionStore',
+                'setIntersectionStore'  => 'Predis_Commands_SetIntersectionStore',
+            'sunion'                    => 'Predis_Commands_SetUnion',
+                'setUnion'              => 'Predis_Commands_SetUnion',
+            'sunionstore'               => 'Predis_Commands_SetUnionStore',
+                'setUnionStore'         => 'Predis_Commands_SetUnionStore',
+            'sdiff'                     => 'Predis_Commands_SetDifference',
+                'setDifference'         => 'Predis_Commands_SetDifference',
+            'sdiffstore'                => 'Predis_Commands_SetDifferenceStore',
+                'setDifferenceStore'    => 'Predis_Commands_SetDifferenceStore',
+            'smembers'                  => 'Predis_Commands_SetMembers',
+                'setMembers'            => 'Predis_Commands_SetMembers',
+            'srandmember'               => 'Predis_Commands_SetRandomMember',
+                'setRandomMember'       => 'Predis_Commands_SetRandomMember',
+
+            /* commands operating on sorted sets */
+            'zadd'                          => 'Predis_Commands_ZSetAdd',
+                'zsetAdd'                   => 'Predis_Commands_ZSetAdd',
+            'zincrby'                       => 'Predis_Commands_ZSetIncrementBy',
+                'zsetIncrementBy'           => 'Predis_Commands_ZSetIncrementBy',
+            'zrem'                          => 'Predis_Commands_ZSetRemove',
+                'zsetRemove'                => 'Predis_Commands_ZSetRemove',
+            'zrange'                        => 'Predis_Commands_ZSetRange',
+                'zsetRange'                 => 'Predis_Commands_ZSetRange',
+            'zrevrange'                     => 'Predis_Commands_ZSetReverseRange',
+                'zsetReverseRange'          => 'Predis_Commands_ZSetReverseRange',
+            'zrangebyscore'                 => 'Predis_Commands_ZSetRangeByScore',
+                'zsetRangeByScore'          => 'Predis_Commands_ZSetRangeByScore',
+            'zcard'                         => 'Predis_Commands_ZSetCardinality',
+                'zsetCardinality'           => 'Predis_Commands_ZSetCardinality',
+            'zscore'                        => 'Predis_Commands_ZSetScore',
+                'zsetScore'                 => 'Predis_Commands_ZSetScore',
+            'zremrangebyscore'              => 'Predis_Commands_ZSetRemoveRangeByScore',
+                'zsetRemoveRangeByScore'    => 'Predis_Commands_ZSetRemoveRangeByScore',
+
+            /* multiple databases handling commands */
+            'select'                => 'Predis_Commands_SelectDatabase',
+                'selectDatabase'    => 'Predis_Commands_SelectDatabase',
+            'move'                  => 'Predis_Commands_MoveKey',
+                'moveKey'           => 'Predis_Commands_MoveKey',
+            'flushdb'               => 'Predis_Commands_FlushDatabase',
+                'flushDatabase'     => 'Predis_Commands_FlushDatabase',
+            'flushall'              => 'Predis_Commands_FlushAll',
+                'flushDatabases'    => 'Predis_Commands_FlushAll',
+
+            /* sorting */
+            'sort'                  => 'Predis_Commands_Sort',
+
+            /* remote server control commands */
+            'info'                  => 'Predis_Commands_Info',
+            'slaveof'               => 'Predis_Commands_SlaveOf',
+                'slaveOf'           => 'Predis_Commands_SlaveOf',
+
+            /* persistence control commands */
+            'save'                  => 'Predis_Commands_Save',
+            'bgsave'                => 'Predis_Commands_BackgroundSave',
+                'backgroundSave'    => 'Predis_Commands_BackgroundSave',
+            'lastsave'              => 'Predis_Commands_LastSave',
+                'lastSave'          => 'Predis_Commands_LastSave',
+            'shutdown'              => 'Predis_Commands_Shutdown',
+            'bgrewriteaof'                      =>  'Predis_Commands_BackgroundRewriteAppendOnlyFile',
+            'backgroundRewriteAppendOnlyFile'   =>  'Predis_Commands_BackgroundRewriteAppendOnlyFile',
+        );
+    }
+}
+
+class Predis_RedisServer_v2_0_LongNames extends Predis_RedisServer_v1_2_LongNames {
+    public function getVersion() { return '2.0'; }
+    public function getSupportedCommands() {
+        return array_merge(parent::getSupportedCommands(), array(
+            /* transactions */
+            'multi'                     => 'Predis_Commands_Multi',
+            'exec'                      => 'Predis_Commands_Exec',
+            'discard'                   => 'Predis_Commands_Discard',
+
+            /* commands operating on string values */
+            'setex'                     => 'Predis_Commands_SetExpire',
+                'setExpire'             => 'Predis_Commands_SetExpire',
+            'append'                    => 'Predis_Commands_Append',
+            'substr'                    => 'Predis_Commands_Substr',
+
+            /* commands operating on the key space */
+            'keys'                      => 'Predis_Commands_Keys',
+
+            /* commands operating on lists */
+            'blpop'                     => 'Predis_Commands_ListPopFirstBlocking',
+                'popFirstBlocking'      => 'Predis_Commands_ListPopFirstBlocking',
+            'brpop'                     => 'Predis_Commands_ListPopLastBlocking',
+                'popLastBlocking'       => 'Predis_Commands_ListPopLastBlocking',
+
+            /* commands operating on sorted sets */
+            'zunionstore'               => 'Predis_Commands_ZSetUnionStore',
+                'zsetUnionStore'        => 'Predis_Commands_ZSetUnionStore',
+            'zinterstore'               => 'Predis_Commands_ZSetIntersectionStore',
+                'zsetIntersectionStore' => 'Predis_Commands_ZSetIntersectionStore',
+            'zcount'                    => 'Predis_Commands_ZSetCount',
+                'zsetCount'             => 'Predis_Commands_ZSetCount',
+            'zrank'                     => 'Predis_Commands_ZSetRank',
+                'zsetRank'              => 'Predis_Commands_ZSetRank',
+            'zrevrank'                  => 'Predis_Commands_ZSetReverseRank',
+                'zsetReverseRank'       => 'Predis_Commands_ZSetReverseRank',
+            'zremrangebyrank'           => 'Predis_Commands_ZSetRemoveRangeByRank',
+                'zsetRemoveRangeByRank' => 'Predis_Commands_ZSetRemoveRangeByRank',
+
+            /* commands operating on hashes */
+            'hset'                      => 'Predis_Commands_HashSet',
+                'hashSet'               => 'Predis_Commands_HashSet',
+            'hsetnx'                    => 'Predis_Commands_HashSetPreserve',
+                'hashSetPreserve'       => 'Predis_Commands_HashSetPreserve',
+            'hmset'                     => 'Predis_Commands_HashSetMultiple',
+                'hashSetMultiple'       => 'Predis_Commands_HashSetMultiple',
+            'hincrby'                   => 'Predis_Commands_HashIncrementBy',
+                'hashIncrementBy'       => 'Predis_Commands_HashIncrementBy',
+            'hget'                      => 'Predis_Commands_HashGet',
+                'hashGet'               => 'Predis_Commands_HashGet',
+            'hmget'                     => 'Predis_Commands_HashGetMultiple',
+                'hashGetMultiple'       => 'Predis_Commands_HashGetMultiple',
+            'hdel'                      => 'Predis_Commands_HashDelete',
+                'hashDelete'            => 'Predis_Commands_HashDelete',
+            'hexists'                   => 'Predis_Commands_HashExists',
+                'hashExists'            => 'Predis_Commands_HashExists',
+            'hlen'                      => 'Predis_Commands_HashLength',
+                'hashLength'            => 'Predis_Commands_HashLength',
+            'hkeys'                     => 'Predis_Commands_HashKeys',
+                'hashKeys'              => 'Predis_Commands_HashKeys',
+            'hvals'                     => 'Predis_Commands_HashValues',
+                'hashValues'            => 'Predis_Commands_HashValues',
+            'hgetall'                   => 'Predis_Commands_HashGetAll',
+                'hashGetAll'            => 'Predis_Commands_HashGetAll',
+
+            /* publish - subscribe */
+            'subscribe'                 => 'Predis_Commands_Subscribe',
+            'unsubscribe'               => 'Predis_Commands_Unsubscribe',
+            'psubscribe'                => 'Predis_Commands_SubscribeByPattern',
+            'punsubscribe'              => 'Predis_Commands_UnsubscribeByPattern',
+            'publish'                   => 'Predis_Commands_Publish',
+
+            /* remote server control commands */
+            'config'                    => 'Predis_Commands_Config',
+                'configuration'         => 'Predis_Commands_Config',
+        ));
+    }
+}
+
 /* ------------------------------------------------------------------------- */
 /* ------------------------------------------------------------------------- */
 
 
 /* miscellaneous commands */
 /* miscellaneous commands */

+ 15 - 0
phpunit.xml.dist

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit bootstrap="test/bootstrap.php">
+    <testsuites>
+        <testsuite name="Predis Test Suite">
+            <directory>test/</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory suffix=".php">lib/Predis/</directory>
+        </whitelist>
+    </filter>
+</phpunit>

+ 103 - 76
test/PredisClientFeatures.php → test/ClientFeaturesTest.php

@@ -1,19 +1,14 @@
 <?php
 <?php
-define('I_AM_AWARE_OF_THE_DESTRUCTIVE_POWER_OF_THIS_TEST_SUITE', false);
 
 
-require_once 'PHPUnit/Framework.php';
-require_once 'PredisShared.php';
-require_once '../lib/Predis_Compatibility.php';
-
-class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
+class ClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
     public $redis;
     public $redis;
 
 
-    protected function setUp() { 
+    protected function setUp() {
         $this->redis = RC::getConnection();
         $this->redis = RC::getConnection();
-        $this->redis->flushDatabase();
+        $this->redis->flushdb();
     }
     }
 
 
-    protected function tearDown() { 
+    protected function tearDown() {
     }
     }
 
 
     protected function onNotSuccessfulTest(Exception $exception) {
     protected function onNotSuccessfulTest(Exception $exception) {
@@ -89,7 +84,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
     function testCommand_InlineWithNoArguments() {
     function testCommand_InlineWithNoArguments() {
         $cmd = new Predis_Compatibility_v1_0_Commands_Ping();
         $cmd = new Predis_Compatibility_v1_0_Commands_Ping();
 
 
-        $this->assertType('Predis_InlineCommand', $cmd);
+        $this->assertInstanceOf('Predis_InlineCommand', $cmd);
         $this->assertEquals('PING', $cmd->getCommandId());
         $this->assertEquals('PING', $cmd->getCommandId());
         $this->assertFalse($cmd->closesConnection());
         $this->assertFalse($cmd->closesConnection());
         $this->assertFalse($cmd->canBeHashed());
         $this->assertFalse($cmd->canBeHashed());
@@ -101,7 +96,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $cmd = new Predis_Compatibility_v1_0_Commands_Get();
         $cmd = new Predis_Compatibility_v1_0_Commands_Get();
         $cmd->setArgumentsArray(array('key'));
         $cmd->setArgumentsArray(array('key'));
 
 
-        $this->assertType('Predis_InlineCommand', $cmd);
+        $this->assertInstanceOf('Predis_InlineCommand', $cmd);
         $this->assertEquals('GET', $cmd->getCommandId());
         $this->assertEquals('GET', $cmd->getCommandId());
         $this->assertFalse($cmd->closesConnection());
         $this->assertFalse($cmd->closesConnection());
         $this->assertTrue($cmd->canBeHashed());
         $this->assertTrue($cmd->canBeHashed());
@@ -113,7 +108,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $cmd = new Predis_Compatibility_v1_0_Commands_Set();
         $cmd = new Predis_Compatibility_v1_0_Commands_Set();
         $cmd->setArgumentsArray(array('key', 'value'));
         $cmd->setArgumentsArray(array('key', 'value'));
 
 
-        $this->assertType('Predis_BulkCommand', $cmd);
+        $this->assertInstanceOf('Predis_BulkCommand', $cmd);
         $this->assertEquals('SET', $cmd->getCommandId());
         $this->assertEquals('SET', $cmd->getCommandId());
         $this->assertFalse($cmd->closesConnection());
         $this->assertFalse($cmd->closesConnection());
         $this->assertTrue($cmd->canBeHashed());
         $this->assertTrue($cmd->canBeHashed());
@@ -125,7 +120,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $cmd = new Predis_Commands_SetMultiple();
         $cmd = new Predis_Commands_SetMultiple();
         $cmd->setArgumentsArray(array('key1', 'value1', 'key2', 'value2'));
         $cmd->setArgumentsArray(array('key1', 'value1', 'key2', 'value2'));
 
 
-        $this->assertType('Predis_MultiBulkCommand', $cmd);
+        $this->assertInstanceOf('Predis_MultiBulkCommand', $cmd);
         $this->assertEquals('MSET', $cmd->getCommandId());
         $this->assertEquals('MSET', $cmd->getCommandId());
         $this->assertFalse($cmd->closesConnection());
         $this->assertFalse($cmd->closesConnection());
         $this->assertFalse($cmd->canBeHashed());
         $this->assertFalse($cmd->canBeHashed());
@@ -155,11 +150,11 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
     /* RedisServerProfile and derivates */
     /* RedisServerProfile and derivates */
 
 
     function testRedisServerProfile_GetSpecificVersions() {
     function testRedisServerProfile_GetSpecificVersions() {
-        $this->assertType('Predis_RedisServer_v1_0', Predis_RedisServerProfile::get('1.0'));
-        $this->assertType('Predis_RedisServer_v1_2', Predis_RedisServerProfile::get('1.2'));
-        $this->assertType('Predis_RedisServer_v2_0', Predis_RedisServerProfile::get('2.0'));
-        $this->assertType('Predis_RedisServer_vNext', Predis_RedisServerProfile::get('dev'));
-        $this->assertType('Predis_RedisServerProfile', Predis_RedisServerProfile::get('default'));
+        $this->assertInstanceOf('Predis_RedisServer_v1_0', Predis_RedisServerProfile::get('1.0'));
+        $this->assertInstanceOf('Predis_RedisServer_v1_2', Predis_RedisServerProfile::get('1.2'));
+        $this->assertInstanceOf('Predis_RedisServer_v2_0', Predis_RedisServerProfile::get('2.0'));
+        $this->assertInstanceOf('Predis_RedisServer_vNext', Predis_RedisServerProfile::get('dev'));
+        $this->assertInstanceOf('Predis_RedisServerProfile', Predis_RedisServerProfile::get('default'));
         $this->assertEquals(Predis_RedisServerProfile::get('default'), Predis_RedisServerProfile::getDefault());
         $this->assertEquals(Predis_RedisServerProfile::get('default'), Predis_RedisServerProfile::getDefault());
     }
     }
 
 
@@ -181,12 +176,12 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $profile = Predis_RedisServerProfile::get('1.0');
         $profile = Predis_RedisServerProfile::get('1.0');
 
 
         $cmdNoArgs = $profile->createCommand('info');
         $cmdNoArgs = $profile->createCommand('info');
-        $this->assertType('Predis_Compatibility_v1_0_Commands_Info', $cmdNoArgs);
+        $this->assertInstanceOf('Predis_Compatibility_v1_0_Commands_Info', $cmdNoArgs);
         $this->assertNull($cmdNoArgs->getArgument());
         $this->assertNull($cmdNoArgs->getArgument());
 
 
         $args = array('key1', 'key2');
         $args = array('key1', 'key2');
         $cmdWithArgs = $profile->createCommand('mget', $args);
         $cmdWithArgs = $profile->createCommand('mget', $args);
-        $this->assertType('Predis_Compatibility_v1_0_Commands_GetMultiple', $cmdWithArgs);
+        $this->assertInstanceOf('Predis_Compatibility_v1_0_Commands_GetMultiple', $cmdWithArgs);
         $this->assertEquals($args[0], $cmdWithArgs->getArgument()); // TODO: why?
         $this->assertEquals($args[0], $cmdWithArgs->getArgument()); // TODO: why?
         $this->assertEquals($args[0], $cmdWithArgs->getArgument(0));
         $this->assertEquals($args[0], $cmdWithArgs->getArgument(0));
         $this->assertEquals($args[1], $cmdWithArgs->getArgument(1));
         $this->assertEquals($args[1], $cmdWithArgs->getArgument(1));
@@ -207,7 +202,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $this->assertFalse($profile->supportsCommand($cmdId));
         $this->assertFalse($profile->supportsCommand($cmdId));
         $profile->registerCommand(new $cmdClass(), $cmdId);
         $profile->registerCommand(new $cmdClass(), $cmdId);
         $this->assertTrue($profile->supportsCommand($cmdId));
         $this->assertTrue($profile->supportsCommand($cmdId));
-        $this->assertType($cmdClass, $profile->createCommand($cmdId));
+        $this->assertInstanceOf($cmdClass, $profile->createCommand($cmdId));
     }
     }
 
 
 
 
@@ -279,7 +274,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         catch (Predis_CommunicationException $exception) {
         catch (Predis_CommunicationException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $this->assertType('Predis_CommunicationException', $thrownException);
+        $this->assertInstanceOf('Predis_CommunicationException', $thrownException);
         $this->assertEquals($expectedMessage, $thrownException->getMessage());
         $this->assertEquals($expectedMessage, $thrownException->getMessage());
     }
     }
 
 
@@ -287,7 +282,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $connection = new Predis_Connection(RC::getConnectionParameters());
         $connection = new Predis_Connection(RC::getConnectionParameters());
 
 
         $this->assertFalse($connection->isConnected());
         $this->assertFalse($connection->isConnected());
-        $this->assertType('resource', $connection->getSocket());
+        $this->assertInternalType('resource', $connection->getSocket());
         $this->assertTrue($connection->isConnected());
         $this->assertTrue($connection->isConnected());
     }
     }
 
 
@@ -328,7 +323,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         catch (Predis_CommunicationException $exception) {
         catch (Predis_CommunicationException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $this->assertType('Predis_CommunicationException', $thrownException);
+        $this->assertInstanceOf('Predis_CommunicationException', $thrownException);
         $this->assertEquals((float)(time() - $start), $timeout, '', 1);
         $this->assertEquals((float)(time() - $start), $timeout, '', 1);
     }
     }
 
 
@@ -347,7 +342,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         catch (Predis_CommunicationException $exception) {
         catch (Predis_CommunicationException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $this->assertType('Predis_CommunicationException', $thrownException);
+        $this->assertInstanceOf('Predis_CommunicationException', $thrownException);
         $this->assertEquals($expectedMessage, $thrownException->getMessage());
         $this->assertEquals($expectedMessage, $thrownException->getMessage());
         $this->assertEquals((float)(time() - $start), $timeout, '', 1);
         $this->assertEquals((float)(time() - $start), $timeout, '', 1);
     }
     }
@@ -357,19 +352,12 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
 
 
     function testResponseReader_OptionIterableMultiBulkReplies() {
     function testResponseReader_OptionIterableMultiBulkReplies() {
         $connection = new Predis_Connection(RC::getConnectionParameters());
         $connection = new Predis_Connection(RC::getConnectionParameters());
-        $responseReader = $connection->getResponseReader();
 
 
-        $responseReader->setHandler(
-            Predis_Protocol::PREFIX_MULTI_BULK, 
-            new Predis_ResponseMultiBulkHandler()
-        );
-        $this->assertType('array', $connection->rawCommand("KEYS *\r\n"));
+        $connection->getResponseReader()->setOption('iterable_multibulk', false);
+        $this->assertInternalType('array', $connection->rawCommand("KEYS *\r\n"));
 
 
-        $responseReader->setHandler(
-            Predis_Protocol::PREFIX_MULTI_BULK, 
-            new Predis_ResponseMultiBulkStreamHandler()
-        );
-        $this->assertType('Iterator', $connection->rawCommand("KEYS *\r\n"));
+        $connection->getResponseReader()->setOption('iterable_multibulk', true);
+        $this->assertInstanceOf('Iterator', $connection->rawCommand("KEYS *\r\n"));
     }
     }
 
 
     function testResponseReader_OptionExceptionOnError() {
     function testResponseReader_OptionExceptionOnError() {
@@ -378,18 +366,12 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $connection->rawCommand("*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n");
         $connection->rawCommand("*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n");
         $rawCmdUnexpected = "*3\r\n$5\r\nLPUSH\r\n$3\r\nkey\r\n$5\r\nvalue\r\n";
         $rawCmdUnexpected = "*3\r\n$5\r\nLPUSH\r\n$3\r\nkey\r\n$5\r\nvalue\r\n";
 
 
-        $responseReader->setHandler(
-            Predis_Protocol::PREFIX_ERROR,  
-            new Predis_ResponseErrorSilentHandler()
-        );
+        $responseReader->setOption('throw_on_error', false);
         $errorReply = $connection->rawCommand($rawCmdUnexpected);
         $errorReply = $connection->rawCommand($rawCmdUnexpected);
-        $this->assertType('Predis_ResponseError', $errorReply);
+        $this->assertInstanceOf('Predis_ResponseError', $errorReply);
         $this->assertEquals(RC::EXCEPTION_WRONG_TYPE, $errorReply->message);
         $this->assertEquals(RC::EXCEPTION_WRONG_TYPE, $errorReply->message);
 
 
-        $responseReader->setHandler(
-            Predis_Protocol::PREFIX_ERROR, 
-            new Predis_ResponseErrorHandler()
-        );
+        $responseReader->setOption('throw_on_error', true);
         $thrownException = null;
         $thrownException = null;
         try {
         try {
             $connection->rawCommand($rawCmdUnexpected);
             $connection->rawCommand($rawCmdUnexpected);
@@ -397,7 +379,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         catch (Predis_ServerException $exception) {
         catch (Predis_ServerException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $this->assertType('Predis_ServerException', $thrownException);
+        $this->assertInstanceOf('Predis_ServerException', $thrownException);
         $this->assertEquals(RC::EXCEPTION_WRONG_TYPE, $thrownException->getMessage());
         $this->assertEquals(RC::EXCEPTION_WRONG_TYPE, $thrownException->getMessage());
     }
     }
 
 
@@ -416,18 +398,18 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
 
 
         $pipe = $client->pipeline();
         $pipe = $client->pipeline();
 
 
-        $this->assertType('Predis_CommandPipeline', $pipe);
-        $this->assertType('Predis_CommandPipeline', $pipe->set('foo', 'bar'));
-        $this->assertType('Predis_CommandPipeline', $pipe->set('hoge', 'piyo'));
-        $this->assertType('Predis_CommandPipeline', $pipe->mset(array(
+        $this->assertInstanceOf('Predis_CommandPipeline', $pipe);
+        $this->assertInstanceOf('Predis_CommandPipeline', $pipe->set('foo', 'bar'));
+        $this->assertInstanceOf('Predis_CommandPipeline', $pipe->set('hoge', 'piyo'));
+        $this->assertInstanceOf('Predis_CommandPipeline', $pipe->mset(array(
             'foofoo' => 'barbar', 'hogehoge' => 'piyopiyo'
             'foofoo' => 'barbar', 'hogehoge' => 'piyopiyo'
         )));
         )));
-        $this->assertType('Predis_CommandPipeline', $pipe->mget(array(
+        $this->assertInstanceOf('Predis_CommandPipeline', $pipe->mget(array(
             'foo', 'hoge', 'foofoo', 'hogehoge'
             'foo', 'hoge', 'foofoo', 'hogehoge'
         )));
         )));
 
 
         $replies = $pipe->execute();
         $replies = $pipe->execute();
-        $this->assertType('array', $replies);
+        $this->assertInternalType('array', $replies);
         $this->assertEquals(4, count($replies));
         $this->assertEquals(4, count($replies));
         $this->assertEquals(4, count($replies[3]));
         $this->assertEquals(4, count($replies[3]));
         $this->assertEquals('barbar', $replies[3][2]);
         $this->assertEquals('barbar', $replies[3][2]);
@@ -438,7 +420,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $client->flushdb();
         $client->flushdb();
 
 
         $replies = $client->pipeline()->ping()->set('foo', 'bar')->get('foo')->execute();
         $replies = $client->pipeline()->ping()->set('foo', 'bar')->get('foo')->execute();
-        $this->assertType('array', $replies);
+        $this->assertInternalType('array', $replies);
         $this->assertEquals('bar', $replies[2]);
         $this->assertEquals('bar', $replies[2]);
     }
     }
 
 
@@ -452,7 +434,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
             \$pipe->get('foo');
             \$pipe->get('foo');
         "));
         "));
 
 
-        $this->assertType('array', $replies);
+        $this->assertInternalType('array', $replies);
         $this->assertEquals('bar', $replies[2]);
         $this->assertEquals('bar', $replies[2]);
     }
     }
 
 
@@ -472,7 +454,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         catch (Predis_ClientException $exception) {
         catch (Predis_ClientException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $this->assertType('Predis_ClientException', $thrownException);
+        $this->assertInstanceOf('Predis_ClientException', $thrownException);
         $this->assertEquals($expectedMessage, $thrownException->getMessage());
         $this->assertEquals($expectedMessage, $thrownException->getMessage());
 
 
         $this->assertFalse($client->exists('foo'));
         $this->assertFalse($client->exists('foo'));
@@ -481,7 +463,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
     function testCommandPipeline_ServerExceptionInCallableBlock() {
     function testCommandPipeline_ServerExceptionInCallableBlock() {
         $client = RC::getConnection();
         $client = RC::getConnection();
         $client->flushdb();
         $client->flushdb();
-        $client->getResponseReader()->setHandler('-', new Predis_ResponseErrorSilentHandler());
+        $client->getResponseReader()->setOption('throw_on_error', false);
 
 
         $replies = $client->pipeline(p_anon("\$pipe", "
         $replies = $client->pipeline(p_anon("\$pipe", "
             \$pipe->set('foo', 'bar');
             \$pipe->set('foo', 'bar');
@@ -489,8 +471,8 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
             \$pipe->set('hoge', 'piyo');
             \$pipe->set('hoge', 'piyo');
         "));
         "));
 
 
-        $this->assertType('array', $replies);
-        $this->assertType('Predis_ResponseError', $replies[1]);
+        $this->assertInternalType('array', $replies);
+        $this->assertInstanceOf('Predis_ResponseError', $replies[1]);
         $this->assertTrue($client->exists('foo'));
         $this->assertTrue($client->exists('foo'));
         $this->assertTrue($client->exists('hoge'));
         $this->assertTrue($client->exists('hoge'));
     }
     }
@@ -505,7 +487,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $pipe->ping()->mget(array('foo', 'hoge'));
         $pipe->ping()->mget(array('foo', 'hoge'));
         $replies = $pipe->execute();
         $replies = $pipe->execute();
 
 
-        $this->assertType('array', $replies);
+        $this->assertInternalType('array', $replies);
         $this->assertEquals(4, count($replies));
         $this->assertEquals(4, count($replies));
         $this->assertEquals('bar', $replies[3][0]);
         $this->assertEquals('bar', $replies[3][0]);
         $this->assertEquals('piyo', $replies[3][1]);
         $this->assertEquals('piyo', $replies[3][1]);
@@ -520,18 +502,18 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
 
 
         $multi = $client->multiExec();
         $multi = $client->multiExec();
 
 
-        $this->assertType('Predis_MultiExecBlock', $multi);
-        $this->assertType('Predis_MultiExecBlock', $multi->set('foo', 'bar'));
-        $this->assertType('Predis_MultiExecBlock', $multi->set('hoge', 'piyo'));
-        $this->assertType('Predis_MultiExecBlock', $multi->mset(array(
+        $this->assertInstanceOf('Predis_MultiExecBlock', $multi);
+        $this->assertInstanceOf('Predis_MultiExecBlock', $multi->set('foo', 'bar'));
+        $this->assertInstanceOf('Predis_MultiExecBlock', $multi->set('hoge', 'piyo'));
+        $this->assertInstanceOf('Predis_MultiExecBlock', $multi->mset(array(
             'foofoo' => 'barbar', 'hogehoge' => 'piyopiyo'
             'foofoo' => 'barbar', 'hogehoge' => 'piyopiyo'
         )));
         )));
-        $this->assertType('Predis_MultiExecBlock', $multi->mget(array(
+        $this->assertInstanceOf('Predis_MultiExecBlock', $multi->mget(array(
             'foo', 'hoge', 'foofoo', 'hogehoge'
             'foo', 'hoge', 'foofoo', 'hogehoge'
         )));
         )));
 
 
         $replies = $multi->execute();
         $replies = $multi->execute();
-        $this->assertType('array', $replies);
+        $this->assertInternalType('array', $replies);
         $this->assertEquals(4, count($replies));
         $this->assertEquals(4, count($replies));
         $this->assertEquals(4, count($replies[3]));
         $this->assertEquals(4, count($replies[3]));
         $this->assertEquals('barbar', $replies[3][2]);
         $this->assertEquals('barbar', $replies[3][2]);
@@ -542,7 +524,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $client->flushdb();
         $client->flushdb();
 
 
         $replies = $client->multiExec()->ping()->set('foo', 'bar')->get('foo')->execute();
         $replies = $client->multiExec()->ping()->set('foo', 'bar')->get('foo')->execute();
-        $this->assertType('array', $replies);
+        $this->assertInternalType('array', $replies);
         $this->assertEquals('bar', $replies[2]);
         $this->assertEquals('bar', $replies[2]);
     }
     }
 
 
@@ -556,7 +538,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
             \$multi->get('foo');
             \$multi->get('foo');
         "));
         "));
 
 
-        $this->assertType('array', $replies);
+        $this->assertInternalType('array', $replies);
         $this->assertEquals('bar', $replies[2]);
         $this->assertEquals('bar', $replies[2]);
     }
     }
 
 
@@ -602,7 +584,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         catch (Predis_ClientException $exception) {
         catch (Predis_ClientException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $this->assertType('Predis_ClientException', $thrownException);
+        $this->assertInstanceOf('Predis_ClientException', $thrownException);
         $this->assertEquals($expectedMessage, $thrownException->getMessage());
         $this->assertEquals($expectedMessage, $thrownException->getMessage());
 
 
         $this->assertFalse($client->exists('foo'));
         $this->assertFalse($client->exists('foo'));
@@ -611,7 +593,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
     function testMultiExecBlock_ServerExceptionInCallableBlock() {
     function testMultiExecBlock_ServerExceptionInCallableBlock() {
         $client = RC::getConnection();
         $client = RC::getConnection();
         $client->flushdb();
         $client->flushdb();
-        $client->getResponseReader()->setHandler('-', new Predis_ResponseErrorSilentHandler());
+        $client->getResponseReader()->setOption('throw_on_error', false);
 
 
         $multi = $client->multiExec();
         $multi = $client->multiExec();
         $multi->set('foo', 'bar');
         $multi->set('foo', 'bar');
@@ -619,8 +601,8 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         $multi->set('hoge', 'piyo');
         $multi->set('hoge', 'piyo');
         $replies = $multi->execute();
         $replies = $multi->execute();
 
 
-        $this->assertType('array', $replies);
-        $this->assertType('Predis_ResponseError', $replies[1]);
+        $this->assertInternalType('array', $replies);
+        $this->assertInstanceOf('Predis_ResponseError', $replies[1]);
         $this->assertTrue($client->exists('foo'));
         $this->assertTrue($client->exists('foo'));
         $this->assertTrue($client->exists('hoge'));
         $this->assertTrue($client->exists('hoge'));
     }
     }
@@ -664,7 +646,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         catch (PredisException $exception) {
         catch (PredisException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $this->assertType('Predis_AbortedMultiExec', $thrownException);
+        $this->assertInstanceOf('Predis_AbortedMultiExec', $thrownException);
         $this->assertEquals('The current transaction has been aborted by the server', $thrownException->getMessage());
         $this->assertEquals('The current transaction has been aborted by the server', $thrownException->getMessage());
 
 
         $this->assertEquals('client2', $client1->get('sentinel'));
         $this->assertEquals('client2', $client1->get('sentinel'));
@@ -683,7 +665,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
             \$tx->set('foobar', \$foo);
             \$tx->set('foobar', \$foo);
             \$tx->mget('foo', 'foobar');
             \$tx->mget('foo', 'foobar');
         "));
         "));
-        $this->assertType('array', $replies);
+        $this->assertInternalType('array', $replies);
         $this->assertEquals(array(true, array('bar', 'bar')), $replies);
         $this->assertEquals(array(true, array('bar', 'bar')), $replies);
 
 
         $tx = $client->multiExec($options);
         $tx = $client->multiExec($options);
@@ -693,7 +675,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
                       ->set('foobar', $foo)
                       ->set('foobar', $foo)
                       ->mget('foo', 'foobar')
                       ->mget('foo', 'foobar')
                       ->execute();
                       ->execute();
-        $this->assertType('array', $replies);
+        $this->assertInternalType('array', $replies);
         $this->assertEquals(array(true, array('bar', 'bar')), $replies);
         $this->assertEquals(array(true, array('bar', 'bar')), $replies);
     }
     }
 
 
@@ -716,7 +698,7 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         catch (Predis_AbortedMultiExec $exception) {
         catch (Predis_AbortedMultiExec $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $this->assertType('Predis_AbortedMultiExec', $thrownException);
+        $this->assertInstanceOf('Predis_AbortedMultiExec', $thrownException);
         $this->assertEquals('The current transaction has been aborted by the server', $thrownException->getMessage());
         $this->assertEquals('The current transaction has been aborted by the server', $thrownException->getMessage());
         $this->assertEquals('client2', $client1->get('sentinel'));
         $this->assertEquals('client2', $client1->get('sentinel'));
         $this->assertEquals($retry + 1, $client1->get('attempts'));
         $this->assertEquals($retry + 1, $client1->get('attempts'));
@@ -741,10 +723,55 @@ class PredisClientFeaturesTestSuite extends PHPUnit_Framework_TestCase {
         catch (Predis_AbortedMultiExec $exception) {
         catch (Predis_AbortedMultiExec $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $this->assertType('Predis_AbortedMultiExec', $thrownException);
+        $this->assertInstanceOf('Predis_AbortedMultiExec', $thrownException);
         $this->assertEquals('The current transaction has been aborted by the server', $thrownException->getMessage());
         $this->assertEquals('The current transaction has been aborted by the server', $thrownException->getMessage());
         $this->assertEquals('client2', $client1->get('sentinel'));
         $this->assertEquals('client2', $client1->get('sentinel'));
         $this->assertEquals($retry + 1, $client1->get('attempts'));
         $this->assertEquals($retry + 1, $client1->get('attempts'));
     }
     }
+
+    /**
+     * @expectedException InvalidArgumentException
+     */
+    function testMultiExecBlock_RetryNotAvailableWithoutBlock() {
+        $options = array('watch' => 'foo', 'retry' => 1);
+        $tx = RC::getConnection()->multiExec($options);
+        $tx->multi()->get('foo')->exec();
+    }
+
+    function testMultiExecBlock_CheckAndSet_Discard() {
+        $client = RC::getConnection();
+        $client->flushdb();
+
+        $client->set('foo', 'bar');
+        $options = array('watch' => 'foo', 'cas' => true);
+        $replies = $client->multiExec($options, p_anon("\$tx", "
+            \$tx->watch('foobar');
+            \$foo = \$tx->get('foo');
+            \$tx->multi();
+            \$tx->set('foobar', \$foo);
+            \$tx->discard();
+            \$tx->mget('foo', 'foobar');
+        "));
+        $this->assertInternalType('array', $replies);
+        $this->assertEquals(array(array('bar', null)), $replies);
+
+        $hijack = true;
+        $client->set('foo', 'bar');
+        $options = array('watch' => 'foo', 'cas' => true, 'retry' => 1);
+        $replies = $client->multiExec($options, p_anon("\$tx", "
+            \$client2 = RC::getConnection(true);
+            \$hijack = \$client2->get('foo') !== 'hijacked';
+            \$foo = \$tx->get('foo');
+            \$tx->multi();
+            \$tx->set('foobar', \$foo);
+            \$tx->discard();
+            if (\$hijack) {
+                \$client2->set('foo', 'hijacked!');
+            }
+            \$tx->mget('foo', 'foobar');
+        "));
+        $this->assertInternalType('array', $replies);
+        $this->assertEquals(array(array('hijacked!', null)), $replies);
+    }
 }
 }
 ?>
 ?>

+ 22 - 10
test/PredisShared.php

@@ -1,12 +1,23 @@
 <?php
 <?php
-require_once '../lib/Predis.php';
+// -------------------------------------------------------------------------- //
+
+define('I_AM_AWARE_OF_THE_DESTRUCTIVE_POWER_OF_THIS_TEST_SUITE', false);
+
+// -------------------------------------------------------------------------- //
+
+Predis_RedisServerProfile::registerProfile('Predis_RedisServer_v1_2', '1.2');
+Predis_RedisServerProfile::registerProfile('Predis_RedisServer_v2_0', '2.0');
+Predis_RedisServerProfile::registerProfile('Predis_RedisServer_v2_2', '2.2');
 
 
 if (I_AM_AWARE_OF_THE_DESTRUCTIVE_POWER_OF_THIS_TEST_SUITE !== true) {
 if (I_AM_AWARE_OF_THE_DESTRUCTIVE_POWER_OF_THIS_TEST_SUITE !== true) {
-    exit('Please set the I_AM_AWARE_OF_THE_DESTRUCTIVE_POWER_OF_THIS_TEST_SUITE constant to TRUE if you want to proceed.');
+    exit(
+        "Please set the I_AM_AWARE_OF_THE_DESTRUCTIVE_POWER_OF_THIS_TEST_SUITE " .
+        "constant to TRUE in PredisShared.php if you want to proceed.\n"
+    );
 }
 }
 
 
 if (!function_exists('array_union')) {
 if (!function_exists('array_union')) {
-    function array_union(Array $a, Array $b) { 
+    function array_union(Array $a, Array $b) {
         return array_merge($a, array_diff($b, $a));
         return array_merge($a, array_diff($b, $a));
     }
     }
 }
 }
@@ -35,16 +46,16 @@ class RC {
 
 
     private static $_connection;
     private static $_connection;
 
 
-    public static function getConnectionArguments() { 
+    public static function getConnectionArguments() {
         return array('host' => RC::SERVER_HOST, 'port' => RC::SERVER_PORT);
         return array('host' => RC::SERVER_HOST, 'port' => RC::SERVER_PORT);
     }
     }
 
 
-    public static function getConnectionParameters() { 
+    public static function getConnectionParameters() {
         return new Predis_ConnectionParameters(array('host' => RC::SERVER_HOST, 'port' => RC::SERVER_PORT));
         return new Predis_ConnectionParameters(array('host' => RC::SERVER_HOST, 'port' => RC::SERVER_PORT));
     }
     }
 
 
     private static function createConnection() {
     private static function createConnection() {
-        $serverProfile = Predis_RedisServerProfile::get('dev');
+        $serverProfile = Predis_RedisServerProfile::get('2.2');
         $connection = new Predis_Client(RC::getConnectionArguments(), $serverProfile);
         $connection = new Predis_Client(RC::getConnectionArguments(), $serverProfile);
         $connection->connect();
         $connection->connect();
         $connection->select(RC::DEFAULT_DATABASE);
         $connection->select(RC::DEFAULT_DATABASE);
@@ -73,8 +84,9 @@ class RC {
         //       in a separate process to properly test BLPOP/BRPOP
         //       in a separate process to properly test BLPOP/BRPOP
         $redisUri = sprintf('redis://%s:%d/?database=%d', RC::SERVER_HOST, RC::SERVER_PORT, RC::DEFAULT_DATABASE);
         $redisUri = sprintf('redis://%s:%d/?database=%d', RC::SERVER_HOST, RC::SERVER_PORT, RC::DEFAULT_DATABASE);
         $handle = popen('php', 'w');
         $handle = popen('php', 'w');
+        $dir = __DIR__;
         fwrite($handle, "<?php
         fwrite($handle, "<?php
-        require '../lib/Predis.php';
+        require '{$dir}/../lib/Predis.php';
         \$redis = Predis_Client::create('$redisUri');
         \$redis = Predis_Client::create('$redisUri');
         \$redis->rpush('{$op}1', 'a');
         \$redis->rpush('{$op}1', 'a');
         \$redis->rpush('{$op}2', 'b');
         \$redis->rpush('{$op}2', 'b');
@@ -125,7 +137,7 @@ class RC {
         catch (Predis_ServerException $exception) {
         catch (Predis_ServerException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $testcaseInstance->assertType('Predis_ServerException', $thrownException);
+        $testcaseInstance->assertInstanceOf('Predis_ServerException', $thrownException);
         if (isset($expectedMessage)) {
         if (isset($expectedMessage)) {
             $testcaseInstance->assertEquals($expectedMessage, $thrownException->getMessage());
             $testcaseInstance->assertEquals($expectedMessage, $thrownException->getMessage());
         }
         }
@@ -139,7 +151,7 @@ class RC {
         catch (Predis_ClientException $exception) {
         catch (Predis_ClientException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $testcaseInstance->assertType('Predis_ClientException', $thrownException);
+        $testcaseInstance->assertInstanceOf('Predis_ClientException', $thrownException);
         if (isset($expectedMessage)) {
         if (isset($expectedMessage)) {
             $testcaseInstance->assertEquals($expectedMessage, $thrownException->getMessage());
             $testcaseInstance->assertEquals($expectedMessage, $thrownException->getMessage());
         }
         }
@@ -153,7 +165,7 @@ class RC {
         catch (Predis_CommunicationException $exception) {
         catch (Predis_CommunicationException $exception) {
             $thrownException = $exception;
             $thrownException = $exception;
         }
         }
-        $testcaseInstance->assertType('Predis_CommunicationException', $thrownException);
+        $testcaseInstance->assertInstanceOf('Predis_CommunicationException', $thrownException);
         if (isset($expectedMessage)) {
         if (isset($expectedMessage)) {
             $testcaseInstance->assertEquals($expectedMessage, $thrownException->getMessage());
             $testcaseInstance->assertEquals($expectedMessage, $thrownException->getMessage());
         }
         }

+ 48 - 12
test/RedisCommandsTest.php

@@ -1,10 +1,6 @@
 <?php
 <?php
-define('I_AM_AWARE_OF_THE_DESTRUCTIVE_POWER_OF_THIS_TEST_SUITE', false);
 
 
-require_once 'PHPUnit/Framework.php';
-require_once 'PredisShared.php';
-
-class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
+class RedisCommandsTestSuite extends PHPUnit_Framework_TestCase {
     public $redis;
     public $redis;
 
 
     // TODO: instead of an boolean assertion against the return value 
     // TODO: instead of an boolean assertion against the return value 
@@ -51,9 +47,9 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
         //       respective Predis_Command::parseResponse methods. If you need that 
         //       respective Predis_Command::parseResponse methods. If you need that 
         //       kind of behaviour, you should use an instance of Predis_MultiExecBlock.
         //       kind of behaviour, you should use an instance of Predis_MultiExecBlock.
         $this->assertTrue($this->redis->multi());
         $this->assertTrue($this->redis->multi());
-        $this->assertType('Predis_ResponseQueued', $this->redis->ping());
-        $this->assertType('Predis_ResponseQueued', $this->redis->echo('hello'));
-        $this->assertType('Predis_ResponseQueued', $this->redis->echo('redis'));
+        $this->assertInstanceOf('Predis_ResponseQueued', $this->redis->ping());
+        $this->assertInstanceOf('Predis_ResponseQueued', $this->redis->echo('hello'));
+        $this->assertInstanceOf('Predis_ResponseQueued', $this->redis->echo('redis'));
         $this->assertEquals(array('PONG', 'hello', 'redis'), $this->redis->exec());
         $this->assertEquals(array('PONG', 'hello', 'redis'), $this->redis->exec());
 
 
         $this->assertTrue($this->redis->multi());
         $this->assertTrue($this->redis->multi());
@@ -67,8 +63,8 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
 
 
     function testDiscard() {
     function testDiscard() {
         $this->assertTrue($this->redis->multi());
         $this->assertTrue($this->redis->multi());
-        $this->assertType('Predis_ResponseQueued', $this->redis->set('foo', 'bar'));
-        $this->assertType('Predis_ResponseQueued', $this->redis->set('hoge', 'piyo'));
+        $this->assertInstanceOf('Predis_ResponseQueued', $this->redis->set('foo', 'bar'));
+        $this->assertInstanceOf('Predis_ResponseQueued', $this->redis->set('hoge', 'piyo'));
         $this->assertEquals(true, $this->redis->discard());
         $this->assertEquals(true, $this->redis->discard());
 
 
         // should throw an exception when trying to EXEC after a DISCARD
         // should throw an exception when trying to EXEC after a DISCARD
@@ -255,7 +251,7 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
         $this->assertEquals('bar', $this->redis->substr('var', 3, 5));
         $this->assertEquals('bar', $this->redis->substr('var', 3, 5));
         $this->assertEquals('bar', $this->redis->substr('var', -3, -1));
         $this->assertEquals('bar', $this->redis->substr('var', -3, -1));
 
 
-        $this->assertNull($this->redis->substr('var', 5, 0));
+        $this->assertEquals($this->redis->substr('var', 5, 0), '');
 
 
         $this->redis->set('numeric', 123456789);
         $this->redis->set('numeric', 123456789);
         $this->assertEquals(12345, $this->redis->substr('numeric', 0, 4));
         $this->assertEquals(12345, $this->redis->substr('numeric', 0, 4));
@@ -1004,6 +1000,9 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
         $this->redis->set('foo', 'bar');
         $this->redis->set('foo', 'bar');
         $this->assertEquals(count($setA), $this->redis->sinterstore('foo', 'setA'));
         $this->assertEquals(count($setA), $this->redis->sinterstore('foo', 'setA'));
 
 
+        // accepts an array for the list of source keys
+        $this->assertEquals(4, $this->redis->sinterstore('setC', array('setA', 'setB')));
+
         // wrong type
         // wrong type
         $this->redis->set('foo', 'bar');
         $this->redis->set('foo', 'bar');
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
@@ -1067,6 +1066,9 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
         $this->redis->set('foo', 'bar');
         $this->redis->set('foo', 'bar');
         $this->assertEquals(count($setA), $this->redis->sunionstore('foo', 'setA'));
         $this->assertEquals(count($setA), $this->redis->sunionstore('foo', 'setA'));
 
 
+        // accepts an array for the list of source keys
+        $this->assertEquals(9, $this->redis->sunionstore('setC', array('setA', 'setB')));
+
         // wrong type
         // wrong type
         $this->redis->set('foo', 'bar');
         $this->redis->set('foo', 'bar');
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
@@ -1495,6 +1497,23 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
             $this->redis->zrange('zsetc', 0, -1, 'withscores')
             $this->redis->zrange('zsetc', 0, -1, 'withscores')
         );
         );
 
 
+        // using an array to pass the list of source keys
+        $sourceKeys = array('zseta', 'zsetb');
+
+        $this->assertEquals(4, $this->redis->zunionstore('zsetc', $sourceKeys));
+        $this->assertEquals(
+            array(array('a', 1), array('b', 3), array('d', 3), array('c', 5)),
+            $this->redis->zrange('zsetc', 0, -1, 'withscores')
+        );
+
+        // using an array to pass the list of source keys + options array
+        $options = array('weights' => array(2, 3));
+        $this->assertEquals(4, $this->redis->zunionstore('zsetc', $sourceKeys, $options));
+        $this->assertEquals(
+            array(array('a', 2), array('b', 7), array('d', 9), array('c', 12)),
+            $this->redis->zrange('zsetc', 0, -1, 'withscores')
+        );
+
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
             \$test->redis->set('zsetFake', 'fake');
             \$test->redis->set('zsetFake', 'fake');
             \$test->redis->zunionstore('zsetc', 2, 'zseta', 'zsetFake');
             \$test->redis->zunionstore('zsetc', 2, 'zseta', 'zsetFake');
@@ -1540,6 +1559,23 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
             $this->redis->zrange('zsetc', 0, -1, 'withscores')
             $this->redis->zrange('zsetc', 0, -1, 'withscores')
         );
         );
 
 
+        // using an array to pass the list of source keys
+        $sourceKeys = array('zseta', 'zsetb');
+
+        $this->assertEquals(2, $this->redis->zinterstore('zsetc', $sourceKeys));
+        $this->assertEquals(
+            array(array('b', 3), array('c', 5)),
+            $this->redis->zrange('zsetc', 0, -1, 'withscores')
+        );
+
+        // using an array to pass the list of source keys + options array
+        $options = array('weights' => array(2, 3));
+        $this->assertEquals(2, $this->redis->zinterstore('zsetc', $sourceKeys, $options));
+        $this->assertEquals(
+            array(array('b', 7), array('c', 12)),
+            $this->redis->zrange('zsetc', 0, -1, 'withscores')
+        );
+
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
         RC::testForServerException($this, RC::EXCEPTION_WRONG_TYPE, p_anon("\$test", "
             \$test->redis->set('zsetFake', 'fake');
             \$test->redis->set('zsetFake', 'fake');
             \$test->redis->zinterstore('zsetc', 2, 'zseta', 'zsetFake');
             \$test->redis->zinterstore('zsetc', 2, 'zseta', 'zsetFake');
@@ -1989,7 +2025,7 @@ class RedisCommandTestSuite extends PHPUnit_Framework_TestCase {
     function testInfo() {
     function testInfo() {
         $serverInfo = $this->redis->info();
         $serverInfo = $this->redis->info();
 
 
-        $this->assertType('array', $serverInfo);
+        $this->assertInternalType('array', $serverInfo);
         $this->assertNotNull($serverInfo['redis_version']);
         $this->assertNotNull($serverInfo['redis_version']);
         $this->assertGreaterThan(0, $serverInfo['uptime_in_seconds']);
         $this->assertGreaterThan(0, $serverInfo['uptime_in_seconds']);
         $this->assertGreaterThan(0, $serverInfo['total_connections_received']);
         $this->assertGreaterThan(0, $serverInfo['total_connections_received']);

+ 9 - 0
test/bootstrap.php

@@ -0,0 +1,9 @@
+<?php
+
+if (!defined(__DIR__)) {
+    define('__DIR__', dirname(__FILE__));
+}
+
+require_once(__DIR__ . '/../lib/Predis.php');
+require_once(__DIR__ . '/../lib/Predis_Compatibility.php');
+require_once(__DIR__ . '/../test/PredisShared.php');

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.