Compare commits

...

17 Commits

Author SHA1 Message Date
Daniele Alessandri 4bc6f588fc Bump version in files for release. 2012-06-01 11:17:31 +02:00
Daniele Alessandri 2522a249f3 Minor CS fixes. 2012-06-01 11:16:34 +02:00
Daniele Alessandri b4e1cfcee7 Update CHANGELOG. 2012-06-01 11:15:47 +02:00
Daniele Alessandri 105bf8a2ee Merge remote-tracking branch 'inadarei/v0.7' into v0.7 2012-05-27 20:56:51 +02:00
Irakli Nadareishvili 4f16e232a8 Updated file_exists() to is_file() and changed require_once() to require() per Predis' author's suggestions 2012-05-26 08:14:29 -03:00
Irakli Nadareishvili 703c3ceb90 Making autoloader act nicer to autoloaders that may be running in parallel 2012-05-22 13:39:44 -03:00
Daniele Alessandri ca2e4aa4a1 Update CHANGELOG.
[ci skip]
2012-05-17 17:33:21 +02:00
Daniele Alessandri 477056b862 For some reason, class and tests for BITCOUNT were missing... 2012-05-17 16:52:21 +02:00
Daniele Alessandri b94e002e90 TIME can be considered a read-only command in MASTER / SLAVE. 2012-05-17 16:37:26 +02:00
Daniele Alessandri 3aff21f8cc New commands: BITOP, BITCOUNT (Redis v2.6-dev). 2012-05-17 16:34:50 +02:00
Daniele Alessandri 1e142a63e6 Fix comment in package.ini.
[ci skip]
2012-05-17 09:52:46 +02:00
Daniele Alessandri b67dab9ab1 Fix Predis\Commands\ServerEvalSHA::getScriptHash().
"Predis\Commands\ServerEvalSHA::getScriptHash()" was calculating the hash
while it just needs to return the first argument of the command.
2012-04-28 01:25:17 +02:00
Daniele Alessandri 6ba1890da9 Do not assume that the position of a MultiBulkResponse iterator is 0. 2012-04-27 16:10:58 +02:00
Daniele Alessandri ca8ba35fb5 Switch to master inside executor when pipelining in replication mode.
The actual code to switch to master has been implemented only in the
standard and the fire-and-forget executor classes since it does not
make sense to have it in special executors used exclusively when in
client-side clustering mode.
2012-04-25 11:53:08 +02:00
Daniele Alessandri 5af2b628f1 Scripting abstraction can use negatives to calculate number of keys.
With a negative number Predis will count from the end of the arguments list
to calculate the actual number of keys that will be interpreted as elements
for `KEYS` by the underlying `EVAL` command.
2012-04-25 11:20:57 +02:00
Daniele Alessandri f4c58b926b Fix example for custom distribution strategy.
See ISSUE #63 for details.
2012-04-13 11:51:02 +02:00
Daniele Alessandri cb390cf292 Back to development for the next patch release. 2012-04-13 11:49:30 +02:00
27 changed files with 619 additions and 43 deletions
+22
View File
@@ -1,3 +1,25 @@
v0.7.3 (2012-06-01)
===============================================================================
- New commands available in the Redis v2.6 profile (dev): `BITOP`, `BITCOUNT`.
- When the number of keys `Predis\Commands\ScriptedCommand` is negative, Predis
will count from the end of the arguments list to calculate the actual number
of keys that will be interpreted as elements for `KEYS` by the underlying
`EVAL` command.
- __FIX__: `examples\CustomDistributionStrategy.php` had a mistyped constructor
call and produced a bad distribution due to an error as pointed in ISSUE #63.
This bug is limited to the above mentioned example and does not affect the
classes implemented in the `Predis\Distribution` namespace.
- __FIX__: `Predis\Commands\ServerEvalSHA::getScriptHash()` was calculating the
hash while it just needs to return the first argument of the command.
- __FIX__: `Predis\Autoloader` has been modified to allow cascading autoloaders
for the `Predis` namespace.
v0.7.2 (2012-04-01)
===============================================================================
+1 -1
View File
@@ -1 +1 @@
0.7.2
0.7.3
+2 -2
View File
@@ -23,7 +23,7 @@ class NaiveDistributionStrategy implements IDistributionStrategy
private $nodes;
private $nodesCount;
public function __constructor()
public function __construct()
{
$this->nodes = array();
$this->nodesCount = 0;
@@ -51,7 +51,7 @@ class NaiveDistributionStrategy implements IDistributionStrategy
throw new RuntimeException('No connections');
}
return $this->nodes[$count > 1 ? abs(crc32($key) % $count) : 0];
return $this->nodes[$count > 1 ? abs($key % $count) : 0];
}
public function generateKey($value)
+27 -10
View File
@@ -20,30 +20,47 @@ require 'SharedConfigurations.php';
use Predis\Commands\ScriptedCommand;
class IncrementExistingKey extends ScriptedCommand
class IncrementExistingKeysBy extends ScriptedCommand
{
public function getKeysCount()
{
return 1;
// Tell Predis to use all the arguments but the last one as arguments
// for KEYS. The last one will be used to populate ARGV.
return -1;
}
public function getScript()
{
return
<<<LUA
local cmd = redis.call
if cmd('exists', KEYS[1]) == 1 then
return cmd('incr', KEYS[1])
end
local cmd, insert = redis.call, table.insert
local increment, results = ARGV[1], { }
for idx, key in ipairs(KEYS) do
if cmd('exists', key) == 1 then
insert(results, idx, cmd('incrby', key, increment))
else
insert(results, idx, false)
end
end
return results
LUA;
}
}
$client = new Predis\Client($single_server, '2.6');
$client->getProfile()->defineCommand('increx', 'IncrementExistingKey');
$client->getProfile()->defineCommand('increxby', 'IncrementExistingKeysBy');
$client->set('foo', 10);
$client->mset('foo', 10, 'foobar', 100);
var_dump($client->increx('foo')); // int(11)
var_dump($client->increx('bar')); // NULL
var_export($client->increxby('foo', 'foofoo', 'foobar', 50));
/*
array (
0 => 60,
1 => NULL,
2 => 150,
)
*/
+4 -1
View File
@@ -52,7 +52,10 @@ class Autoloader
{
if (0 === strpos($className, $this->prefix)) {
$parts = explode('\\', substr($className, $this->prefixLength));
require($this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php');
$filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php';
if (is_file($filepath)) {
require($filepath);
}
}
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ use Predis\Transaction\MultiExecContext;
*/
class Client
{
const VERSION = '0.7.2';
const VERSION = '0.7.3';
private $options;
private $profile;
+18
View File
@@ -67,6 +67,24 @@ class PrefixHelpers
$command->setRawArguments($arguments);
}
/**
* Applies the specified prefix to all the arguments but the first one.
*
* @param ICommand $command Command instance.
* @param string $prefix Prefix string.
*/
public static function skipFirst(ICommand $command, $prefix)
{
$arguments = $command->getArguments();
$length = count($arguments);
for ($i = 1; $i < $length; $i++) {
$arguments[$i] = "$prefix{$arguments[$i]}";
}
$command->setRawArguments($arguments);
}
/**
* Applies the specified prefix to all the arguments but the last one.
*
+7 -2
View File
@@ -60,8 +60,13 @@ abstract class ScriptedCommand extends ServerEval
*/
protected function filterArguments(Array $arguments)
{
$header = array($this->getScript(), ($keys = $this->getKeysCount()) !== false ? $keys : count($arguments));
if (false !== $numkeys = $this->getKeysCount()) {
$numkeys = $numkeys >= 0 ? $numkeys : count($arguments) + $numkeys;
}
else {
$numkeys = count($arguments);
}
return array_merge($header, $arguments);
return array_merge(array($this->getScript(), $numkeys), $arguments);
}
}
+10
View File
@@ -24,4 +24,14 @@ class ServerEvalSHA extends ServerEval
{
return 'EVALSHA';
}
/**
* Returns the SHA1 hash of the body of the script.
*
* @return string SHA1 hash.
*/
public function getScriptHash()
{
return $this->getArgument(0);
}
}
+27
View File
@@ -0,0 +1,27 @@
<?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\Commands;
/**
* @link http://redis.io/commands/bitcount
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class StringBitCount extends PrefixableCommand
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'BITCOUNT';
}
}
+59
View File
@@ -0,0 +1,59 @@
<?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\Commands;
/**
* @link http://redis.io/commands/bitop
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class StringBitOp extends Command implements IPrefixable
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'BITOP';
}
/**
* {@inheritdoc}
*/
protected function filterArguments(Array $arguments)
{
if (count($arguments) === 3 && is_array($arguments[2])) {
list($operation, $destination, ) = $arguments;
$arguments = $arguments[2];
array_unshift($arguments, $operation, $destination);
}
return $arguments;
}
/**
* {@inheritdoc}
*/
public function prefixKeys($prefix)
{
PrefixHelpers::skipFirst($this, $prefix);
}
/**
* {@inheritdoc}
*/
protected function canBeHashed()
{
return $this->checkSameHashForKeys(
array_slice(($args = $this->getArguments()), 1, count($args))
);
}
}
@@ -81,6 +81,16 @@ abstract class MultiBulkResponse implements \Iterator, \Countable
return $this->replySize;
}
/**
* Returns the current position of the iterator.
*
* @return int
*/
public function getPosition()
{
return $this->position;
}
/**
* {@inheritdoc}
*/
@@ -28,7 +28,7 @@ class MultiBulkResponseTuple extends MultiBulkResponse implements \OuterIterator
{
$virtualSize = count($iterator) / 2;
$this->iterator = $iterator;
$this->position = 0;
$this->position = $iterator->getPosition();
$this->current = $virtualSize > 0 ? $this->getValue() : null;
$this->replySize = $virtualSize;
}
@@ -409,6 +409,8 @@ class MasterSlaveReplication implements IConnectionReplication
'ECHO' => true,
'QUIT' => true,
'OBJECT' => true,
'BITCOUNT' => true,
'TIME' => true,
'SORT' => array($this, 'isSortReadOnly'),
);
}
+2 -1
View File
@@ -257,7 +257,8 @@ class PhpiredisConnection extends ConnectionBase
* @param IConnectionParameters $parameters Parameters used to initialize the connection.
* @return string
*/
private function connectWithTimeout(IConnectionParameters $parameters) {
private function connectWithTimeout(IConnectionParameters $parameters)
{
$host = self::getAddress($parameters);
$socket = $this->getResource();
+2 -1
View File
@@ -186,7 +186,8 @@ class StreamConnection extends ConnectionBase
/**
* {@inheritdoc}
*/
public function read() {
public function read()
{
$socket = $this->getResource();
$chunk = fgets($socket);
@@ -12,6 +12,7 @@
namespace Predis\Pipeline;
use Predis\Network\IConnection;
use Predis\Network\IConnectionReplication;
/**
* Implements a pipeline executor strategy that writes a list of commands to
@@ -21,11 +22,27 @@ use Predis\Network\IConnection;
*/
class FireAndForgetExecutor implements IPipelineExecutor
{
/**
* Allows the pipeline executor to perform operations on the
* connection before starting to execute the commands stored
* in the pipeline.
*
* @param IConnection Connection instance.
*/
protected function checkConnection(IConnection $connection)
{
if ($connection instanceof IConnectionReplication) {
$connection->switchTo('master');
}
}
/**
* {@inheritdoc}
*/
public function execute(IConnection $connection, &$commands)
{
$this->checkConnection($connection);
foreach ($commands as $command) {
$connection->writeCommand($command);
}
-8
View File
@@ -15,7 +15,6 @@ use Predis\Client;
use Predis\Helpers;
use Predis\ClientException;
use Predis\Commands\ICommand;
use Predis\Network\IConnectionReplication;
/**
* Abstraction of a pipeline context where write and read operations
@@ -121,13 +120,6 @@ class PipelineContext
if (count($this->pipeline) > 0) {
if ($send) {
$connection = $this->client->getConnection();
// TODO: it would be better to use a dedicated pipeline executor
// for classes implementing master/slave replication.
if ($connection instanceof IConnectionReplication) {
$connection->switchTo('master');
}
$replies = $this->executor->execute($connection, $this->pipeline);
$this->replies = array_merge($this->replies, $replies);
}
+17
View File
@@ -13,6 +13,7 @@ namespace Predis\Pipeline;
use Predis\ServerException;
use Predis\Network\IConnection;
use Predis\Network\IConnectionReplication;
/**
* Implements the standard pipeline executor strategy used
@@ -23,6 +24,20 @@ use Predis\Network\IConnection;
*/
class StandardExecutor implements IPipelineExecutor
{
/**
* Allows the pipeline executor to perform operations on the
* connection before starting to execute the commands stored
* in the pipeline.
*
* @param IConnection Connection instance.
*/
protected function checkConnection(IConnection $connection)
{
if ($connection instanceof IConnectionReplication) {
$connection->switchTo('master');
}
}
/**
* {@inheritdoc}
*/
@@ -31,6 +46,8 @@ class StandardExecutor implements IPipelineExecutor
$sizeofPipe = count($commands);
$values = array();
$this->checkConnection($connection);
foreach ($commands as $command) {
$connection->writeCommand($command);
}
+2
View File
@@ -217,6 +217,8 @@ class ServerVersion26 extends ServerProfile
/* commands operating on string values */
'psetex' => 'Predis\Commands\StringPreciseSetExpire',
'incrbyfloat' => 'Predis\Commands\StringIncrementByFloat',
'bitop' => 'Predis\Commands\StringBitOp',
'bitcount' => 'Predis\Commands\StringBitCount',
/* commands operating on hashes */
'hincrbyfloat' => 'Predis\Commands\HashIncrementByFloat',
+4 -5
View File
@@ -1,9 +1,8 @@
; This file is meant to be used with Onion http://c9s.github.com/Onion/
; In order to be able to build a PEAR package of Predis, open a new terminal
; session and follow these two easy steps:
; For instructions on how to build a PEAR package of Predis please follow
; the instructions at this URL:
;
; $ wget https://github.com/c9s/Onion/raw/master/onion.phar
; $ /usr/bin/env php onion.phar build
; https://github.com/c9s/Onion#a-quick-tutorial-for-building-pear-package
;
[package]
@@ -11,7 +10,7 @@ name = "Predis"
desc = "Flexible and feature-complete PHP client library for Redis"
homepage = "http://github.com/nrk/predis"
license = "MIT"
version = "0.7.2"
version = "0.7.3"
stability = "stable"
channel = "pear.nrk.io"
@@ -39,6 +39,25 @@ class ScriptedCommandTest extends StandardTestCase
$this->assertSame(array_merge(array(self::LUA_SCRIPT, 2), $arguments), $command->getArguments());
}
/**
* @group disconnected
*/
public function testGetArgumentsWithNegativeKeysCount()
{
$arguments = array('key1', 'key2', 'value1', 'value2');
$command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount'));
$command->expects($this->once())
->method('getScript')
->will($this->returnValue(self::LUA_SCRIPT));
$command->expects($this->once())
->method('getKeysCount')
->will($this->returnValue(-2));
$command->setArguments($arguments);
$this->assertSame(array_merge(array(self::LUA_SCRIPT, 2), $arguments), $command->getArguments());
}
/**
* @group disconnected
*/
@@ -58,6 +77,25 @@ class ScriptedCommandTest extends StandardTestCase
$this->assertSame(array('key1', 'key2'), $command->getKeys());
}
/**
* @group disconnected
*/
public function testGetKeysWithNegativeKeysCount()
{
$arguments = array('key1', 'key2', 'value1', 'value2');
$command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount'));
$command->expects($this->once())
->method('getScript')
->will($this->returnValue(self::LUA_SCRIPT));
$command->expects($this->exactly(2))
->method('getKeysCount')
->will($this->returnValue(-2));
$command->setArguments($arguments);
$this->assertSame(array('key1', 'key2'), $command->getKeys());
}
/**
* @group disconnected
*/
@@ -80,6 +118,28 @@ class ScriptedCommandTest extends StandardTestCase
$this->assertSame($expected, $command->getKeys());
}
/**
* @group disconnected
*/
public function testPrefixKeysWithNegativeKeysCount()
{
$arguments = array('foo', 'hoge', 'bar', 'piyo');
$expected = array('prefix:foo', 'prefix:hoge');
$command = $this->getMock('Predis\Commands\ScriptedCommand', array('getScript', 'getKeysCount'));
$command->expects($this->once())
->method('getScript')
->will($this->returnValue(self::LUA_SCRIPT));
$command->expects($this->exactly(2))
->method('getKeysCount')
->will($this->returnValue(-2));
$command->setArguments($arguments);
$command->prefixKeys('prefix:');
$this->assertSame($expected, $command->getKeys());
}
/**
* @group disconnected
*/
@@ -75,6 +75,15 @@ class ServerEvalSHATest extends CommandTestCase
$this->assertSame($expected, $command->getArguments());
}
/**
* @group disconnected
*/
public function testGetScriptHash()
{
$command = $this->getCommandWithArgumentsArray(array($sha1 = sha1('return true')), 0);
$this->assertSame($sha1, $command->getScriptHash());
}
/**
* @group connected
*/
@@ -0,0 +1,108 @@
<?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\Commands;
use \PHPUnit_Framework_TestCase as StandardTestCase;
/**
* @group commands
* @group realm-string
*/
class StringBitCountTest extends CommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand()
{
return 'Predis\Commands\StringBitCount';
}
/**
* {@inheritdoc}
*/
protected function getExpectedId()
{
return 'BITCOUNT';
}
/**
* @group disconnected
*/
public function testFilterArguments()
{
$arguments = array('key', 0, 10);
$expected = array('key', 0, 10);
$command = $this->getCommand();
$command->setArguments($arguments);
$this->assertSame($expected, $command->getArguments());
}
/**
* @group disconnected
*/
public function testParseResponse()
{
$raw = 10;
$expected = 10;
$command = $this->getCommand();
$this->assertSame($expected, $command->parseResponse($raw));
}
/**
* @group disconnected
*/
public function testPrefixKeys()
{
$arguments = array('key', 0, 10);
$expected = array('prefix:key', 0, 10);
$command = $this->getCommandWithArgumentsArray($arguments);
$command->prefixKeys('prefix:');
$this->assertSame($expected, $command->getArguments());
}
/**
* @group connected
*/
public function testReturnsNumberOfBitsSet()
{
$redis = $this->getClient();
$redis->setbit('key', 1, 1);
$redis->setbit('key', 10, 1);
$redis->setbit('key', 16, 1);
$redis->setbit('key', 22, 1);
$redis->setbit('key', 32, 1);
$this->assertSame(5, $redis->bitcount('key'), 'Count bits set (without range)');
$this->assertSame(3, $redis->bitcount('key', 2, 4), 'Count bits set (with range)');
}
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnWrongType()
{
$redis = $this->getClient();
$redis->lpush('key', 'list');
$redis->bitcount('key');
}
}
+193
View File
@@ -0,0 +1,193 @@
<?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\Commands;
use \PHPUnit_Framework_TestCase as StandardTestCase;
/**
* @group commands
* @group realm-string
*/
class StringBitOpTest extends CommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand()
{
return 'Predis\Commands\StringBitOp';
}
/**
* {@inheritdoc}
*/
protected function getExpectedId()
{
return 'BITOP';
}
/**
* @group disconnected
*/
public function testFilterArguments()
{
$arguments = array('AND', 'key:dst', 'key:01', 'key:02');
$expected = array('AND', 'key:dst', 'key:01', 'key:02');
$command = $this->getCommand();
$command->setArguments($arguments);
$this->assertSame($expected, $command->getArguments());
}
/**
* @group disconnected
*/
public function testFilterArgumentsKeysAsSingleArray()
{
$arguments = array('AND', 'key:dst', array('key:01', 'key:02'));
$expected = array('AND', 'key:dst', 'key:01', 'key:02');
$command = $this->getCommand();
$command->setArguments($arguments);
$this->assertSame($expected, $command->getArguments());
}
/**
* @group disconnected
*/
public function testParseResponse()
{
$raw = 10;
$expected = 10;
$command = $this->getCommand();
$this->assertSame($expected, $command->parseResponse($raw));
}
/**
* @group disconnected
*/
public function testPrefixKeys()
{
$arguments = array('AND', 'key:dst', 'key:01', 'key:02');
$expected = array('AND', 'prefix:key:dst', 'prefix:key:01', 'prefix:key:02');
$command = $this->getCommandWithArgumentsArray($arguments);
$command->prefixKeys('prefix:');
$this->assertSame($expected, $command->getArguments());
}
/**
* @group connected
*/
public function testCanPerformBitwiseAND()
{
$redis = $this->getClient();
$redis->set('key:src:1', "h\x80");
$redis->set('key:src:2', "R");
$this->assertSame(2, $redis->bitop('AND', 'key:dst', 'key:src:1', 'key:src:2'));
$this->assertSame("@\x00", $redis->get('key:dst'));
}
/**
* @group connected
*/
public function testCanPerformBitwiseOR()
{
$redis = $this->getClient();
$redis->set('key:src:1', "h\x80");
$redis->set('key:src:2', "R");
$this->assertSame(2, $redis->bitop('OR', 'key:dst', 'key:src:1', 'key:src:2'));
$this->assertSame("z\x80", $redis->get('key:dst'));
}
/**
* @group connected
*/
public function testCanPerformBitwiseXOR()
{
$redis = $this->getClient();
$redis->set('key:src:1', "h\x80");
$redis->set('key:src:2', "R");
$this->assertSame(2, $redis->bitop('XOR', 'key:dst', 'key:src:1', 'key:src:2'));
$this->assertSame(":\x80", $redis->get('key:dst'));
}
/**
* @group connected
*/
public function testCanPerformBitwiseNOT()
{
$redis = $this->getClient();
$redis->set('key:src:1', "h\x80");
$this->assertSame(2, $redis->bitop('NOT', 'key:dst', 'key:src:1'));
$this->assertSame("\x97\x7f", $redis->get('key:dst'));
}
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR BITOP NOT must be called with a single source key.
*/
public function testBitwiseNOTAcceptsOnlyOneSourceKey()
{
$this->getClient()->bitop('NOT', 'key:dst', 'key:src:1', 'key:src:2');
}
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR syntax error
*/
public function testThrowsExceptionOnInvalidOperation()
{
$this->getClient()->bitop('NOOP', 'key:dst', 'key:src:1', 'key:src:2');
}
/**
* @group connected
* @expectedException Predis\ServerException
* @expectedExceptionMessage ERR Operation against a key holding the wrong kind of value
*/
public function testThrowsExceptionOnInvalidSourceKey()
{
$redis = $this->getClient();
$redis->lpush('key:src:1', 'list');
$redis->bitop('AND', 'key:dst', 'key:src:1', 'key:src:2');
}
/**
* @group connected
*/
public function testDoesNotThrowExceptionOnInvalidDestinationKey()
{
$redis = $this->getClient();
$redis->lpush('key:dst', 'list');
$redis->bitop('AND', 'key:dst', 'key:src:1', 'key:src:2');
$this->assertSame('none', $redis->type('key:dst'));
}
}
@@ -164,11 +164,13 @@ class ServerVersion26Test extends ServerVersionTestCase
123 => 'pexpireat',
124 => 'psetex',
125 => 'incrbyfloat',
126 => 'hincrbyfloat',
127 => 'eval',
128 => 'evalsha',
129 => 'script',
130 => 'time',
126 => 'bitop',
127 => 'bitcount',
128 => 'hincrbyfloat',
129 => 'eval',
130 => 'evalsha',
131 => 'script',
132 => 'time',
);
}
}
@@ -164,11 +164,13 @@ class ServerVersionNextTest extends ServerVersionTestCase
123 => 'pexpireat',
124 => 'psetex',
125 => 'incrbyfloat',
126 => 'hincrbyfloat',
127 => 'eval',
128 => 'evalsha',
129 => 'script',
130 => 'time',
126 => 'bitop',
127 => 'bitcount',
128 => 'hincrbyfloat',
129 => 'eval',
130 => 'evalsha',
131 => 'script',
132 => 'time',
);
}
}