RedisClusterTest.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  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\Connection\Aggregate;
  11. use PredisTestCase;
  12. use Predis\Command;
  13. use Predis\Connection;
  14. use Predis\Profile;
  15. use Predis\Response;
  16. /**
  17. *
  18. */
  19. class RedisClusterTest extends PredisTestCase
  20. {
  21. /**
  22. * @group disconnected
  23. */
  24. public function testUsesRedisClusterStrategyByDefault()
  25. {
  26. $cluster = new RedisCluster();
  27. $this->assertInstanceOf('Predis\Cluster\RedisStrategy', $cluster->getClusterStrategy());
  28. }
  29. /**
  30. * @group disconnected
  31. */
  32. public function testAcceptsCustomClusterStrategy()
  33. {
  34. $strategy = $this->getMock('Predis\Cluster\StrategyInterface');
  35. $cluster = new RedisCluster(null, $strategy);
  36. $this->assertSame($strategy, $cluster->getClusterStrategy());
  37. }
  38. /**
  39. * @group disconnected
  40. */
  41. public function testAddingConnectionsToCluster()
  42. {
  43. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  44. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  45. $cluster = new RedisCluster();
  46. $cluster->add($connection1);
  47. $cluster->add($connection2);
  48. $this->assertSame(2, count($cluster));
  49. $this->assertSame($connection1, $cluster->getConnectionById('127.0.0.1:6379'));
  50. $this->assertSame($connection2, $cluster->getConnectionById('127.0.0.1:6380'));
  51. }
  52. /**
  53. * @group disconnected
  54. */
  55. public function testRemovingConnectionsFromCluster()
  56. {
  57. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  58. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  59. $connection3 = $this->getMockConnection('tcp://127.0.0.1:6371');
  60. $cluster = new RedisCluster();
  61. $cluster->add($connection1);
  62. $cluster->add($connection2);
  63. $this->assertTrue($cluster->remove($connection1));
  64. $this->assertFalse($cluster->remove($connection3));
  65. $this->assertSame(1, count($cluster));
  66. }
  67. /**
  68. * @group disconnected
  69. */
  70. public function testRemovingConnectionsFromClusterByAlias()
  71. {
  72. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  73. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  74. $cluster = new RedisCluster();
  75. $cluster->add($connection1);
  76. $cluster->add($connection2);
  77. $this->assertTrue($cluster->removeById('127.0.0.1:6380'));
  78. $this->assertFalse($cluster->removeById('127.0.0.1:6390'));
  79. $this->assertSame(1, count($cluster));
  80. }
  81. /**
  82. * @group disconnected
  83. */
  84. public function testCountReturnsNumberOfConnectionsInPool()
  85. {
  86. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  87. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  88. $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381');
  89. $cluster = new RedisCluster();
  90. $cluster->add($connection1);
  91. $cluster->add($connection2);
  92. $cluster->add($connection3);
  93. $this->assertSame(3, count($cluster));
  94. $cluster->remove($connection3);
  95. $this->assertSame(2, count($cluster));
  96. }
  97. /**
  98. * @group disconnected
  99. */
  100. public function testConnectPicksRandomConnection()
  101. {
  102. $connect1 = false;
  103. $connect2 = false;
  104. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  105. $connection1->expects($this->any())
  106. ->method('connect')
  107. ->will($this->returnCallback(function () use (&$connect1) {
  108. $connect1 = true;
  109. }));
  110. $connection1->expects($this->any())
  111. ->method('isConnected')
  112. ->will($this->returnCallback(function () use (&$connect1) {
  113. return $connect1;
  114. }));
  115. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  116. $connection2->expects($this->any())
  117. ->method('connect')
  118. ->will($this->returnCallback(function () use (&$connect2) {
  119. $connect2 = true;
  120. }));
  121. $connection2->expects($this->any())
  122. ->method('isConnected')
  123. ->will($this->returnCallback(function () use (&$connect2) {
  124. return $connect2;
  125. }));
  126. $cluster = new RedisCluster();
  127. $cluster->add($connection1);
  128. $cluster->add($connection2);
  129. $cluster->connect();
  130. $this->assertTrue($cluster->isConnected());
  131. if ($connect1) {
  132. $this->assertTrue($connect1);
  133. $this->assertFalse($connect2);
  134. } else {
  135. $this->assertFalse($connect1);
  136. $this->assertTrue($connect2);
  137. }
  138. }
  139. /**
  140. * @group disconnected
  141. */
  142. public function testDisconnectForcesAllConnectionsToDisconnect()
  143. {
  144. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  145. $connection1->expects($this->once())->method('disconnect');
  146. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  147. $connection2->expects($this->once())->method('disconnect');
  148. $cluster = new RedisCluster();
  149. $cluster->add($connection1);
  150. $cluster->add($connection2);
  151. $cluster->disconnect();
  152. }
  153. /**
  154. * @group disconnected
  155. */
  156. public function testIsConnectedReturnsTrueIfAtLeastOneConnectionIsOpen()
  157. {
  158. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  159. $connection1->expects($this->once())
  160. ->method('isConnected')
  161. ->will($this->returnValue(false));
  162. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  163. $connection2->expects($this->once())
  164. ->method('isConnected')
  165. ->will($this->returnValue(true));
  166. $cluster = new RedisCluster();
  167. $cluster->add($connection1);
  168. $cluster->add($connection2);
  169. $this->assertTrue($cluster->isConnected());
  170. }
  171. /**
  172. * @group disconnected
  173. */
  174. public function testIsConnectedReturnsFalseIfAllConnectionsAreClosed()
  175. {
  176. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  177. $connection1->expects($this->once())
  178. ->method('isConnected')
  179. ->will($this->returnValue(false));
  180. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  181. $connection2->expects($this->once())
  182. ->method('isConnected')
  183. ->will($this->returnValue(false));
  184. $cluster = new RedisCluster();
  185. $cluster->add($connection1);
  186. $cluster->add($connection2);
  187. $this->assertFalse($cluster->isConnected());
  188. }
  189. /**
  190. * @group disconnected
  191. */
  192. public function testCanReturnAnIteratorForConnections()
  193. {
  194. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  195. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  196. $cluster = new RedisCluster();
  197. $cluster->add($connection1);
  198. $cluster->add($connection2);
  199. $this->assertInstanceOf('Iterator', $iterator = $cluster->getIterator());
  200. $connections = iterator_to_array($iterator);
  201. $this->assertSame($connection1, $connections[0]);
  202. $this->assertSame($connection2, $connections[1]);
  203. }
  204. /**
  205. * @group disconnected
  206. */
  207. public function testCanAssignConnectionsToCustomSlots()
  208. {
  209. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  210. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  211. $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381');
  212. $cluster = new RedisCluster();
  213. $cluster->add($connection1);
  214. $cluster->add($connection2);
  215. $cluster->add($connection3);
  216. $cluster->setSlots(0, 1364, '127.0.0.1:6379');
  217. $cluster->setSlots(1365, 2729, '127.0.0.1:6380');
  218. $cluster->setSlots(2730, 4095, '127.0.0.1:6381');
  219. $expectedMap = array_merge(
  220. array_fill(0, 1365, '127.0.0.1:6379'),
  221. array_fill(1364, 1365, '127.0.0.1:6380'),
  222. array_fill(2729, 1366, '127.0.0.1:6381')
  223. );
  224. $this->assertSame($expectedMap, $cluster->getSlotsMap());
  225. }
  226. /**
  227. * @group disconnected
  228. */
  229. public function testAddingConnectionResetsSlotsMap()
  230. {
  231. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  232. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  233. $cluster = new RedisCluster();
  234. $cluster->add($connection1);
  235. $cluster->setSlots(0, 4095, '127.0.0.1:6379');
  236. $this->assertSame(array_fill(0, 4096, '127.0.0.1:6379'), $cluster->getSlotsMap());
  237. $cluster->add($connection2);
  238. $this->assertEmpty($cluster->getSlotsMap());
  239. }
  240. /**
  241. * @group disconnected
  242. */
  243. public function testRemovingConnectionResetsSlotsMap()
  244. {
  245. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  246. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  247. $cluster = new RedisCluster();
  248. $cluster->add($connection1);
  249. $cluster->add($connection2);
  250. $cluster->setSlots(0, 2047, '127.0.0.1:6379');
  251. $cluster->setSlots(2048, 4095, '127.0.0.1:6380');
  252. $expectedMap = array_merge(
  253. array_fill(0, 2048, '127.0.0.1:6379'),
  254. array_fill(2048, 2048, '127.0.0.1:6380')
  255. );
  256. $this->assertSame($expectedMap, $cluster->getSlotsMap());
  257. $cluster->remove($connection1);
  258. $this->assertEmpty($cluster->getSlotsMap());
  259. }
  260. /**
  261. * @group disconnected
  262. */
  263. public function testCanAssignConnectionsToCustomSlotsFromParameters()
  264. {
  265. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379?slots=0-5460');
  266. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380?slots=5461-10921');
  267. $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381?slots=10922-16383');
  268. $cluster = new RedisCluster();
  269. $cluster->add($connection1);
  270. $cluster->add($connection2);
  271. $cluster->add($connection3);
  272. $expectedMap = array_merge(
  273. array_fill(0, 5461, '127.0.0.1:6379'),
  274. array_fill(5460, 5461, '127.0.0.1:6380'),
  275. array_fill(10921, 5462, '127.0.0.1:6381')
  276. );
  277. $cluster->buildSlotsMap();
  278. $this->assertSame($expectedMap, $cluster->getSlotsMap());
  279. }
  280. /**
  281. * @group disconnected
  282. */
  283. public function testReturnsCorrectConnectionUsingSlotID()
  284. {
  285. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  286. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  287. $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381');
  288. $cluster = new RedisCluster();
  289. $cluster->add($connection1);
  290. $cluster->add($connection2);
  291. $cluster->add($connection3);
  292. $this->assertSame($connection1, $cluster->getConnectionBySlot(0));
  293. $this->assertSame($connection2, $cluster->getConnectionBySlot(5461));
  294. $this->assertSame($connection3, $cluster->getConnectionBySlot(10922));
  295. $cluster->setSlots(5461, 7096, '127.0.0.1:6380');
  296. $this->assertSame($connection2, $cluster->getConnectionBySlot(5461));
  297. }
  298. /**
  299. * @group disconnected
  300. */
  301. public function testReturnsCorrectConnectionUsingCommandInstance()
  302. {
  303. $profile = Profile\Factory::getDefault();
  304. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  305. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  306. $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381');
  307. $cluster = new RedisCluster();
  308. $cluster->add($connection1);
  309. $cluster->add($connection2);
  310. $cluster->add($connection3);
  311. $set = $profile->createCommand('set', array('node:1001', 'foobar'));
  312. $get = $profile->createCommand('get', array('node:1001'));
  313. $this->assertSame($connection1, $cluster->getConnection($set));
  314. $this->assertSame($connection1, $cluster->getConnection($get));
  315. $set = $profile->createCommand('set', array('node:1048', 'foobar'));
  316. $get = $profile->createCommand('get', array('node:1048'));
  317. $this->assertSame($connection2, $cluster->getConnection($set));
  318. $this->assertSame($connection2, $cluster->getConnection($get));
  319. $set = $profile->createCommand('set', array('node:1082', 'foobar'));
  320. $get = $profile->createCommand('get', array('node:1082'));
  321. $this->assertSame($connection3, $cluster->getConnection($set));
  322. $this->assertSame($connection3, $cluster->getConnection($get));
  323. }
  324. /**
  325. * @group disconnected
  326. */
  327. public function testWritesCommandToCorrectConnection()
  328. {
  329. $command = Profile\Factory::getDefault()->createCommand('get', array('node:1001'));
  330. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  331. $connection1->expects($this->once())->method('writeRequest')->with($command);
  332. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  333. $connection2->expects($this->never())->method('writeRequest');
  334. $cluster = new RedisCluster();
  335. $cluster->add($connection1);
  336. $cluster->add($connection2);
  337. $cluster->writeRequest($command);
  338. }
  339. /**
  340. * @group disconnected
  341. */
  342. public function testReadsCommandFromCorrectConnection()
  343. {
  344. $command = Profile\Factory::getDefault()->createCommand('get', array('node:1050'));
  345. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  346. $connection1->expects($this->never())->method('readResponse');
  347. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  348. $connection2->expects($this->once())->method('readResponse')->with($command);
  349. $cluster = new RedisCluster();
  350. $cluster->add($connection1);
  351. $cluster->add($connection2);
  352. $cluster->readResponse($command);
  353. }
  354. /**
  355. * @group disconnected
  356. */
  357. public function testSupportsKeyHashTags()
  358. {
  359. $profile = Profile\Factory::getDefault();
  360. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  361. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  362. $cluster = new RedisCluster();
  363. $cluster->add($connection1);
  364. $cluster->add($connection2);
  365. $set = $profile->createCommand('set', array('{node:1001}:foo', 'foobar'));
  366. $get = $profile->createCommand('get', array('{node:1001}:foo'));
  367. $this->assertSame($connection1, $cluster->getConnection($set));
  368. $this->assertSame($connection1, $cluster->getConnection($get));
  369. $set = $profile->createCommand('set', array('{node:1001}:bar', 'foobar'));
  370. $get = $profile->createCommand('get', array('{node:1001}:bar'));
  371. $this->assertSame($connection1, $cluster->getConnection($set));
  372. $this->assertSame($connection1, $cluster->getConnection($get));
  373. }
  374. /**
  375. * @group disconnected
  376. */
  377. public function testAskResponseWithConnectionInPool()
  378. {
  379. $askResponse = new Response\Error('ASK 1970 127.0.0.1:6380');
  380. $command = Profile\Factory::getDefault()->createCommand('get', array('node:1001'));
  381. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  382. $connection1->expects($this->exactly(2))
  383. ->method('executeCommand')
  384. ->with($command)
  385. ->will($this->onConsecutiveCalls($askResponse, 'foobar'));
  386. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  387. $connection2->expects($this->at(2))
  388. ->method('executeCommand')
  389. ->with($this->isRedisCommand('ASKING'));
  390. $connection2->expects($this->at(3))
  391. ->method('executeCommand')
  392. ->with($command)
  393. ->will($this->returnValue('foobar'));
  394. $factory = $this->getMock('Predis\Connection\Factory');
  395. $factory->expects($this->never())->method('create');
  396. $cluster = new RedisCluster($factory);
  397. $cluster->add($connection1);
  398. $cluster->add($connection2);
  399. $this->assertSame('foobar', $cluster->executeCommand($command));
  400. $this->assertSame('foobar', $cluster->executeCommand($command));
  401. $this->assertSame(2, count($cluster));
  402. }
  403. /**
  404. * @group disconnected
  405. */
  406. public function testAskResponseWithConnectionNotInPool()
  407. {
  408. $askResponse = new Response\Error('ASK 1970 127.0.0.1:6381');
  409. $command = Profile\Factory::getDefault()->createCommand('get', array('node:1001'));
  410. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  411. $connection1->expects($this->exactly(2))
  412. ->method('executeCommand')
  413. ->with($command)
  414. ->will($this->onConsecutiveCalls($askResponse, 'foobar'));
  415. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  416. $connection2->expects($this->never())
  417. ->method('executeCommand');
  418. $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381');
  419. $connection3->expects($this->at(0))
  420. ->method('executeCommand')
  421. ->with($this->isRedisCommand('ASKING'));
  422. $connection3->expects($this->at(1))
  423. ->method('executeCommand')
  424. ->with($command)
  425. ->will($this->returnValue('foobar'));
  426. $factory = $this->getMock('Predis\Connection\Factory');
  427. $factory->expects($this->once())
  428. ->method('create')
  429. ->with(array('host' => '127.0.0.1', 'port' => '6381'))
  430. ->will($this->returnValue($connection3));
  431. $cluster = new RedisCluster($factory);
  432. $cluster->add($connection1);
  433. $cluster->add($connection2);
  434. $this->assertSame('foobar', $cluster->executeCommand($command));
  435. $this->assertSame('foobar', $cluster->executeCommand($command));
  436. $this->assertSame(2, count($cluster));
  437. }
  438. /**
  439. * @group disconnected
  440. */
  441. public function testMovedResponseWithConnectionInPool()
  442. {
  443. $movedResponse = new Response\Error('MOVED 1970 127.0.0.1:6380');
  444. $command = Profile\Factory::getDefault()->createCommand('get', array('node:1001'));
  445. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  446. $connection1->expects($this->exactly(1))
  447. ->method('executeCommand')
  448. ->with($command)
  449. ->will($this->returnValue($movedResponse));
  450. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  451. $connection2->expects($this->exactly(2))
  452. ->method('executeCommand')
  453. ->with($command)
  454. ->will($this->onConsecutiveCalls('foobar', 'foobar'));
  455. $factory = $this->getMock('Predis\Connection\Factory');
  456. $factory->expects($this->never())->method('create');
  457. $cluster = new RedisCluster($factory);
  458. $cluster->add($connection1);
  459. $cluster->add($connection2);
  460. $this->assertSame('foobar', $cluster->executeCommand($command));
  461. $this->assertSame('foobar', $cluster->executeCommand($command));
  462. $this->assertSame(2, count($cluster));
  463. }
  464. /**
  465. * @group disconnected
  466. */
  467. public function testMovedResponseWithConnectionNotInPool()
  468. {
  469. $movedResponse = new Response\Error('MOVED 1970 127.0.0.1:6381');
  470. $command = Profile\Factory::getDefault()->createCommand('get', array('node:1001'));
  471. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379');
  472. $connection1->expects($this->once())
  473. ->method('executeCommand')
  474. ->with($command)
  475. ->will($this->returnValue($movedResponse));
  476. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  477. $connection2->expects($this->never())
  478. ->method('executeCommand');
  479. $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381');
  480. $connection3->expects($this->exactly(2))
  481. ->method('executeCommand')
  482. ->with($command)
  483. ->will($this->onConsecutiveCalls('foobar', 'foobar'));
  484. $factory = $this->getMock('Predis\Connection\Factory');
  485. $factory->expects($this->once())
  486. ->method('create')
  487. ->with(array('host' => '127.0.0.1', 'port' => '6381'))
  488. ->will($this->returnValue($connection3));
  489. $cluster = new RedisCluster($factory);
  490. $cluster->add($connection1);
  491. $cluster->add($connection2);
  492. $this->assertSame('foobar', $cluster->executeCommand($command));
  493. $this->assertSame('foobar', $cluster->executeCommand($command));
  494. $this->assertSame(3, count($cluster));
  495. }
  496. /**
  497. * @group disconnected
  498. */
  499. public function testFetchSlotsMapFromClusterWithClusterSlotsCommand()
  500. {
  501. $response = array(
  502. array(12288, 13311, array('10.1.0.51', 6387), array('10.1.0.52', 6387)),
  503. array(3072 , 4095, array('10.1.0.52', 6392), array('10.1.0.51', 6392)),
  504. array(6144 , 7167, array('', 6384), array('10.1.0.52', 6384)),
  505. array(14336, 15359, array('10.1.0.51', 6388), array('10.1.0.52', 6388)),
  506. array(15360, 16383, array('10.1.0.52', 6398), array('10.1.0.51', 6398)),
  507. array(1024 , 2047, array('10.1.0.52', 6391), array('10.1.0.51', 6391)),
  508. array(11264, 12287, array('10.1.0.52', 6396), array('10.1.0.51', 6396)),
  509. array( 5120, 6143, array('10.1.0.52', 6393), array('10.1.0.51', 6393)),
  510. array( 0, 1023, array('10.1.0.51', 6381), array('10.1.0.52', 6381)),
  511. array(13312, 14335, array('10.1.0.52', 6397), array('10.1.0.51', 6397)),
  512. array( 4096, 5119, array('10.1.0.51', 6383), array('10.1.0.52', 6383)),
  513. array( 9216, 10239, array('10.1.0.52', 6395), array('10.1.0.51', 6395)),
  514. array( 8192, 9215, array('10.1.0.51', 6385), array('10.1.0.52', 6385)),
  515. array(10240, 11263, array('10.1.0.51', 6386), array('10.1.0.52', 6386)),
  516. array( 2048, 3071, array('10.1.0.51', 6382), array('10.1.0.52', 6382)),
  517. array( 7168, 8191, array('10.1.0.52', 6394), array('10.1.0.51', 6394)),
  518. );
  519. $command = Command\RawCommand::create('CLUSTER', 'SLOTS');
  520. $connection1 = $this->getMockConnection('tcp://10.1.0.51:6384');
  521. $connection1->expects($this->once())
  522. ->method('executeCommand')
  523. ->with($command)
  524. ->will($this->returnValue($response));
  525. $factory = $this->getMock('Predis\Connection\Factory');
  526. $cluster = new RedisCluster($factory);
  527. $cluster->add($connection1);
  528. $cluster->askSlotsMap();
  529. $this->assertSame($cluster->getConnectionBySlot('6144'), $connection1);
  530. }
  531. /**
  532. * @group disconnected
  533. * @expectedException Predis\NotSupportedException
  534. * @expectedExceptionMessage Cannot use 'PING' with redis-cluster.
  535. */
  536. public function testThrowsExceptionOnNonSupportedCommand()
  537. {
  538. $ping = Profile\Factory::getDefault()->createCommand('ping');
  539. $cluster = new RedisCluster();
  540. $cluster->add($this->getMockConnection('tcp://127.0.0.1:6379'));
  541. $cluster->getConnection($ping);
  542. }
  543. /**
  544. * @group disconnected
  545. */
  546. public function testCanBeSerialized()
  547. {
  548. $connection1 = $this->getMockConnection('tcp://127.0.0.1:6379?slots=0-1364');
  549. $connection2 = $this->getMockConnection('tcp://127.0.0.1:6380?slots=1365-2729');
  550. $connection3 = $this->getMockConnection('tcp://127.0.0.1:6381?slots=2730-4095');
  551. $cluster = new RedisCluster();
  552. $cluster->add($connection1);
  553. $cluster->add($connection2);
  554. $cluster->add($connection3);
  555. $cluster->buildSlotsMap();
  556. $unserialized = unserialize(serialize($cluster));
  557. $this->assertEquals($cluster, $unserialized);
  558. }
  559. // ******************************************************************** //
  560. // ---- HELPER METHODS ------------------------------------------------ //
  561. // ******************************************************************** //
  562. /**
  563. * Returns a base mocked connection from Predis\Connection\NodeConnectionInterface.
  564. *
  565. * @param mixed $parameters Optional parameters.
  566. * @return mixed
  567. */
  568. protected function getMockConnection($parameters = null)
  569. {
  570. $connection = $this->getMock('Predis\Connection\NodeConnectionInterface');
  571. if ($parameters) {
  572. $parameters = Connection\Parameters::create($parameters);
  573. $hash = "{$parameters->host}:{$parameters->port}";
  574. $connection->expects($this->any())
  575. ->method('getParameters')
  576. ->will($this->returnValue($parameters));
  577. $connection->expects($this->any())
  578. ->method('__toString')
  579. ->will($this->returnValue($hash));
  580. }
  581. return $connection;
  582. }
  583. }