Compare commits

...

32 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
Daniele Alessandri 74cc0e3225 Bump version in files for release. 2012-04-01 10:09:20 +02:00
Daniele Alessandri b5ae1b9a2b Update README. 2012-03-31 11:58:38 +02:00
Daniele Alessandri 31c47362fb Add a couple of paragraphs in the FAQ. 2012-03-31 11:29:59 +02:00
Daniele Alessandri 871f1a3a1d Update TODO. 2012-03-31 10:45:16 +02:00
Daniele Alessandri ba0338e3d8 Update CHANGELOG. 2012-03-31 10:44:29 +02:00
Daniele Alessandri a7c906ab4c Apparently the next major version or Redis will be 2.8. 2012-03-31 10:43:50 +02:00
Daniele Alessandri 7675bb040a Make it possible to prepend the autoloader. 2012-03-19 11:31:39 +01:00
Daniele Alessandri 930af24c7f Make Predis\Autoloader faster. 2012-03-18 18:00:00 +01:00
Daniele Alessandri 23ed563e45 Add missing tests for Predis\Profiles\ServerProfile::defineCommand(). 2012-03-18 12:58:19 +01:00
Daniele Alessandri f00bf6443d Update CHANGELOG.
[ci skip]
2012-03-11 14:01:49 +01:00
Daniele Alessandri 6d73f4a538 Promote 2.6 as an independent server profile for Redis 2.6.
The development server profile now targets Redis 3.0.
2012-03-11 13:53:28 +01:00
Daniele Alessandri f0f3d7814c Fix MONITOR and Predis\MonitorContext with Redis 2.6.
Starting with 2.6, Redis uses a slightly different format for the payload
returned by MONITOR for each command. Predis can now adapt to this difference
and returns a new `client` field in the payload object. This new field is
always defined but is set to NULL when connected to Redis < 2.6.

Please note that Redis 2.6 now does not echo the `MONITOR` command as the
first payload when opening a new MONITOR context.
2012-03-11 13:30:30 +01:00
Daniele Alessandri 5c2704c9d4 Add a not about MONITOR failing the test with Redis unstable. 2012-03-07 13:04:28 +01:00
Daniele Alessandri effefcee34 New command: TIME (Redis v2.6-dev). 2012-03-07 12:30:39 +01:00
Daniele Alessandri 86bf223ec0 Enable integration tests for Redis commands on Travis CI.
This was not possible before since our test suite requires Redis >= 2.4 but
their environment was running Redis 2.2 until a month ago or so.
2012-02-25 11:04:31 +01:00
39 changed files with 1282 additions and 89 deletions
+29 -2
View File
@@ -1,8 +1,30 @@
v0.7.2 (2012-xx-xx)
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)
===============================================================================
- Added `2.6` in the server profiles aliases list for the upcoming Redis 2.6.
`2.4` is still the default server profile.
`2.4` is still the default server profile. `dev` now targets Redis 2.8.
- Connection instances can be serialized and unserialized using `serialize()`
and `unserialize()`. This is handy in certain scenarios such as client-side
@@ -10,6 +32,11 @@ v0.7.2 (2012-xx-xx)
object with many sub-connections since unserializing them can be up to 5x
times faster.
- Reworked the default autoloader to make it faster. It is also possible to
prepend it in PHP's autoload stack.
- __FIX__: fixed parsing of the payload returned by `MONITOR` with Redis 2.6.
v0.7.1 (2011-12-27)
===============================================================================
+42
View File
@@ -56,3 +56,45 @@ generalized when using Redis because of the many possible access patterns for th
mean that it is impossible to have such a feature, you can leverage Predis' extensibility to define your
own serialization-aware commands. See [here](http://github.com/nrk/predis/issues/29#issuecomment-1202624)
for more details on how to implement such a feature with a practical example.
### How can I force Predis to connect to Redis before sending any command? ###
Explicitly connecting to Redis is usually not needed since the client library relies on lazily initialized
connections to the server, but this behavior can be inconvenient in certain scenarios when you absolutely
need to do an upfront check to detect if the server is up and running and eventually catch exceptions on
failures. In this case developers can use `Predis\Client::connect()` to explicitly connect to the server:
```
$client = new Predis\Client();
try {
$client->connect();
}
catch (Predis\Network\ConnectionException $exception) {
// We could not connect to Redis! Your handling code goes here.
}
$client->info();
```
### How Predis implements abstraction of Redis commands? ###
The approach used in Predis to implement the abstraction of Redis commands is quite simple. By default
every command in the library follows exactly the same argument list as defined in the great online
[Redis documentation](http://redis.io/commands) which makes things pretty easy if you already know how
Redis works or if you need to look up how to use certain commands. Alternatively, variadic commands can
accept an array for keys or values (depending on the command) instead of a list of arguments. See for
example how [RPUSH](http://redis.io/commands/rpush) or [HMSET](http://redis.io/commands/hmset) work:
```
$client->rpush('my:list', 'value1', 'value2', 'value3'); // values as arguments
$client->rpush('my:list', array('value1', 'value2', 'value3')); // values as single argument array
$client->hmset('my:hash', 'field1', 'value1', 'field2', 'value2'); // values as arguments
$client->hmset('my:hash', array('field1'=>'value1', 'field2'=>'value2'); // values as single named array
```
The only exception to this _rule_ is the [SORT](http://redis.io/commands/sort) command for which modifiers are
[passed using a named array](https://github.com/nrk/predis/blob/v0.7.1/tests/Predis/Commands/KeySortTest.php#L56-77).
+3 -4
View File
@@ -5,13 +5,12 @@ Predis is a flexible and feature-complete PHP (>= 5.3) client library for the Re
For a list of frequently asked questions about Predis, see the __FAQ__ file in the root of the repository.
For a version compatible with PHP 5.2 you must use the backported version from the latest release in the
0.6.x series. More details are available on the [official wiki](http://wiki.github.com/nrk/predis) of the
project,
project.
## Main features ##
- Complete support for Redis from __1.2__ to __2.4__ and the current development versions using different
server profiles.
- Complete support for Redis from __1.2__ to __2.6__ and unstable versions using different server profiles.
- Client-side sharding with support for consistent hashing or custom distribution strategies.
- Support for master / slave replication configurations (write on master, read from slaves).
- Command pipelining on single and aggregated connections.
@@ -35,7 +34,7 @@ by browsing the list of [tagged releases](http://github.com/nrk/predis/tags).
### Loading the library ###
To automatically load all of its files, Predis relies on the autoloading features of PHP and complies
Predis relies on the autoloading features of PHP to automatically load the needed files and complies
with the [PSR-0 standard](http://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md) for
interoperability with most of the major frameworks and libraries. Everything is transparently handled
for you when installing the library using Composer, but you can also leverage its own autoloader class
-2
View File
@@ -1,4 +1,2 @@
* Documentation! The README is obviously not enought to show how to use Predis
as it does not cover all of its features.
* [v0.8] Implement smart and transparent support for redis-cluster.
+1 -1
View File
@@ -1 +1 @@
0.7.2-dev
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,
)
*/
+16 -12
View File
@@ -15,27 +15,32 @@ namespace Predis;
* Implements a lightweight PSR-0 compliant autoloader.
*
* @author Eric Naeseth <eric@thumbtack.com>
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class Autoloader
{
private $baseDir;
private $directory;
private $prefix;
private $prefixLength;
/**
* @param string $baseDirectory Base directory where the source files are located.
*/
public function __construct($baseDirectory = null)
public function __construct($baseDirectory = __DIR__)
{
$this->baseDir = $baseDirectory ?: dirname(__FILE__);
$this->directory = $baseDirectory;
$this->prefix = __NAMESPACE__ . '\\';
$this->prefixLength = strlen($this->prefix);
}
/**
* Registers the autoloader class with the PHP SPL autoloader.
*
* @param boolean $prepend Prepend the autoloader on the stack instead of appending it.
*/
public static function register()
public static function register($prepend = false)
{
spl_autoload_register(array(new self, 'autoload'));
spl_autoload_register(array(new self, 'autoload'), true, $prepend);
}
/**
@@ -45,13 +50,12 @@ class Autoloader
*/
public function autoload($className)
{
if (0 !== strpos($className, $this->prefix)) {
return;
if (0 === strpos($className, $this->prefix)) {
$parts = explode('\\', substr($className, $this->prefixLength));
$filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php';
if (is_file($filepath)) {
require($filepath);
}
}
$relativeClassName = substr($className, strlen($this->prefix));
$classNameParts = explode('\\', $relativeClassName);
require_once $this->baseDir.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $classNameParts).'.php';
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ use Predis\Transaction\MultiExecContext;
*/
class Client
{
const VERSION = '0.7.2-dev';
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);
}
}
+43
View File
@@ -0,0 +1,43 @@
<?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/time
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ServerTime extends Command
{
/**
* {@inheritdoc}
*/
public function getId()
{
return 'TIME';
}
/**
* {@inheritdoc}
*/
protected function canBeHashed()
{
return false;
}
/**
* {@inheritdoc}
*/
public function parseResponse($data)
{
return $data instanceof \Iterator ? iterator_to_array($data) : $data;
}
}
+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;
}
+12 -4
View File
@@ -132,21 +132,29 @@ class MonitorContext implements \Iterator
private function getValue()
{
$database = 0;
$client = null;
$event = $this->client->getConnection()->read();
$callback = function($matches) use (&$database) {
if (isset($matches[1])) {
$callback = function($matches) use (&$database, &$client) {
if (2 === $count = count($matches)) {
// Redis <= 2.4
$database = (int) $matches[1];
}
if (4 === $count) {
// Redis >= 2.6
$database = (int) $matches[2];
$client = $matches[3];
}
return ' ';
};
$event = preg_replace_callback('/ \(db (\d+)\) /', $callback, $event, 1);
@list($timestamp, $command, $arguments) = split(' ', $event, 3);
$event = preg_replace_callback('/ \(db (\d+)\) | \[(\d+) (.*?)\] /', $callback, $event, 1);
@list($timestamp, $command, $arguments) = explode(' ', $event, 3);
return (object) array(
'timestamp' => (float) $timestamp,
'database' => $database,
'client' => $client,
'command' => substr($command, 1, -1),
'arguments' => $arguments,
);
@@ -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);
}
+1 -1
View File
@@ -76,7 +76,7 @@ abstract class ServerProfile implements IServerProfile, IProcessingSupport
'2.0' => 'Predis\Profiles\ServerVersion20',
'2.2' => 'Predis\Profiles\ServerVersion22',
'2.4' => 'Predis\Profiles\ServerVersion24',
'2.6' => 'Predis\Profiles\ServerVersionNext',
'2.6' => 'Predis\Profiles\ServerVersion26',
'default' => 'Predis\Profiles\ServerVersion24',
'dev' => 'Predis\Profiles\ServerVersionNext',
);
+236
View File
@@ -0,0 +1,236 @@
<?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\Profiles;
/**
* Server profile for Redis v2.6.x.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ServerVersion26 extends ServerProfile
{
/**
* {@inheritdoc}
*/
public function getVersion()
{
return '2.6';
}
/**
* {@inheritdoc}
*/
public function getSupportedCommands()
{
return array(
/* ---------------- Redis 1.2 ---------------- */
/* commands operating on the key space */
'exists' => 'Predis\Commands\KeyExists',
'del' => 'Predis\Commands\KeyDelete',
'type' => 'Predis\Commands\KeyType',
'keys' => 'Predis\Commands\KeyKeys',
'randomkey' => 'Predis\Commands\KeyRandom',
'rename' => 'Predis\Commands\KeyRename',
'renamenx' => 'Predis\Commands\KeyRenamePreserve',
'expire' => 'Predis\Commands\KeyExpire',
'expireat' => 'Predis\Commands\KeyExpireAt',
'ttl' => 'Predis\Commands\KeyTimeToLive',
'move' => 'Predis\Commands\KeyMove',
'sort' => 'Predis\Commands\KeySort',
/* commands operating on string values */
'set' => 'Predis\Commands\StringSet',
'setnx' => 'Predis\Commands\StringSetPreserve',
'mset' => 'Predis\Commands\StringSetMultiple',
'msetnx' => 'Predis\Commands\StringSetMultiplePreserve',
'get' => 'Predis\Commands\StringGet',
'mget' => 'Predis\Commands\StringGetMultiple',
'getset' => 'Predis\Commands\StringGetSet',
'incr' => 'Predis\Commands\StringIncrement',
'incrby' => 'Predis\Commands\StringIncrementBy',
'decr' => 'Predis\Commands\StringDecrement',
'decrby' => 'Predis\Commands\StringDecrementBy',
/* commands operating on lists */
'rpush' => 'Predis\Commands\ListPushTail',
'lpush' => 'Predis\Commands\ListPushHead',
'llen' => 'Predis\Commands\ListLength',
'lrange' => 'Predis\Commands\ListRange',
'ltrim' => 'Predis\Commands\ListTrim',
'lindex' => 'Predis\Commands\ListIndex',
'lset' => 'Predis\Commands\ListSet',
'lrem' => 'Predis\Commands\ListRemove',
'lpop' => 'Predis\Commands\ListPopFirst',
'rpop' => 'Predis\Commands\ListPopLast',
'rpoplpush' => 'Predis\Commands\ListPopLastPushHead',
/* commands operating on sets */
'sadd' => 'Predis\Commands\SetAdd',
'srem' => 'Predis\Commands\SetRemove',
'spop' => 'Predis\Commands\SetPop',
'smove' => 'Predis\Commands\SetMove',
'scard' => 'Predis\Commands\SetCardinality',
'sismember' => 'Predis\Commands\SetIsMember',
'sinter' => 'Predis\Commands\SetIntersection',
'sinterstore' => 'Predis\Commands\SetIntersectionStore',
'sunion' => 'Predis\Commands\SetUnion',
'sunionstore' => 'Predis\Commands\SetUnionStore',
'sdiff' => 'Predis\Commands\SetDifference',
'sdiffstore' => 'Predis\Commands\SetDifferenceStore',
'smembers' => 'Predis\Commands\SetMembers',
'srandmember' => 'Predis\Commands\SetRandomMember',
/* commands operating on sorted sets */
'zadd' => 'Predis\Commands\ZSetAdd',
'zincrby' => 'Predis\Commands\ZSetIncrementBy',
'zrem' => 'Predis\Commands\ZSetRemove',
'zrange' => 'Predis\Commands\ZSetRange',
'zrevrange' => 'Predis\Commands\ZSetReverseRange',
'zrangebyscore' => 'Predis\Commands\ZSetRangeByScore',
'zcard' => 'Predis\Commands\ZSetCardinality',
'zscore' => 'Predis\Commands\ZSetScore',
'zremrangebyscore' => 'Predis\Commands\ZSetRemoveRangeByScore',
/* connection related commands */
'ping' => 'Predis\Commands\ConnectionPing',
'auth' => 'Predis\Commands\ConnectionAuth',
'select' => 'Predis\Commands\ConnectionSelect',
'echo' => 'Predis\Commands\ConnectionEcho',
'quit' => 'Predis\Commands\ConnectionQuit',
/* remote server control commands */
'info' => 'Predis\Commands\ServerInfo',
'slaveof' => 'Predis\Commands\ServerSlaveOf',
'monitor' => 'Predis\Commands\ServerMonitor',
'dbsize' => 'Predis\Commands\ServerDatabaseSize',
'flushdb' => 'Predis\Commands\ServerFlushDatabase',
'flushall' => 'Predis\Commands\ServerFlushAll',
'save' => 'Predis\Commands\ServerSave',
'bgsave' => 'Predis\Commands\ServerBackgroundSave',
'lastsave' => 'Predis\Commands\ServerLastSave',
'shutdown' => 'Predis\Commands\ServerShutdown',
'bgrewriteaof' => 'Predis\Commands\ServerBackgroundRewriteAOF',
/* ---------------- Redis 2.0 ---------------- */
/* commands operating on string values */
'setex' => 'Predis\Commands\StringSetExpire',
'append' => 'Predis\Commands\StringAppend',
'substr' => 'Predis\Commands\StringSubstr',
/* commands operating on lists */
'blpop' => 'Predis\Commands\ListPopFirstBlocking',
'brpop' => 'Predis\Commands\ListPopLastBlocking',
/* commands operating on sorted sets */
'zunionstore' => 'Predis\Commands\ZSetUnionStore',
'zinterstore' => 'Predis\Commands\ZSetIntersectionStore',
'zcount' => 'Predis\Commands\ZSetCount',
'zrank' => 'Predis\Commands\ZSetRank',
'zrevrank' => 'Predis\Commands\ZSetReverseRank',
'zremrangebyrank' => 'Predis\Commands\ZSetRemoveRangeByRank',
/* commands operating on hashes */
'hset' => 'Predis\Commands\HashSet',
'hsetnx' => 'Predis\Commands\HashSetPreserve',
'hmset' => 'Predis\Commands\HashSetMultiple',
'hincrby' => 'Predis\Commands\HashIncrementBy',
'hget' => 'Predis\Commands\HashGet',
'hmget' => 'Predis\Commands\HashGetMultiple',
'hdel' => 'Predis\Commands\HashDelete',
'hexists' => 'Predis\Commands\HashExists',
'hlen' => 'Predis\Commands\HashLength',
'hkeys' => 'Predis\Commands\HashKeys',
'hvals' => 'Predis\Commands\HashValues',
'hgetall' => 'Predis\Commands\HashGetAll',
/* transactions */
'multi' => 'Predis\Commands\TransactionMulti',
'exec' => 'Predis\Commands\TransactionExec',
'discard' => 'Predis\Commands\TransactionDiscard',
/* publish - subscribe */
'subscribe' => 'Predis\Commands\PubSubSubscribe',
'unsubscribe' => 'Predis\Commands\PubSubUnsubscribe',
'psubscribe' => 'Predis\Commands\PubSubSubscribeByPattern',
'punsubscribe' => 'Predis\Commands\PubSubUnsubscribeByPattern',
'publish' => 'Predis\Commands\PubSubPublish',
/* remote server control commands */
'config' => 'Predis\Commands\ServerConfig',
/* ---------------- Redis 2.2 ---------------- */
/* commands operating on the key space */
'persist' => 'Predis\Commands\KeyPersist',
/* commands operating on string values */
'strlen' => 'Predis\Commands\StringStrlen',
'setrange' => 'Predis\Commands\StringSetRange',
'getrange' => 'Predis\Commands\StringGetRange',
'setbit' => 'Predis\Commands\StringSetBit',
'getbit' => 'Predis\Commands\StringGetBit',
/* commands operating on lists */
'rpushx' => 'Predis\Commands\ListPushTailX',
'lpushx' => 'Predis\Commands\ListPushHeadX',
'linsert' => 'Predis\Commands\ListInsert',
'brpoplpush' => 'Predis\Commands\ListPopLastPushHeadBlocking',
/* commands operating on sorted sets */
'zrevrangebyscore' => 'Predis\Commands\ZSetReverseRangeByScore',
/* transactions */
'watch' => 'Predis\Commands\TransactionWatch',
'unwatch' => 'Predis\Commands\TransactionUnwatch',
/* remote server control commands */
'object' => 'Predis\Commands\ServerObject',
'slowlog' => 'Predis\Commands\ServerSlowlog',
/* ---------------- Redis 2.4 ---------------- */
/* remote server control commands */
'client' => 'Predis\Commands\ServerClient',
/* ---------------- Redis 2.6 ---------------- */
/* commands operating on the key space */
'pttl' => 'Predis\Commands\KeyPreciseTimeToLive',
'pexpire' => 'Predis\Commands\KeyPreciseExpire',
'pexpireat' => 'Predis\Commands\KeyPreciseExpireAt',
/* 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',
/* scripting */
'eval' => 'Predis\Commands\ServerEval',
'evalsha' => 'Predis\Commands\ServerEvalSHA',
'script' => 'Predis\Commands\ServerScript',
/* remote server control commands */
'info' => 'Predis\Commands\ServerInfoV26x',
'time' => 'Predis\Commands\ServerTime',
);
}
}
+3 -22
View File
@@ -12,18 +12,18 @@
namespace Predis\Profiles;
/**
* Server profile for the current development version of Redis.
* Server profile for the current unstable version of Redis.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class ServerVersionNext extends ServerVersion24
class ServerVersionNext extends ServerVersion26
{
/**
* {@inheritdoc}
*/
public function getVersion()
{
return '2.6';
return '2.8';
}
/**
@@ -32,25 +32,6 @@ class ServerVersionNext extends ServerVersion24
public function getSupportedCommands()
{
return array_merge(parent::getSupportedCommands(), array(
/* commands operating on the key space */
'pttl' => 'Predis\Commands\KeyPreciseTimeToLive',
'pexpire' => 'Predis\Commands\KeyPreciseExpire',
'pexpireat' => 'Predis\Commands\KeyPreciseExpireAt',
/* commands operating on string values */
'psetex' => 'Predis\Commands\StringPreciseSetExpire',
'incrbyfloat' => 'Predis\Commands\StringIncrementByFloat',
/* commands operating on hashes */
'hincrbyfloat' => 'Predis\Commands\HashIncrementByFloat',
/* scripting */
'eval' => 'Predis\Commands\ServerEval',
'evalsha' => 'Predis\Commands\ServerEvalSHA',
'script' => 'Predis\Commands\ServerScript',
/* remote server control commands */
'info' => 'Predis\Commands\ServerInfoV26x',
));
}
}
+5 -6
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,8 +10,8 @@ name = "Predis"
desc = "Flexible and feature-complete PHP client library for Redis"
homepage = "http://github.com/nrk/predis"
license = "MIT"
version = "0.7.2"
stability = "beta"
version = "0.7.3"
stability = "stable"
channel = "pear.nrk.io"
author = "Daniele Alessandri \"nrk\" <suppakilla@gmail.com>"
+1 -1
View File
@@ -12,7 +12,7 @@
<group>ext-phpiredis</group>
<group>ext-curl</group>
<group>realm-webdis</group>
<group>connected</group>
<!-- <group>connected</group> -->
<!-- <group>disconnected</group> -->
<!-- <group>commands</group> -->
<!-- <group>slow</group> -->
@@ -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
*/
+6 -1
View File
@@ -64,6 +64,11 @@ class ServerMonitorTest extends CommandTestCase
$command = $this->getCommand();
$this->assertTrue($connection->executeCommand($command));
$this->assertRegExp('/\d+.\d+(\s?\(db \d+\))? "MONITOR"/', $connection->read());
// NOTE: Starting with 2.6 Redis does not return the "MONITOR" message after
// +OK to the client that issued the MONITOR command.
if (version_compare($this->getProfile()->getVersion(), '2.4', '<=')) {
$this->assertRegExp('/\d+.\d+(\s?\(db \d+\))? "MONITOR"/', $connection->read());
}
}
}
+74
View File
@@ -0,0 +1,74 @@
<?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-server
*/
class ServerTimeTest extends CommandTestCase
{
/**
* {@inheritdoc}
*/
protected function getExpectedCommand()
{
return 'Predis\Commands\ServerTime';
}
/**
* {@inheritdoc}
*/
protected function getExpectedId()
{
return 'TIME';
}
/**
* @group disconnected
*/
public function testFilterArguments()
{
$arguments = array();
$expected = array();
$command = $this->getCommand();
$command->setArguments($arguments);
$this->assertSame($expected, $command->getArguments());
}
/**
* @group disconnected
*/
public function testParseResponse()
{
$expected = array(1331114908, 453990);
$command = $this->getCommand();
$this->assertSame($expected, $command->parseResponse($expected));
}
/**
* @group connected
*/
public function testReturnsServerTime()
{
$redis = $this->getClient();
$this->assertInternalType('array', $time = $redis->time());
$this->assertInternalType('string', $time[0]);
$this->assertInternalType('string', $time[1]);
}
}
@@ -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'));
}
}
+25 -1
View File
@@ -105,7 +105,7 @@ class MonitorContextTest extends StandardTestCase
/**
* @group disconnected
*/
public function testCurrentReadsMessageFromConnection()
public function testReadsMessageFromConnectionToRedis24()
{
$message = '1323367530.939137 (db 15) "MONITOR"';
@@ -120,6 +120,30 @@ class MonitorContextTest extends StandardTestCase
$payload = $monitor->current();
$this->assertSame(1323367530, (int) $payload->timestamp);
$this->assertSame(15, $payload->database);
$this->assertNull($payload->client);
$this->assertSame('MONITOR', $payload->command);
$this->assertNull($payload->arguments);
}
/**
* @group disconnected
*/
public function testReadsMessageFromConnectionToRedis26()
{
$message = '1323367530.939137 [15 127.0.0.1:37265] "MONITOR"';
$connection = $this->getMock('Predis\Network\IConnectionSingle');
$connection->expects($this->once())
->method('read')
->will($this->returnValue($message));
$client = new Client($connection);
$monitor = new MonitorContext($client);
$payload = $monitor->current();
$this->assertSame(1323367530, (int) $payload->timestamp);
$this->assertSame(15, $payload->database);
$this->assertSame('127.0.0.1:37265', $payload->client);
$this->assertSame('MONITOR', $payload->command);
$this->assertNull($payload->arguments);
}
+29 -1
View File
@@ -20,7 +20,7 @@ use Predis\Commands\Processors\ProcessorChain;
class ServerProfileTest extends StandardTestCase
{
const DEFAULT_PROFILE_VERSION = '2.4';
const DEVELOPMENT_PROFILE_VERSION = '2.6';
const DEVELOPMENT_PROFILE_VERSION = '2.8';
/**
* @group disconnected
@@ -145,6 +145,34 @@ class ServerProfileTest extends StandardTestCase
$this->assertNull($profile->getCommandClass('UNKNOWN'));
}
/**
* @group disconnected
*/
public function testDefineCommand()
{
$profile = ServerProfile::getDefault();
$command = $this->getMock('Predis\Commands\ICommand');
$profile->defineCommand('mock', get_class($command));
$this->assertTrue($profile->supportsCommand('mock'));
$this->assertTrue($profile->supportsCommand('MOCK'));
$this->assertSame(get_class($command), $profile->getCommandClass('mock'));
}
/**
* @group disconnected
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Cannot register 'stdClass' as it is not a valid Redis command
*/
public function testDefineInvalidCommand()
{
$profile = ServerProfile::getDefault();
$profile->defineCommand('mock', 'stdClass');
}
/**
* @group disconnected
*/
@@ -0,0 +1,176 @@
<?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\Profiles;
/**
*
*/
class ServerVersion26Test extends ServerVersionTestCase
{
/**
* {@inheritdoc}
*/
public function getProfileInstance()
{
return new ServerVersion26();
}
/**
* {@inheritdoc}
*/
public function getExpectedVersion()
{
return '2.6';
}
/**
* {@inheritdoc}
*/
public function getExpectedCommands()
{
return array(
0 => 'exists',
1 => 'del',
2 => 'type',
3 => 'keys',
4 => 'randomkey',
5 => 'rename',
6 => 'renamenx',
7 => 'expire',
8 => 'expireat',
9 => 'ttl',
10 => 'move',
11 => 'sort',
12 => 'set',
13 => 'setnx',
14 => 'mset',
15 => 'msetnx',
16 => 'get',
17 => 'mget',
18 => 'getset',
19 => 'incr',
20 => 'incrby',
21 => 'decr',
22 => 'decrby',
23 => 'rpush',
24 => 'lpush',
25 => 'llen',
26 => 'lrange',
27 => 'ltrim',
28 => 'lindex',
29 => 'lset',
30 => 'lrem',
31 => 'lpop',
32 => 'rpop',
33 => 'rpoplpush',
34 => 'sadd',
35 => 'srem',
36 => 'spop',
37 => 'smove',
38 => 'scard',
39 => 'sismember',
40 => 'sinter',
41 => 'sinterstore',
42 => 'sunion',
43 => 'sunionstore',
44 => 'sdiff',
45 => 'sdiffstore',
46 => 'smembers',
47 => 'srandmember',
48 => 'zadd',
49 => 'zincrby',
50 => 'zrem',
51 => 'zrange',
52 => 'zrevrange',
53 => 'zrangebyscore',
54 => 'zcard',
55 => 'zscore',
56 => 'zremrangebyscore',
57 => 'ping',
58 => 'auth',
59 => 'select',
60 => 'echo',
61 => 'quit',
62 => 'info',
63 => 'slaveof',
64 => 'monitor',
65 => 'dbsize',
66 => 'flushdb',
67 => 'flushall',
68 => 'save',
69 => 'bgsave',
70 => 'lastsave',
71 => 'shutdown',
72 => 'bgrewriteaof',
73 => 'setex',
74 => 'append',
75 => 'substr',
76 => 'blpop',
77 => 'brpop',
78 => 'zunionstore',
79 => 'zinterstore',
80 => 'zcount',
81 => 'zrank',
82 => 'zrevrank',
83 => 'zremrangebyrank',
84 => 'hset',
85 => 'hsetnx',
86 => 'hmset',
87 => 'hincrby',
88 => 'hget',
89 => 'hmget',
90 => 'hdel',
91 => 'hexists',
92 => 'hlen',
93 => 'hkeys',
94 => 'hvals',
95 => 'hgetall',
96 => 'multi',
97 => 'exec',
98 => 'discard',
99 => 'subscribe',
100 => 'unsubscribe',
101 => 'psubscribe',
102 => 'punsubscribe',
103 => 'publish',
104 => 'config',
105 => 'persist',
106 => 'strlen',
107 => 'setrange',
108 => 'getrange',
109 => 'setbit',
110 => 'getbit',
111 => 'rpushx',
112 => 'lpushx',
113 => 'linsert',
114 => 'brpoplpush',
115 => 'zrevrangebyscore',
116 => 'watch',
117 => 'unwatch',
118 => 'object',
119 => 'slowlog',
120 => 'client',
121 => 'pttl',
122 => 'pexpire',
123 => 'pexpireat',
124 => 'psetex',
125 => 'incrbyfloat',
126 => 'bitop',
127 => 'bitcount',
128 => 'hincrbyfloat',
129 => 'eval',
130 => 'evalsha',
131 => 'script',
132 => 'time',
);
}
}
@@ -29,7 +29,7 @@ class ServerVersionNextTest extends ServerVersionTestCase
*/
public function getExpectedVersion()
{
return '2.6';
return '2.8';
}
/**
@@ -164,10 +164,13 @@ class ServerVersionNextTest extends ServerVersionTestCase
123 => 'pexpireat',
124 => 'psetex',
125 => 'incrbyfloat',
126 => 'hincrbyfloat',
127 => 'eval',
128 => 'evalsha',
129 => 'script',
126 => 'bitop',
127 => 'bitcount',
128 => 'hincrbyfloat',
129 => 'eval',
130 => 'evalsha',
131 => 'script',
132 => 'time',
);
}
}