ClientTest.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. <?php
  2. /*
  3. * This file is part of the Predis package.
  4. *
  5. * (c) Daniele Alessandri <suppakilla@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Predis;
  11. use PredisTestCase;
  12. use Predis\Connection;
  13. use Predis\Profile;
  14. use Predis\Response;
  15. /**
  16. *
  17. */
  18. class ClientTest extends PredisTestCase
  19. {
  20. /**
  21. * @group disconnected
  22. */
  23. public function testConstructorWithoutArguments()
  24. {
  25. $client = new Client();
  26. $connection = $client->getConnection();
  27. $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $connection);
  28. $parameters = $connection->getParameters();
  29. $this->assertSame($parameters->host, '127.0.0.1');
  30. $this->assertSame($parameters->port, 6379);
  31. $options = $client->getOptions();
  32. $this->assertSame($options->profile->getVersion(), Profile\Factory::getDefault()->getVersion());
  33. $this->assertFalse($client->isConnected());
  34. }
  35. /**
  36. * @group disconnected
  37. */
  38. public function testConstructorWithNullArgument()
  39. {
  40. $client = new Client(null);
  41. $connection = $client->getConnection();
  42. $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $connection);
  43. $parameters = $connection->getParameters();
  44. $this->assertSame($parameters->host, '127.0.0.1');
  45. $this->assertSame($parameters->port, 6379);
  46. $options = $client->getOptions();
  47. $this->assertSame($options->profile->getVersion(), Profile\Factory::getDefault()->getVersion());
  48. $this->assertFalse($client->isConnected());
  49. }
  50. /**
  51. * @group disconnected
  52. */
  53. public function testConstructorWithNullAndNullArguments()
  54. {
  55. $client = new Client(null, null);
  56. $connection = $client->getConnection();
  57. $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $connection);
  58. $parameters = $connection->getParameters();
  59. $this->assertSame($parameters->host, '127.0.0.1');
  60. $this->assertSame($parameters->port, 6379);
  61. $options = $client->getOptions();
  62. $this->assertSame($options->profile->getVersion(), Profile\Factory::getDefault()->getVersion());
  63. $this->assertFalse($client->isConnected());
  64. }
  65. /**
  66. * @group disconnected
  67. */
  68. public function testConstructorWithArrayArgument()
  69. {
  70. $client = new Client($arg1 = array('host' => 'localhost', 'port' => 7000));
  71. $parameters = $client->getConnection()->getParameters();
  72. $this->assertSame($parameters->host, $arg1['host']);
  73. $this->assertSame($parameters->port, $arg1['port']);
  74. }
  75. /**
  76. * @group disconnected
  77. */
  78. public function testConstructorWithArrayOfArrayArgument()
  79. {
  80. $arg1 = array(
  81. array('host' => 'localhost', 'port' => 7000),
  82. array('host' => 'localhost', 'port' => 7001),
  83. );
  84. $client = new Client($arg1);
  85. $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $client->getConnection());
  86. }
  87. /**
  88. * @group disconnected
  89. */
  90. public function testConstructorWithStringArgument()
  91. {
  92. $client = new Client('tcp://localhost:7000');
  93. $parameters = $client->getConnection()->getParameters();
  94. $this->assertSame($parameters->host, 'localhost');
  95. $this->assertSame($parameters->port, 7000);
  96. }
  97. /**
  98. * @group disconnected
  99. */
  100. public function testConstructorWithArrayOfStringArgument()
  101. {
  102. $client = new Client($arg1 = array('tcp://localhost:7000', 'tcp://localhost:7001'));
  103. $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $client->getConnection());
  104. }
  105. /**
  106. * @group disconnected
  107. */
  108. public function testConstructorWithArrayOfConnectionsArgument()
  109. {
  110. $connection1 = $this->getMock('Predis\Connection\SingleConnectionInterface');
  111. $connection2 = $this->getMock('Predis\Connection\SingleConnectionInterface');
  112. $client = new Client(array($connection1, $connection2));
  113. $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $cluster = $client->getConnection());
  114. $this->assertSame($connection1, $cluster->getConnectionById(0));
  115. $this->assertSame($connection2, $cluster->getConnectionById(1));
  116. }
  117. /**
  118. * @group disconnected
  119. */
  120. public function testConstructorWithConnectionArgument()
  121. {
  122. $factory = new Connection\Factory();
  123. $connection = $factory->create('tcp://localhost:7000');
  124. $client = new Client($connection);
  125. $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $client->getConnection());
  126. $this->assertSame($connection, $client->getConnection());
  127. $parameters = $client->getConnection()->getParameters();
  128. $this->assertSame($parameters->host, 'localhost');
  129. $this->assertSame($parameters->port, 7000);
  130. }
  131. /**
  132. * @group disconnected
  133. */
  134. public function testConstructorWithClusterArgument()
  135. {
  136. $cluster = new Connection\PredisCluster();
  137. $factory = new Connection\Factory();
  138. $factory->aggregate($cluster, array('tcp://localhost:7000', 'tcp://localhost:7001'));
  139. $client = new Client($cluster);
  140. $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $client->getConnection());
  141. $this->assertSame($cluster, $client->getConnection());
  142. }
  143. /**
  144. * @group disconnected
  145. */
  146. public function testConstructorWithReplicationArgument()
  147. {
  148. $replication = new Connection\MasterSlaveReplication();
  149. $factory = new Connection\Factory();
  150. $factory->aggregate($replication, array('tcp://host1?alias=master', 'tcp://host2?alias=slave'));
  151. $client = new Client($replication);
  152. $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $client->getConnection());
  153. $this->assertSame($replication, $client->getConnection());
  154. }
  155. /**
  156. * @group disconnected
  157. */
  158. public function testConstructorWithCallableArgument()
  159. {
  160. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  161. $callable = $this->getMock('stdClass', array('__invoke'));
  162. $callable->expects($this->once())
  163. ->method('__invoke')
  164. ->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'))
  165. ->will($this->returnValue($connection));
  166. $client = new Client($callable);
  167. $this->assertSame($connection, $client->getConnection());
  168. }
  169. /**
  170. * @group disconnected
  171. * @expectedException UnexpectedValueException
  172. * @expectedExceptionMessage The callable connection initializer returned an invalid type
  173. */
  174. public function testConstructorWithCallableConnectionInitializerThrowsExceptionOnInvalidReturnType()
  175. {
  176. $wrongType = $this->getMock('stdClass');
  177. $callable = $this->getMock('stdClass', array('__invoke'));
  178. $callable->expects($this->once())
  179. ->method('__invoke')
  180. ->with($this->isInstanceOf('Predis\Configuration\OptionsInterface'))
  181. ->will($this->returnValue($wrongType));
  182. $client = new Client($callable);
  183. }
  184. /**
  185. * @group disconnected
  186. */
  187. public function testConstructorWithNullAndArrayArgument()
  188. {
  189. $factory = $this->getMock('Predis\Connection\FactoryInterface');
  190. $arg2 = array('profile' => '2.0', 'prefix' => 'prefix:', 'connections' => $factory);
  191. $client = new Client(null, $arg2);
  192. $profile = $client->getProfile();
  193. $this->assertSame($profile->getVersion(), Profile\Factory::get('2.0')->getVersion());
  194. $this->assertInstanceOf('Predis\Command\Processor\KeyPrefixProcessor', $profile->getProcessor());
  195. $this->assertSame('prefix:', $profile->getProcessor()->getPrefix());
  196. }
  197. /**
  198. * @group disconnected
  199. */
  200. public function testConstructorWithArrayAndOptionReplication()
  201. {
  202. $arg1 = array('tcp://host1?alias=master', 'tcp://host2?alias=slave');
  203. $arg2 = array('replication' => true);
  204. $client = new Client($arg1, $arg2);
  205. $this->assertInstanceOf('Predis\Connection\ReplicationConnectionInterface', $connection = $client->getConnection());
  206. $this->assertSame('host1', $connection->getConnectionById('master')->getParameters()->host);
  207. $this->assertSame('host2', $connection->getConnectionById('slave')->getParameters()->host);
  208. }
  209. /**
  210. * @group disconnected
  211. */
  212. public function testConstructorWithArrayAndOptionAggregate()
  213. {
  214. $arg1 = array('tcp://host1', 'tcp://host2');
  215. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  216. $fnaggregate = $this->getMock('stdClass', array('__invoke'));
  217. $fnaggregate->expects($this->once())
  218. ->method('__invoke')
  219. ->with($arg1)
  220. ->will($this->returnValue($connection));
  221. $fncluster = $this->getMock('stdClass', array('__invoke'));
  222. $fncluster->expects($this->never())->method('__invoke');
  223. $fnreplication = $this->getMock('stdClass', array('__invoke'));
  224. $fnreplication->expects($this->never())->method('__invoke');
  225. $arg2 = array(
  226. 'aggregate' => function () use ($fnaggregate) { return $fnaggregate; },
  227. 'cluster' => function () use ($fncluster) { return $fncluster; },
  228. 'replication' => function () use ($fnreplication) { return $fncluster; },
  229. );
  230. $client = new Client($arg1, $arg2);
  231. $this->assertSame($connection, $client->getConnection());
  232. }
  233. /**
  234. * @group disconnected
  235. * @expectedException UnexpectedValueException
  236. * @expectedExceptionMessage The callable connection initializer returned an invalid type
  237. */
  238. public function testConstructorWithArrayAndOptionAggregateThrowsExceptionOnInvalidReturnType()
  239. {
  240. $arg1 = array('tcp://host1', 'tcp://host2');
  241. $fnaggregate = $this->getMock('stdClass', array('__invoke'));
  242. $fnaggregate->expects($this->once())
  243. ->method('__invoke')
  244. ->with($arg1)
  245. ->will($this->returnValue(false));
  246. $arg2 = array('aggregate' => function () use ($fnaggregate) { return $fnaggregate; });
  247. $client = new Client($arg1, $arg2);
  248. }
  249. /**
  250. * @group disconnected
  251. */
  252. public function testConnectAndDisconnect()
  253. {
  254. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  255. $connection->expects($this->once())->method('connect');
  256. $connection->expects($this->once())->method('disconnect');
  257. $client = new Client($connection);
  258. $client->connect();
  259. $client->disconnect();
  260. }
  261. /**
  262. * @group disconnected
  263. */
  264. public function testIsConnectedChecksConnectionState()
  265. {
  266. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  267. $connection->expects($this->once())->method('isConnected');
  268. $client = new Client($connection);
  269. $client->isConnected();
  270. }
  271. /**
  272. * @group disconnected
  273. */
  274. public function testQuitIsAliasForDisconnect()
  275. {
  276. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  277. $connection->expects($this->once())->method('disconnect');
  278. $client = new Client($connection);
  279. $client->quit();
  280. }
  281. /**
  282. * @group disconnected
  283. */
  284. public function testCreatesNewCommandUsingSpecifiedProfile()
  285. {
  286. $ping = Profile\Factory::getDefault()->createCommand('ping', array());
  287. $profile = $this->getMock('Predis\Profile\ProfileInterface');
  288. $profile->expects($this->once())
  289. ->method('createCommand')
  290. ->with('ping', array())
  291. ->will($this->returnValue($ping));
  292. $client = new Client(null, array('profile' => $profile));
  293. $this->assertSame($ping, $client->createCommand('ping', array()));
  294. }
  295. /**
  296. * @group disconnected
  297. */
  298. public function testExecuteCommandReturnsParsedResponses()
  299. {
  300. $profile = Profile\Factory::getDefault();
  301. $ping = $profile->createCommand('ping', array());
  302. $hgetall = $profile->createCommand('hgetall', array('metavars', 'foo', 'hoge'));
  303. $connection= $this->getMock('Predis\Connection\ConnectionInterface');
  304. $connection->expects($this->at(0))
  305. ->method('executeCommand')
  306. ->with($ping)
  307. ->will($this->returnValue(new Response\Status('PONG')));
  308. $connection->expects($this->at(1))
  309. ->method('executeCommand')
  310. ->with($hgetall)
  311. ->will($this->returnValue(array('foo', 'bar', 'hoge', 'piyo')));
  312. $client = new Client($connection);
  313. $this->assertEquals('PONG', $client->executeCommand($ping));
  314. $this->assertSame(array('foo' => 'bar', 'hoge' => 'piyo'), $client->executeCommand($hgetall));
  315. }
  316. /**
  317. * @group disconnected
  318. * @expectedException Predis\Response\ServerException
  319. * @expectedExceptionMessage Operation against a key holding the wrong kind of value
  320. */
  321. public function testExecuteCommandThrowsExceptionOnRedisError()
  322. {
  323. $ping = Profile\Factory::getDefault()->createCommand('ping', array());
  324. $expectedResponse = new Response\Error('ERR Operation against a key holding the wrong kind of value');
  325. $connection= $this->getMock('Predis\Connection\ConnectionInterface');
  326. $connection->expects($this->once())
  327. ->method('executeCommand')
  328. ->will($this->returnValue($expectedResponse));
  329. $client = new Client($connection);
  330. $client->executeCommand($ping);
  331. }
  332. /**
  333. * @group disconnected
  334. */
  335. public function testExecuteCommandReturnsErrorResponseOnRedisError()
  336. {
  337. $ping = Profile\Factory::getDefault()->createCommand('ping', array());
  338. $expectedResponse = new Response\Error('ERR Operation against a key holding the wrong kind of value');
  339. $connection= $this->getMock('Predis\Connection\ConnectionInterface');
  340. $connection->expects($this->once())
  341. ->method('executeCommand')
  342. ->will($this->returnValue($expectedResponse));
  343. $client = new Client($connection, array('exceptions' => false));
  344. $response = $client->executeCommand($ping);
  345. $this->assertSame($response, $expectedResponse);
  346. }
  347. /**
  348. * @group disconnected
  349. */
  350. public function testCallingRedisCommandExecutesInstanceOfCommand()
  351. {
  352. $ping = Profile\Factory::getDefault()->createCommand('ping', array());
  353. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  354. $connection->expects($this->once())
  355. ->method('executeCommand')
  356. ->with($this->isInstanceOf('Predis\Command\ConnectionPing'))
  357. ->will($this->returnValue('PONG'));
  358. $profile = $this->getMock('Predis\Profile\ProfileInterface');
  359. $profile->expects($this->once())
  360. ->method('createCommand')
  361. ->with('ping', array())
  362. ->will($this->returnValue($ping));
  363. $options = array('profile' => $profile);
  364. $client = $this->getMock('Predis\Client', null, array($connection, $options));
  365. $this->assertEquals('PONG', $client->ping());
  366. }
  367. /**
  368. * @group disconnected
  369. * @expectedException Predis\Response\ServerException
  370. * @expectedExceptionMessage Operation against a key holding the wrong kind of value
  371. */
  372. public function testCallingRedisCommandThrowsExceptionOnServerError()
  373. {
  374. $expectedResponse = new Response\Error('ERR Operation against a key holding the wrong kind of value');
  375. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  376. $connection->expects($this->once())
  377. ->method('executeCommand')
  378. ->with($this->isInstanceOf('Predis\Command\ConnectionPing'))
  379. ->will($this->returnValue($expectedResponse));
  380. $client = new Client($connection);
  381. $client->ping();
  382. }
  383. /**
  384. * @group disconnected
  385. */
  386. public function testCallingRedisCommandReturnsErrorResponseOnRedisError()
  387. {
  388. $expectedResponse = new Response\Error('ERR Operation against a key holding the wrong kind of value');
  389. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  390. $connection->expects($this->once())
  391. ->method('executeCommand')
  392. ->with($this->isInstanceOf('Predis\Command\ConnectionPing'))
  393. ->will($this->returnValue($expectedResponse));
  394. $client = new Client($connection, array('exceptions' => false));
  395. $response = $client->ping();
  396. $this->assertSame($response, $expectedResponse);
  397. }
  398. /**
  399. * @group disconnected
  400. */
  401. public function testRawCommand()
  402. {
  403. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  404. $connection->expects($this->at(0))
  405. ->method('executeCommand')
  406. ->with($this->isRedisCommand('SET', array('foo', 'bar')))
  407. ->will($this->returnValue(new Response\Status('OK')));
  408. $connection->expects($this->at(1))
  409. ->method('executeCommand')
  410. ->with($this->isRedisCommand('GET', array('foo')))
  411. ->will($this->returnValue('bar'));
  412. $connection->expects($this->at(2))
  413. ->method('executeCommand')
  414. ->with($this->isRedisCommand('PING'))
  415. ->will($this->returnValue('PONG'));
  416. $client = new Client($connection);
  417. $this->assertSame('OK', $client->executeRaw(array('SET', 'foo', 'bar')));
  418. $this->assertSame('bar', $client->executeRaw(array('GET', 'foo')));
  419. $error = true; // $error is always populated by reference.
  420. $this->assertSame('PONG', $client->executeRaw(array('PING'), $error));
  421. $this->assertFalse($error);
  422. }
  423. /**
  424. * @group disconnected
  425. */
  426. public function testRawCommandNeverAppliesPrefix()
  427. {
  428. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  429. $connection->expects($this->at(0))
  430. ->method('executeCommand')
  431. ->with($this->isRedisCommand('SET', array('foo', 'bar')))
  432. ->will($this->returnValue(new Response\Status('OK')));
  433. $connection->expects($this->at(1))
  434. ->method('executeCommand')
  435. ->with($this->isRedisCommand('GET', array('foo')))
  436. ->will($this->returnValue('bar'));
  437. $client = new Client($connection, array('prefix' => 'predis:'));
  438. $this->assertSame('OK', $client->executeRaw(array('SET', 'foo', 'bar')));
  439. $this->assertSame('bar', $client->executeRaw(array('GET', 'foo')));
  440. }
  441. /**
  442. * @group disconnected
  443. */
  444. public function testRawCommandNeverThrowsExceptions()
  445. {
  446. $message = 'ERR Mock error response';
  447. $response = new Response\Error($message);
  448. $connection = $this->getMock('Predis\Connection\ConnectionInterface');
  449. $connection->expects($this->once())
  450. ->method('executeCommand')
  451. ->with($this->isRedisCommand('PING'))
  452. ->will($this->returnValue($response));
  453. $client = new Client($connection, array('exceptions' => true));
  454. $this->assertSame($message, $client->executeRaw(array('PING'), $error));
  455. $this->assertTrue($error);
  456. }
  457. /**
  458. * @group disconnected
  459. * @expectedException Predis\ClientException
  460. * @expectedExceptionMessage 'INVALIDCOMMAND' is not a registered Redis command
  461. */
  462. public function testThrowsExceptionOnNonRegisteredRedisCommand()
  463. {
  464. $client = new Client();
  465. $client->invalidCommand();
  466. }
  467. /**
  468. * @group disconnected
  469. */
  470. public function testGetConnectionFromAggregateConnectionWithAlias()
  471. {
  472. $client = new Client(array('tcp://host1?alias=node01', 'tcp://host2?alias=node02'));
  473. $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $cluster = $client->getConnection());
  474. $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $node01 = $client->getConnectionById('node01'));
  475. $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $node02 = $client->getConnectionById('node02'));
  476. $this->assertSame('host1', $node01->getParameters()->host);
  477. $this->assertSame('host2', $node02->getParameters()->host);
  478. }
  479. /**
  480. * @group disconnected
  481. * @expectedException Predis\NotSupportedException
  482. * @expectedExceptionMessage Retrieving connections by ID is supported only when using aggregate connections
  483. */
  484. public function testGetConnectionByIdWorksOnlyWithAggregateConnections()
  485. {
  486. $client = new Client();
  487. $client->getConnectionById('node01');
  488. }
  489. /**
  490. * @group disconnected
  491. */
  492. public function testCreateClientWithConnectionFromAggregateConnection()
  493. {
  494. $client = new Client(array('tcp://host1?alias=node01', 'tcp://host2?alias=node02'), array('prefix' => 'pfx:'));
  495. $this->assertInstanceOf('Predis\Connection\ClusterConnectionInterface', $cluster = $client->getConnection());
  496. $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $node01 = $client->getConnectionById('node01'));
  497. $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $node02 = $client->getConnectionById('node02'));
  498. $clientNode02 = $client->getClientFor('node02');
  499. $this->assertInstanceOf('Predis\Client', $clientNode02);
  500. $this->assertSame($node02, $clientNode02->getConnection());
  501. $this->assertSame($client->getOptions(), $clientNode02->getOptions());
  502. }
  503. /**
  504. * @group disconnected
  505. */
  506. public function testGetClientForReturnsInstanceOfSubclass()
  507. {
  508. $nodes = array('tcp://host1?alias=node01', 'tcp://host2?alias=node02');
  509. $client = $this->getMock('Predis\Client', array('dummy'), array($nodes), 'SubclassedClient');
  510. $this->assertInstanceOf('SubclassedClient', $client->getClientFor('node02'));
  511. }
  512. /**
  513. * @group disconnected
  514. */
  515. public function testPipelineWithoutArgumentsReturnsPipeline()
  516. {
  517. $client = new Client();
  518. $this->assertInstanceOf('Predis\Pipeline\Pipeline', $client->pipeline());
  519. }
  520. /**
  521. * @group disconnected
  522. */
  523. public function testPipelineWithArrayReturnsPipeline()
  524. {
  525. $client = new Client();
  526. $this->assertInstanceOf('Predis\Pipeline\Pipeline', $client->pipeline(array()));
  527. $this->assertInstanceOf('Predis\Pipeline\Atomic', $client->pipeline(array('atomic' => true)));
  528. $this->assertInstanceOf('Predis\Pipeline\FireAndForget', $client->pipeline(array('fire-and-forget' => true)));
  529. }
  530. /**
  531. * @group disconnected
  532. */
  533. public function testPipelineWithCallableExecutesPipeline()
  534. {
  535. $callable = $this->getMock('stdClass', array('__invoke'));
  536. $callable->expects($this->once())
  537. ->method('__invoke')
  538. ->with($this->isInstanceOf('Predis\Pipeline\Pipeline'));
  539. $client = new Client();
  540. $client->pipeline($callable);
  541. }
  542. /**
  543. * @group disconnected
  544. */
  545. public function testPubSubLoopWithoutArgumentsReturnsPubSubConsumer()
  546. {
  547. $client = new Client();
  548. $this->assertInstanceOf('Predis\PubSub\Consumer', $client->pubSubLoop());
  549. }
  550. /**
  551. * @group disconnected
  552. */
  553. public function testPubSubLoopWithArrayReturnsPubSubConsumerWithOptions()
  554. {
  555. $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
  556. $options = array('subscribe' => 'channel');
  557. $client = new Client($connection);
  558. $this->assertInstanceOf('Predis\PubSub\Consumer', $pubsub = $client->pubSubLoop($options));
  559. $reflection = new \ReflectionProperty($pubsub, 'options');
  560. $reflection->setAccessible(true);
  561. $this->assertSame($options, $reflection->getValue($pubsub));
  562. }
  563. /**
  564. * @group disconnected
  565. */
  566. public function testPubSubLoopWithArrayAndCallableExecutesPubSub()
  567. {
  568. // NOTE: we use a subscribe count of 0 in the fake message to trick
  569. // the context and to make it think that it can be closed
  570. // since there are no more subscriptions active.
  571. $message = array('subscribe', 'channel', 0);
  572. $options = array('subscribe' => 'channel');
  573. $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
  574. $connection->expects($this->once())
  575. ->method('read')
  576. ->will($this->returnValue($message));
  577. $callable = $this->getMock('stdClass', array('__invoke'));
  578. $callable->expects($this->once())
  579. ->method('__invoke');
  580. $client = new Client($connection);
  581. $client->pubSubLoop($options, $callable);
  582. }
  583. /**
  584. * @group disconnected
  585. */
  586. public function testTransactionWithoutArgumentsReturnsMultiExec()
  587. {
  588. $client = new Client();
  589. $this->assertInstanceOf('Predis\Transaction\MultiExec', $client->transaction());
  590. }
  591. /**
  592. * @group disconnected
  593. * @todo I hate this test but reflection is the easiest way in this case.
  594. */
  595. public function testTransactionWithArrayReturnsTransactionMultiExecWithOptions()
  596. {
  597. $options = array('cas' => true, 'retry' => 3);
  598. $client = new Client();
  599. $this->assertInstanceOf('Predis\Transaction\MultiExec', $tx = $client->transaction($options));
  600. $property = new \ReflectionProperty($tx, 'modeCAS');
  601. $property->setAccessible(true);
  602. $this->assertSame($options['cas'], $property->getValue($tx));
  603. $property = new \ReflectionProperty($tx, 'attempts');
  604. $property->setAccessible(true);
  605. $this->assertSame($options['retry'], $property->getValue($tx));
  606. }
  607. /**
  608. * @group disconnected
  609. */
  610. public function testTransactionWithArrayAndCallableExecutesMultiExec()
  611. {
  612. // NOTE: we use CAS since testing the actual MULTI/EXEC context
  613. // here is not the point.
  614. $options = array('cas' => true, 'retry' => 3);
  615. $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
  616. $connection->expects($this->once())
  617. ->method('executeCommand')
  618. ->will($this->returnValue(new Response\Status('QUEUED')));
  619. $txCallback = function ($tx) {
  620. $tx->ping();
  621. };
  622. $callable = $this->getMock('stdClass', array('__invoke'));
  623. $callable->expects($this->once())
  624. ->method('__invoke')
  625. ->will($this->returnCallback($txCallback));
  626. $client = new Client($connection);
  627. $client->transaction($options, $callable);
  628. }
  629. /**
  630. * @group disconnected
  631. */
  632. public function testMonitorReturnsMonitorConsumer()
  633. {
  634. $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
  635. $client = new Client($connection);
  636. $this->assertInstanceOf('Predis\Monitor\Consumer', $monitor = $client->monitor());
  637. }
  638. /**
  639. * @group disconnected
  640. */
  641. public function testClientResendScriptCommandUsingEvalOnNoScriptErrors()
  642. {
  643. $command = $this->getMockForAbstractClass('Predis\Command\ScriptCommand', array(), '', true, true, true, array('parseResponse'));
  644. $command->expects($this->once())
  645. ->method('getScript')
  646. ->will($this->returnValue('return redis.call(\'exists\', KEYS[1])'));
  647. $command->expects($this->once())
  648. ->method('parseResponse')
  649. ->with('OK')
  650. ->will($this->returnValue(true));
  651. $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
  652. $connection->expects($this->at(0))
  653. ->method('executeCommand')
  654. ->with($command)
  655. ->will($this->returnValue(new Response\Error('NOSCRIPT')));
  656. $connection->expects($this->at(1))
  657. ->method('executeCommand')
  658. ->with($this->isInstanceOf('Predis\Command\ServerEval'))
  659. ->will($this->returnValue('OK'));
  660. $client = new Client($connection);
  661. $this->assertTrue($client->executeCommand($command));
  662. }
  663. // ******************************************************************** //
  664. // ---- HELPER METHODS ------------------------------------------------ //
  665. // ******************************************************************** //
  666. /**
  667. * Returns an URI string representation of the specified connection parameters.
  668. *
  669. * @param array $parameters Array of connection parameters.
  670. * @return String URI string.
  671. */
  672. protected function getParametersString(array $parameters)
  673. {
  674. $defaults = $this->getDefaultParametersArray();
  675. $scheme = isset($parameters['scheme']) ? $parameters['scheme'] : $defaults['scheme'];
  676. $host = isset($parameters['host']) ? $parameters['host'] : $defaults['host'];
  677. $port = isset($parameters['port']) ? $parameters['port'] : $defaults['port'];
  678. unset($parameters['scheme'], $parameters['host'], $parameters['port']);
  679. $uriString = "$scheme://$host:$port/?";
  680. foreach ($parameters as $k => $v) {
  681. $uriString .= "$k=$v&";
  682. }
  683. return $uriString;
  684. }
  685. }