mirror of
https://github.com/predis/predis.git
synced 2026-08-24 08:09:39 +00:00
67c0fb8eb1
This change does not affect distribution but simply separates the two concepts of connection ID (ip:port pair) and alias (value set via the "alias" connection parameter), the method getConnectionByAlias() has been added to reflect this change. The method getConnectionBySlot() has also been added.
1218 lines
40 KiB
PHP
1218 lines
40 KiB
PHP
<?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;
|
|
|
|
use PredisTestCase;
|
|
|
|
/**
|
|
*
|
|
*/
|
|
class ClientTest extends PredisTestCase
|
|
{
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithoutArguments()
|
|
{
|
|
$client = new Client();
|
|
|
|
$connection = $client->getConnection();
|
|
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
|
|
|
$parameters = $connection->getParameters();
|
|
$this->assertSame($parameters->host, '127.0.0.1');
|
|
$this->assertSame($parameters->port, 6379);
|
|
|
|
$options = $client->getOptions();
|
|
$this->assertSame($options->commands, $client->getCommandFactory());
|
|
|
|
$this->assertFalse($client->isConnected());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithNullArgument()
|
|
{
|
|
$client = new Client(null);
|
|
|
|
$connection = $client->getConnection();
|
|
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
|
|
|
$parameters = $connection->getParameters();
|
|
$this->assertSame($parameters->host, '127.0.0.1');
|
|
$this->assertSame($parameters->port, 6379);
|
|
|
|
$options = $client->getOptions();
|
|
$this->assertSame($options->commands, $client->getCommandFactory());
|
|
|
|
$this->assertFalse($client->isConnected());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithNullAndNullArguments()
|
|
{
|
|
$client = new Client(null, null);
|
|
|
|
$connection = $client->getConnection();
|
|
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection);
|
|
|
|
$parameters = $connection->getParameters();
|
|
$this->assertSame($parameters->host, '127.0.0.1');
|
|
$this->assertSame($parameters->port, 6379);
|
|
|
|
$options = $client->getOptions();
|
|
$this->assertSame($options->commands, $client->getCommandFactory());
|
|
|
|
$this->assertFalse($client->isConnected());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithArrayArgument()
|
|
{
|
|
$client = new Client($arg1 = array('host' => 'localhost', 'port' => 7000));
|
|
|
|
$parameters = $client->getConnection()->getParameters();
|
|
$this->assertSame($parameters->host, $arg1['host']);
|
|
$this->assertSame($parameters->port, $arg1['port']);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \InvalidArgumentException
|
|
* @expectedExceptionMessage Array of connection parameters requires `cluster`, `replication` or `aggregate` client option
|
|
*/
|
|
public function testConstructorThrowsExceptionWithArrayOfParametersArgumentAndMissingOption()
|
|
{
|
|
$arg1 = array(
|
|
array('host' => 'localhost', 'port' => 7000),
|
|
array('host' => 'localhost', 'port' => 7001),
|
|
);
|
|
|
|
$client = new Client($arg1);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithArrayOfArrayArgumentAndClusterOption()
|
|
{
|
|
$arg1 = array(
|
|
array('host' => 'localhost', 'port' => 7000),
|
|
array('host' => 'localhost', 'port' => 7001),
|
|
);
|
|
|
|
$client = new Client($arg1, array(
|
|
'aggregate' => $this->getAggregateInitializer($arg1),
|
|
));
|
|
|
|
$this->assertInstanceOf('Predis\Connection\AggregateConnectionInterface', $client->getConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithStringArgument()
|
|
{
|
|
$client = new Client('tcp://localhost:7000');
|
|
|
|
$parameters = $client->getConnection()->getParameters();
|
|
$this->assertSame($parameters->host, 'localhost');
|
|
$this->assertSame($parameters->port, 7000);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithArrayOfStringArgument()
|
|
{
|
|
$arg1 = array('tcp://localhost:7000', 'tcp://localhost:7001');
|
|
|
|
$client = new Client($arg1, array(
|
|
'aggregate' => $this->getAggregateInitializer($arg1),
|
|
));
|
|
|
|
$this->assertInstanceOf('Predis\Connection\AggregateConnectionInterface', $client->getConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithArrayOfConnectionsArgument()
|
|
{
|
|
$arg1 = array(
|
|
$this->getMock('Predis\Connection\NodeConnectionInterface'),
|
|
$this->getMock('Predis\Connection\NodeConnectionInterface'),
|
|
);
|
|
|
|
$client = new Client($arg1, array(
|
|
'aggregate' => $this->getAggregateInitializer($arg1),
|
|
));
|
|
|
|
$this->assertInstanceOf('Predis\Connection\AggregateConnectionInterface', $client->getConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithConnectionArgument()
|
|
{
|
|
$factory = new Connection\Factory();
|
|
$connection = $factory->create('tcp://localhost:7000');
|
|
|
|
$client = new Client($connection);
|
|
|
|
$this->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $client->getConnection());
|
|
$this->assertSame($connection, $client->getConnection());
|
|
|
|
$parameters = $client->getConnection()->getParameters();
|
|
$this->assertSame($parameters->host, 'localhost');
|
|
$this->assertSame($parameters->port, 7000);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithClusterArgument()
|
|
{
|
|
$cluster = new Connection\Cluster\PredisCluster();
|
|
|
|
$factory = new Connection\Factory();
|
|
$factory->aggregate($cluster, array('tcp://localhost:7000', 'tcp://localhost:7001'));
|
|
|
|
$client = new Client($cluster);
|
|
|
|
$this->assertInstanceOf('Predis\Connection\Cluster\ClusterInterface', $client->getConnection());
|
|
$this->assertSame($cluster, $client->getConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithReplicationArgument()
|
|
{
|
|
$replication = new Connection\Replication\MasterSlaveReplication();
|
|
|
|
$factory = new Connection\Factory();
|
|
$factory->aggregate($replication, array('tcp://host1?alias=master', 'tcp://host2?alias=slave'));
|
|
|
|
$client = new Client($replication);
|
|
|
|
$this->assertInstanceOf('Predis\Connection\Replication\ReplicationInterface', $client->getConnection());
|
|
$this->assertSame($replication, $client->getConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithCallableArgument()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
|
|
$callable = $this->getMock('stdClass', array('__invoke'));
|
|
$callable
|
|
->expects($this->once())
|
|
->method('__invoke')
|
|
->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'))
|
|
->will($this->returnValue($connection));
|
|
|
|
$client = new Client($callable);
|
|
|
|
$this->assertSame($connection, $client->getConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \InvalidArgumentException
|
|
* @expectedExceptionMessage Callable parameters must return a valid connection
|
|
*/
|
|
public function testConstructorWithCallableConnectionInitializerThrowsExceptionOnInvalidReturnType()
|
|
{
|
|
$wrongType = $this->getMock('stdClass');
|
|
|
|
$callable = $this->getMock('stdClass', array('__invoke'));
|
|
$callable
|
|
->expects($this->once())
|
|
->method('__invoke')
|
|
->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'))
|
|
->will($this->returnValue($wrongType));
|
|
|
|
new Client($callable);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithNullAndArrayArgument()
|
|
{
|
|
$connections = $this->getMock('Predis\Connection\FactoryInterface');
|
|
|
|
$arg2 = array('prefix' => 'prefix:', 'connections' => $connections);
|
|
$client = new Client(null, $arg2);
|
|
|
|
$this->assertInstanceOf('Predis\Command\FactoryInterface', $commands = $client->getCommandFactory());
|
|
$this->assertInstanceOf('Predis\Command\Processor\KeyPrefixProcessor', $commands->getProcessor());
|
|
$this->assertSame('prefix:', $commands->getProcessor()->getPrefix());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConstructorWithArrayAndOptionReplication()
|
|
{
|
|
$arg1 = array('tcp://127.0.0.1:6379?role=master', 'tcp://127.0.0.1:6380?role=slave');
|
|
$arg2 = array('replication' => 'predis');
|
|
$client = new Client($arg1, $arg2);
|
|
|
|
$this->assertInstanceOf('Predis\Connection\Replication\ReplicationInterface', $connection = $client->getConnection());
|
|
$this->assertSame('127.0.0.1:6379', (string) $connection->getConnectionByRole('master'));
|
|
$this->assertSame('127.0.0.1:6380', (string) $connection->getConnectionByRole('slave'));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testClusterOptionHasPrecedenceOverReplicationOptionAndAggregateOption()
|
|
{
|
|
$arg1 = array('tcp://host1', 'tcp://host2');
|
|
|
|
$connection = $this->getMock('Predis\Connection\AggregateConnectionInterface');
|
|
|
|
$fncluster = $this->getMock('stdClass', array('__invoke'));
|
|
$fncluster
|
|
->expects($this->once())
|
|
->method('__invoke')
|
|
->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'), $arg1)
|
|
->will($this->returnValue($connection));
|
|
|
|
$fnreplication = $this->getMock('stdClass', array('__invoke'));
|
|
$fnreplication
|
|
->expects($this->never())
|
|
->method('__invoke');
|
|
|
|
$fnaggregate = $this->getMock('stdClass', array('__invoke'));
|
|
$fnaggregate
|
|
->expects($this->never())
|
|
->method('__invoke');
|
|
|
|
$arg2 = array(
|
|
'cluster' => $fncluster,
|
|
'replication' => $fnreplication,
|
|
'aggregate' => $fnaggregate,
|
|
);
|
|
|
|
$client = new Client($arg1, $arg2);
|
|
|
|
$this->assertSame($connection, $client->getConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testReplicationOptionHasPrecedenceOverAggregateOption()
|
|
{
|
|
$arg1 = array('tcp://host1', 'tcp://host2');
|
|
|
|
$connection = $this->getMock('Predis\Connection\AggregateConnectionInterface');
|
|
|
|
$fnreplication = $this->getMock('stdClass', array('__invoke'));
|
|
$fnreplication
|
|
->expects($this->once())
|
|
->method('__invoke')
|
|
->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'), $arg1)
|
|
->will($this->returnValue($connection));
|
|
|
|
$fnaggregate = $this->getMock('stdClass', array('__invoke'));
|
|
$fnaggregate->expects($this->never())->method('__invoke');
|
|
|
|
$arg2 = array(
|
|
'replication' => $fnreplication,
|
|
'aggregate' => $fnaggregate,
|
|
);
|
|
|
|
$client = new Client($arg1, $arg2);
|
|
|
|
$this->assertSame($connection, $client->getConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testAggregateOptionDoesNotTriggerAggregationInClient()
|
|
{
|
|
$arg1 = array('tcp://host1', 'tcp://host2');
|
|
|
|
$connection = $this->getMock('Predis\Connection\AggregateConnectionInterface');
|
|
|
|
$fnaggregate = $this->getMock('stdClass', array('__invoke'));
|
|
$fnaggregate
|
|
->expects($this->once())
|
|
->method('__invoke')
|
|
->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'), $arg1)
|
|
->will($this->returnValue($connection));
|
|
|
|
$connections = $this->getMock('Predis\Connection\FactoryInterface');
|
|
$connections
|
|
->expects($this->never())
|
|
->method('aggregate');
|
|
|
|
$arg2 = array('aggregate' => $fnaggregate, 'connections' => $connections);
|
|
|
|
$client = new Client($arg1, $arg2);
|
|
|
|
$this->assertSame($connection, $client->getConnection());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \InvalidArgumentException
|
|
* @expectedExceptionMessage Invalid type for connection parameters
|
|
*/
|
|
public function testConstructorWithInvalidArgumentType()
|
|
{
|
|
$client = new Client(new \stdClass());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \InvalidArgumentException
|
|
* @expectedExceptionMessage Invalid type for client options
|
|
*/
|
|
public function testConstructorWithInvalidOptionType()
|
|
{
|
|
$client = new Client('tcp://host1', new \stdClass());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testConnectAndDisconnect()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('connect');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('disconnect');
|
|
|
|
$client = new Client($connection);
|
|
$client->connect();
|
|
$client->disconnect();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testIsConnectedChecksConnectionState()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('isConnected');
|
|
|
|
$client = new Client($connection);
|
|
$client->isConnected();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testQuitIsAliasForDisconnect()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('disconnect');
|
|
|
|
$client = new Client($connection);
|
|
$client->quit();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testCreatesNewCommandUsingSpecifiedCommandFactory()
|
|
{
|
|
$ping = $this->getCommandFactory()->createCommand('ping', array());
|
|
|
|
$commands = $this->getMock('Predis\Command\FactoryInterface');
|
|
$commands
|
|
->expects($this->once())
|
|
->method('createCommand')
|
|
->with('ping', array())
|
|
->will($this->returnValue($ping));
|
|
|
|
$client = new Client(null, array('commands' => $commands));
|
|
$this->assertSame($ping, $client->createCommand('ping', array()));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testExecuteCommandReturnsParsedResponses()
|
|
{
|
|
$commands = $this->getCommandFactory();
|
|
|
|
$ping = $commands->createCommand('ping', array());
|
|
$hgetall = $commands->createCommand('hgetall', array('metavars', 'foo', 'hoge'));
|
|
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->at(0))
|
|
->method('executeCommand')
|
|
->with($ping)
|
|
->will($this->returnValue(new Response\Status('PONG')));
|
|
$connection
|
|
->expects($this->at(1))
|
|
->method('executeCommand')
|
|
->with($hgetall)
|
|
->will($this->returnValue(array('foo', 'bar', 'hoge', 'piyo')));
|
|
|
|
$client = new Client($connection);
|
|
|
|
$this->assertEquals('PONG', $client->executeCommand($ping));
|
|
$this->assertSame(array('foo' => 'bar', 'hoge' => 'piyo'), $client->executeCommand($hgetall));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \Predis\Response\ServerException
|
|
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
|
|
*/
|
|
public function testExecuteCommandThrowsExceptionOnRedisError()
|
|
{
|
|
$ping = $this->getCommandFactory()->createCommand('ping', array());
|
|
$expectedResponse = new Response\Error('ERR Operation against a key holding the wrong kind of value');
|
|
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('executeCommand')
|
|
->will($this->returnValue($expectedResponse));
|
|
|
|
$client = new Client($connection);
|
|
$client->executeCommand($ping);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testExecuteCommandReturnsErrorResponseOnRedisError()
|
|
{
|
|
$ping = $this->getCommandFactory()->createCommand('ping', array());
|
|
$expectedResponse = new Response\Error('ERR Operation against a key holding the wrong kind of value');
|
|
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('executeCommand')
|
|
->will($this->returnValue($expectedResponse));
|
|
|
|
$client = new Client($connection, array('exceptions' => false));
|
|
$response = $client->executeCommand($ping);
|
|
|
|
$this->assertSame($response, $expectedResponse);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testCallingRedisCommandExecutesInstanceOfCommand()
|
|
{
|
|
$ping = $this->getCommandFactory()->createCommand('ping', array());
|
|
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('executeCommand')
|
|
->with($this->isInstanceOf('Predis\Command\Redis\PING'))
|
|
->will($this->returnValue('PONG'));
|
|
|
|
$commands = $this->getMock('Predis\Command\FactoryInterface');
|
|
$commands
|
|
->expects($this->once())
|
|
->method('createCommand')
|
|
->with('ping', array())
|
|
->will($this->returnValue($ping));
|
|
|
|
$options = array('commands' => $commands);
|
|
$client = $this->getMock('Predis\Client', null, array($connection, $options));
|
|
|
|
$this->assertEquals('PONG', $client->ping());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \Predis\Response\ServerException
|
|
* @expectedExceptionMessage Operation against a key holding the wrong kind of value
|
|
*/
|
|
public function testCallingRedisCommandThrowsExceptionOnServerError()
|
|
{
|
|
$expectedResponse = new Response\Error('ERR Operation against a key holding the wrong kind of value');
|
|
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('PING'))
|
|
->will($this->returnValue($expectedResponse));
|
|
|
|
$client = new Client($connection);
|
|
$client->ping();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testCallingRedisCommandReturnsErrorResponseOnRedisError()
|
|
{
|
|
$expectedResponse = new Response\Error('ERR Operation against a key holding the wrong kind of value');
|
|
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('PING'))
|
|
->will($this->returnValue($expectedResponse));
|
|
|
|
$client = new Client($connection, array('exceptions' => false));
|
|
$response = $client->ping();
|
|
|
|
$this->assertSame($response, $expectedResponse);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testRawCommand()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->at(0))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('SET', array('foo', 'bar')))
|
|
->will($this->returnValue(new Response\Status('OK')));
|
|
$connection
|
|
->expects($this->at(1))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('GET', array('foo')))
|
|
->will($this->returnValue('bar'));
|
|
$connection
|
|
->expects($this->at(2))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('PING'))
|
|
->will($this->returnValue('PONG'));
|
|
|
|
$client = new Client($connection);
|
|
|
|
$this->assertSame('OK', $client->executeRaw(array('SET', 'foo', 'bar')));
|
|
$this->assertSame('bar', $client->executeRaw(array('GET', 'foo')));
|
|
|
|
$error = true; // $error is always populated by reference.
|
|
$this->assertSame('PONG', $client->executeRaw(array('PING'), $error));
|
|
$this->assertFalse($error);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testRawCommandNeverAppliesPrefix()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->at(0))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('SET', array('foo', 'bar')))
|
|
->will($this->returnValue(new Response\Status('OK')));
|
|
$connection
|
|
->expects($this->at(1))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('GET', array('foo')))
|
|
->will($this->returnValue('bar'));
|
|
|
|
$client = new Client($connection, array('prefix' => 'predis:'));
|
|
|
|
$this->assertSame('OK', $client->executeRaw(array('SET', 'foo', 'bar')));
|
|
$this->assertSame('bar', $client->executeRaw(array('GET', 'foo')));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testRawCommandNeverThrowsExceptions()
|
|
{
|
|
$message = 'ERR Mock error response';
|
|
$response = new Response\Error($message);
|
|
|
|
$connection = $this->getMock('Predis\Connection\ConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('PING'))
|
|
->will($this->returnValue($response));
|
|
|
|
$client = new Client($connection, array('exceptions' => true));
|
|
|
|
$this->assertSame($message, $client->executeRaw(array('PING'), $error));
|
|
$this->assertTrue($error);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \Predis\ClientException
|
|
* @expectedExceptionMessage Command 'INVALIDCOMMAND' is not a registered Redis command.
|
|
*/
|
|
public function testThrowsExceptionOnNonRegisteredRedisCommand()
|
|
{
|
|
$client = new Client();
|
|
$client->invalidCommand();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetClientByMethodReturnsInstanceOfSubclass()
|
|
{
|
|
$nodes = array('tcp://host1?alias=node01', 'tcp://host2?alias=node02');
|
|
$client = $this->getMock('Predis\Client', array('dummy'), array($nodes, array('cluster' => 'predis')), 'SubclassedClient');
|
|
|
|
$this->assertInstanceOf('SubclassedClient', $client->getClientBy('alias', 'node02'));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetClientByMethodInvokesCallableInSecondArgumentAndReturnsItsReturnValue()
|
|
{
|
|
$test = $this;
|
|
$client = new Client(array('tcp://host1?alias=node01', 'tcp://host2?alias=node02'), array('cluster' => 'predis'));
|
|
|
|
$callable = $this->getMock('stdClass', array('__invoke'));
|
|
$callable
|
|
->expects($this->once())
|
|
->method('__invoke')
|
|
->with($this->callback(function ($clientNode) use ($test, $client) {
|
|
$test->isInstanceOf('Predis\ClientInterface', $clientNode);
|
|
$test->assertNotSame($client, $clientNode);
|
|
$test->assertInstanceOf('Predis\Connection\NodeConnectionInterface', $connection = $clientNode->getConnection());
|
|
$test->assertSame('node02', $connection->getParameters()->alias);
|
|
|
|
return true;
|
|
}))
|
|
->will($this->returnValue('value'));
|
|
|
|
$this->assertSame('value', $client->getClientBy('alias', 'node02', $callable));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetClientByMethodSupportsSelectingConnectionById()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
|
|
$aggregate = $this->getMockBuilder('Predis\Connection\AggregateConnectionInterface')
|
|
->setMethods(array('getConnectionById'))
|
|
->getMockForAbstractClass();
|
|
$aggregate
|
|
->expects($this->once())
|
|
->method('getConnectionById')
|
|
->with('127.0.0.1:6379')
|
|
->will($this->returnValue($connection));
|
|
|
|
$client = new Client($aggregate);
|
|
$nodeClient = $client->getClientBy('id', '127.0.0.1:6379');
|
|
|
|
$this->assertSame($connection, $nodeClient->getConnection());
|
|
$this->assertSame($client->getOptions(), $nodeClient->getOptions());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \InvalidArgumentException
|
|
* @expectedExceptionMessage Cannot find a connection by id matching `127.0.0.1:7000`
|
|
*/
|
|
public function testGetClientByMethodThrowsExceptionSelectingConnectionByUnknownId()
|
|
{
|
|
$aggregate = $this->getMock('Predis\Connection\AggregateConnectionInterface');
|
|
$aggregate
|
|
->expects($this->once())
|
|
->method('getConnectionById')
|
|
->with('127.0.0.1:7000')
|
|
->will($this->returnValue(null));
|
|
|
|
$client = new Client($aggregate);
|
|
$client->getClientBy('id', '127.0.0.1:7000');
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetClientByMethodSupportsSelectingConnectionByAlias()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
|
|
$aggregate = $this->getMockBuilder('Predis\Connection\AggregateConnectionInterface')
|
|
->setMethods(array('getConnectionByAlias'))
|
|
->getMockForAbstractClass();
|
|
$aggregate
|
|
->expects($this->once())
|
|
->method('getConnectionByAlias')
|
|
->with('myalias')
|
|
->will($this->returnValue($connection));
|
|
|
|
$client = new Client($aggregate);
|
|
$nodeClient = $client->getClientBy('alias', 'myalias');
|
|
|
|
$this->assertSame($connection, $nodeClient->getConnection());
|
|
$this->assertSame($client->getOptions(), $nodeClient->getOptions());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetClientByMethodSupportsSelectingConnectionByKey()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
|
|
$aggregate = $this->getMockBuilder('Predis\Connection\AggregateConnectionInterface')
|
|
->setMethods(array('getConnectionByKey'))
|
|
->getMockForAbstractClass();
|
|
$aggregate
|
|
->expects($this->once())
|
|
->method('getConnectionByKey')
|
|
->with('key:1')
|
|
->will($this->returnValue($connection));
|
|
|
|
$client = new Client($aggregate);
|
|
$nodeClient = $client->getClientBy('key', 'key:1');
|
|
|
|
$this->assertSame($connection, $nodeClient->getConnection());
|
|
$this->assertSame($client->getOptions(), $nodeClient->getOptions());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetClientByMethodSupportsSelectingConnectionBySlot()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
|
|
$aggregate = $this->getMockBuilder('Predis\Connection\AggregateConnectionInterface')
|
|
->setMethods(array('getConnectionBySlot'))
|
|
->getMockForAbstractClass();
|
|
$aggregate
|
|
->expects($this->once())
|
|
->method('getConnectionBySlot')
|
|
->with(5460)
|
|
->will($this->returnValue($connection));
|
|
|
|
$client = new Client($aggregate);
|
|
$nodeClient = $client->getClientBy('slot', 5460);
|
|
|
|
$this->assertSame($connection, $nodeClient->getConnection());
|
|
$this->assertSame($client->getOptions(), $nodeClient->getOptions());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetClientByMethodSupportsSelectingConnectionByRole()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
|
|
$aggregate = $this->getMockBuilder('Predis\Connection\AggregateConnectionInterface')
|
|
->setMethods(array('getConnectionByRole'))
|
|
->getMockForAbstractClass();
|
|
$aggregate
|
|
->expects($this->once())
|
|
->method('getConnectionByRole')
|
|
->with('master')
|
|
->will($this->returnValue($connection));
|
|
|
|
$client = new Client($aggregate);
|
|
$nodeClient = $client->getClientBy('role', 'master');
|
|
|
|
$this->assertSame($connection, $nodeClient->getConnection());
|
|
$this->assertSame($client->getOptions(), $nodeClient->getOptions());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetClientByMethodSupportsSelectingConnectionByCommand()
|
|
{
|
|
$command = \Predis\Command\RawCommand::create('GET', 'key');
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
|
|
$aggregate = $this->getMockBuilder('Predis\Connection\AggregateConnectionInterface')
|
|
->setMethods(array('getConnectionByCommand'))
|
|
->getMockForAbstractClass();
|
|
$aggregate
|
|
->expects($this->once())
|
|
->method('getConnectionByCommand')
|
|
->with($command)
|
|
->will($this->returnValue($connection));
|
|
|
|
$client = new Client($aggregate);
|
|
$nodeClient = $client->getClientBy('command', $command);
|
|
|
|
$this->assertSame($connection, $nodeClient->getConnection());
|
|
$this->assertSame($client->getOptions(), $nodeClient->getOptions());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \InvalidArgumentException
|
|
* @expectedExceptionMessage Invalid selector type: `unknown`
|
|
*/
|
|
public function testGetClientByMethodThrowsExceptionWhenSelectingConnectionByUnknownType()
|
|
{
|
|
$client = new Client('tcp://127.0.0.1?alias=node01');
|
|
|
|
$client->getClientBy('unknown', 'test');
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \InvalidArgumentException
|
|
* @expectedExceptionMessage Selecting connection by id is not supported by Predis\Connection\StreamConnection
|
|
*/
|
|
public function testGetClientByMethodThrowsExceptionWhenConnectionDoesNotSupportSelectorType()
|
|
{
|
|
$client = new Client('tcp://127.0.0.1?alias=node01');
|
|
|
|
$client->getClientBy('id', 'node01');
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testPipelineWithoutArgumentsReturnsPipeline()
|
|
{
|
|
$client = new Client();
|
|
|
|
$this->assertInstanceOf('Predis\Pipeline\Pipeline', $client->pipeline());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testPipelineWithArrayReturnsPipeline()
|
|
{
|
|
$client = new Client();
|
|
|
|
$this->assertInstanceOf('Predis\Pipeline\Pipeline', $client->pipeline(array()));
|
|
$this->assertInstanceOf('Predis\Pipeline\Atomic', $client->pipeline(array('atomic' => true)));
|
|
$this->assertInstanceOf('Predis\Pipeline\FireAndForget', $client->pipeline(array('fire-and-forget' => true)));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testPipelineWithCallableExecutesPipeline()
|
|
{
|
|
$callable = $this->getMock('stdClass', array('__invoke'));
|
|
$callable
|
|
->expects($this->once())
|
|
->method('__invoke')
|
|
->with($this->isInstanceOf('Predis\Pipeline\Pipeline'));
|
|
|
|
$client = new Client();
|
|
$client->pipeline($callable);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testPubSubLoopWithoutArgumentsReturnsPubSubConsumer()
|
|
{
|
|
$client = new Client();
|
|
|
|
$this->assertInstanceOf('Predis\PubSub\Consumer', $client->pubSubLoop());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testPubSubLoopWithArrayReturnsPubSubConsumerWithOptions()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
$options = array('subscribe' => 'channel');
|
|
|
|
$client = new Client($connection);
|
|
|
|
$this->assertInstanceOf('Predis\PubSub\Consumer', $pubsub = $client->pubSubLoop($options));
|
|
|
|
$reflection = new \ReflectionProperty($pubsub, 'options');
|
|
$reflection->setAccessible(true);
|
|
|
|
$this->assertSame($options, $reflection->getValue($pubsub));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testPubSubLoopWithArrayAndCallableExecutesPubSub()
|
|
{
|
|
// NOTE: we use a subscribe count of 0 in the message payload to trick
|
|
// the context and forcing it to be closed since there are no more
|
|
// active subscriptions.
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('read')
|
|
->will($this->returnValue(array('subscribe', 'channel', 0)));
|
|
|
|
$callable = $this->getMock('stdClass', array('__invoke'));
|
|
$callable
|
|
->expects($this->once())
|
|
->method('__invoke');
|
|
|
|
$client = new Client($connection);
|
|
$this->assertNull($client->pubSubLoop(array('subscribe' => 'channel'), $callable));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testPubSubLoopWithCallableReturningFalseStopsPubSubConsumer()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
$connection
|
|
->expects($this->at(1))
|
|
->method('read')
|
|
->will($this->returnValue(array('subscribe', 'channel', 1)));
|
|
$connection
|
|
->expects($this->at(2))
|
|
->method('writeRequest')
|
|
->with($this->isRedisCommand('UNSUBSCRIBE'));
|
|
$connection
|
|
->expects($this->at(3))
|
|
->method('read')
|
|
->will($this->returnValue(array('unsubscribe', 'channel', 0)));
|
|
|
|
$callable = $this->getMock('stdClass', array('__invoke'));
|
|
$callable
|
|
->expects($this->at(0))
|
|
->method('__invoke')
|
|
->will($this->returnValue(false));
|
|
|
|
$client = new Client($connection);
|
|
|
|
$this->assertNull($client->pubSubLoop(array('subscribe' => 'channel'), $callable));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testTransactionWithoutArgumentsReturnsMultiExec()
|
|
{
|
|
$client = new Client();
|
|
|
|
$this->assertInstanceOf('Predis\Transaction\MultiExec', $client->transaction());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testTransactionWithArrayReturnsMultiExecTransactionWithOptions()
|
|
{
|
|
$options = array('cas' => true, 'retry' => 3);
|
|
|
|
$client = new Client();
|
|
|
|
$this->assertInstanceOf('Predis\Transaction\MultiExec', $tx = $client->transaction($options));
|
|
|
|
// I hate this part but reflection is the easiest way in this case.
|
|
$property = new \ReflectionProperty($tx, 'modeCAS');
|
|
$property->setAccessible(true);
|
|
$this->assertSame($options['cas'], $property->getValue($tx));
|
|
|
|
$property = new \ReflectionProperty($tx, 'attempts');
|
|
$property->setAccessible(true);
|
|
$this->assertSame($options['retry'], $property->getValue($tx));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testTransactionWithArrayAndCallableExecutesMultiExec()
|
|
{
|
|
// We use CAS here as we don't care about the actual MULTI/EXEC context.
|
|
$options = array('cas' => true, 'retry' => 3);
|
|
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
$connection
|
|
->expects($this->once())
|
|
->method('executeCommand')
|
|
->will($this->returnValue(new Response\Status('QUEUED')));
|
|
|
|
$callable = $this->getMock('stdClass', array('__invoke'));
|
|
$callable
|
|
->expects($this->once())
|
|
->method('__invoke')
|
|
->will($this->returnCallback(function ($tx) { $tx->ping(); }));
|
|
|
|
$client = new Client($connection);
|
|
$client->transaction($options, $callable);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMonitorReturnsMonitorConsumer()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
$client = new Client($connection);
|
|
|
|
$this->assertInstanceOf('Predis\Monitor\Consumer', $monitor = $client->monitor());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testClientResendScriptCommandUsingEvalOnNoScriptErrors()
|
|
{
|
|
$command = $this->getMockForAbstractClass('Predis\Command\ScriptCommand', array(), '', true, true, true, array('parseResponse'));
|
|
$command
|
|
->expects($this->once())
|
|
->method('getScript')
|
|
->will($this->returnValue('return redis.call(\'exists\', KEYS[1])'));
|
|
$command
|
|
->expects($this->once())
|
|
->method('parseResponse')
|
|
->with('OK')
|
|
->will($this->returnValue(true));
|
|
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
$connection
|
|
->expects($this->at(0))
|
|
->method('executeCommand')
|
|
->with($command)
|
|
->will($this->returnValue(new Response\Error('NOSCRIPT')));
|
|
$connection
|
|
->expects($this->at(1))
|
|
->method('executeCommand')
|
|
->with($this->isRedisCommand('EVAL'))
|
|
->will($this->returnValue('OK'));
|
|
|
|
$client = new Client($connection);
|
|
|
|
$this->assertTrue($client->executeCommand($command));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testGetIteratorWithTraversableConnections()
|
|
{
|
|
$connection1 = $this->getMockConnection('tcp://127.0.0.1:6381');
|
|
$connection2 = $this->getMockConnection('tcp://127.0.0.1:6382');
|
|
$connection3 = $this->getMockConnection('tcp://127.0.0.1:6383');
|
|
|
|
$aggregate = new \Predis\Connection\Cluster\PredisCluster();
|
|
|
|
$aggregate->add($connection1);
|
|
$aggregate->add($connection2);
|
|
$aggregate->add($connection3);
|
|
|
|
$client = new Client($aggregate);
|
|
|
|
$iterator = $client->getIterator();
|
|
|
|
$this->assertInstanceOf('\Predis\Client', $nodeClient = $iterator->current());
|
|
$this->assertSame($connection1, $nodeClient->getConnection());
|
|
$this->assertSame('127.0.0.1:6381', $iterator->key());
|
|
|
|
$iterator->next();
|
|
|
|
$this->assertInstanceOf('\Predis\Client', $nodeClient = $iterator->current());
|
|
$this->assertSame($connection2, $nodeClient->getConnection());
|
|
$this->assertSame('127.0.0.1:6382', $iterator->key());
|
|
|
|
$iterator->next();
|
|
|
|
$this->assertInstanceOf('\Predis\Client', $nodeClient = $iterator->current());
|
|
$this->assertSame($connection3, $nodeClient->getConnection());
|
|
$this->assertSame('127.0.0.1:6383', $iterator->key());
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
* @expectedException \Predis\ClientException
|
|
* @expectedExceptionMessage The underlying connection is not traversable
|
|
*/
|
|
public function testGetIteratorWithNonTraversableConnectionThrowsException()
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
|
|
$client = new Client($connection);
|
|
|
|
$client->getIterator();
|
|
}
|
|
|
|
// ******************************************************************** //
|
|
// ---- HELPER METHODS ------------------------------------------------ //
|
|
// ******************************************************************** //
|
|
|
|
/**
|
|
* Returns an URI string representation of the specified connection parameters.
|
|
*
|
|
* @param array $parameters Array of connection parameters.
|
|
*
|
|
* @return string URI string.
|
|
*/
|
|
protected function getParametersString(array $parameters)
|
|
{
|
|
$defaults = $this->getDefaultParametersArray();
|
|
|
|
$scheme = isset($parameters['scheme']) ? $parameters['scheme'] : $defaults['scheme'];
|
|
$host = isset($parameters['host']) ? $parameters['host'] : $defaults['host'];
|
|
$port = isset($parameters['port']) ? $parameters['port'] : $defaults['port'];
|
|
|
|
unset($parameters['scheme'], $parameters['host'], $parameters['port']);
|
|
$uriString = "$scheme://$host:$port/?";
|
|
|
|
foreach ($parameters as $k => $v) {
|
|
$uriString .= "$k=$v&";
|
|
}
|
|
|
|
return $uriString;
|
|
}
|
|
|
|
/**
|
|
* Returns a mock callable simulating an aggregate connection initializer.
|
|
*
|
|
* @param mixed $parameters Expected connection parameters
|
|
*
|
|
* @return callable
|
|
*/
|
|
protected function getAggregateInitializer($parameters)
|
|
{
|
|
$connection = $this->getMock('Predis\Connection\AggregateConnectionInterface');
|
|
|
|
$callable = $this->getMock('stdClass', array('__invoke'));
|
|
$callable
|
|
->expects($this->once())
|
|
->method('__invoke')
|
|
->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'), $parameters)
|
|
->will($this->returnValue($connection));
|
|
|
|
return $callable;
|
|
}
|
|
}
|