SentinelReplicationTest.php 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  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 Predis\Command;
  12. use Predis\Connection;
  13. use Predis\Replication;
  14. use Predis\Response;
  15. use PredisTestCase;
  16. /**
  17. *
  18. */
  19. class SentinelReplicationTest extends PredisTestCase
  20. {
  21. /**
  22. * @group disconnected
  23. * @expectedException Predis\ClientException
  24. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  25. */
  26. public function testMethodGetSentinelConnectionThrowsExceptionOnEmptySentinelsPool()
  27. {
  28. $replication = $this->getReplicationConnection('svc', array());
  29. $replication->getSentinelConnection();
  30. }
  31. /**
  32. * @group disconnected
  33. */
  34. public function testParametersForSentinelConnectionShouldNotUseDatabaseAndPassword()
  35. {
  36. $replication = $this->getReplicationConnection('svc', array(
  37. 'tcp://127.0.0.1:5381?alias=sentinel1&database=1&password=secret',
  38. ));
  39. $parameters = $replication->getSentinelConnection()->getParameters()->toArray();
  40. $this->assertArraySubset(array('database' => null, 'password' => null), $parameters);
  41. }
  42. /**
  43. * @group disconnected
  44. */
  45. public function testParametersForSentinelConnectionHaveDefaultTimeout()
  46. {
  47. $replication = $this->getReplicationConnection('svc', array(
  48. 'tcp://127.0.0.1:5381?alias=sentinel',
  49. ));
  50. $parameters = $replication->getSentinelConnection()->getParameters()->toArray();
  51. $this->assertArrayHasKey('timeout', $parameters);
  52. $this->assertSame(0.100, $parameters['timeout']);
  53. }
  54. /**
  55. * @group disconnected
  56. */
  57. public function testParametersForSentinelConnectionCanOverrideDefaultTimeout()
  58. {
  59. $replication = $this->getReplicationConnection('svc', array(
  60. 'tcp://127.0.0.1:5381?alias=sentinel&timeout=1',
  61. ));
  62. $parameters = $replication->getSentinelConnection()->getParameters()->toArray();
  63. $this->assertArrayHasKey('timeout', $parameters);
  64. $this->assertSame('1', $parameters['timeout']);
  65. }
  66. /**
  67. * @group disconnected
  68. */
  69. public function testConnectionParametersInstanceForSentinelConnectionIsNotModified()
  70. {
  71. $originalParameters = Connection\Parameters::create(
  72. 'tcp://127.0.0.1:5381?alias=sentinel1&database=1&password=secret'
  73. );
  74. $replication = $this->getReplicationConnection('svc', array($originalParameters));
  75. $parameters = $replication->getSentinelConnection()->getParameters();
  76. $this->assertSame($originalParameters, $parameters);
  77. $this->assertNotNull($parameters->password);
  78. $this->assertNotNull($parameters->database);
  79. }
  80. /**
  81. * @group disconnected
  82. */
  83. public function testMethodGetSentinelConnectionReturnsFirstAvailableSentinel()
  84. {
  85. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  86. $sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?alias=sentinel2');
  87. $sentinel3 = $this->getMockSentinelConnection('tcp://127.0.0.1:5383?alias=sentinel3');
  88. $replication = $this->getReplicationConnection('svc', array($sentinel1, $sentinel2, $sentinel3));
  89. $this->assertSame($sentinel1, $replication->getSentinelConnection());
  90. }
  91. /**
  92. * @group disconnected
  93. */
  94. public function testMethodAddAttachesMasterOrSlaveNodesToReplication()
  95. {
  96. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  97. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  98. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  99. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  100. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  101. $replication->add($master);
  102. $replication->add($slave1);
  103. $replication->add($slave2);
  104. $this->assertSame($master, $replication->getConnectionById('master'));
  105. $this->assertSame($slave1, $replication->getConnectionById('slave1'));
  106. $this->assertSame($slave2, $replication->getConnectionById('slave2'));
  107. $this->assertSame($master, $replication->getMaster());
  108. $this->assertSame(array($slave1, $slave2), $replication->getSlaves());
  109. }
  110. /**
  111. * @group disconnected
  112. */
  113. public function testMethodRemoveDismissesMasterOrSlaveNodesFromReplication()
  114. {
  115. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  116. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  117. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  118. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  119. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  120. $replication->add($master);
  121. $replication->add($slave1);
  122. $replication->add($slave2);
  123. $this->assertTrue($replication->remove($slave1));
  124. $this->assertFalse($replication->remove($sentinel1));
  125. $this->assertSame('127.0.0.1:6381', (string) $replication->getMaster());
  126. $this->assertCount(1, $slaves = $replication->getSlaves());
  127. $this->assertSame('127.0.0.1:6383', (string) $slaves[0]);
  128. }
  129. /**
  130. * @group disconnected
  131. */
  132. public function testMethodUpdateSentinelsFetchesSentinelNodes()
  133. {
  134. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  135. $sentinel1->expects($this->once())
  136. ->method('executeCommand')
  137. ->with($this->isRedisCommand(
  138. 'SENTINEL', array('sentinels', 'svc')
  139. ))
  140. ->will($this->returnValue(
  141. array(
  142. array(
  143. 'name', '127.0.0.1:5382',
  144. 'ip', '127.0.0.1',
  145. 'port', '5382',
  146. 'runid', 'a113aa7a0d4870a85bb22b4b605fd26eb93ed40e',
  147. 'flags', 'sentinel',
  148. ),
  149. array(
  150. 'name', '127.0.0.1:5383',
  151. 'ip', '127.0.0.1',
  152. 'port', '5383',
  153. 'runid', 'f53b52d281be5cdd4873700c94846af8dbe47209',
  154. 'flags', 'sentinel',
  155. ),
  156. )
  157. ));
  158. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  159. $replication->updateSentinels();
  160. // TODO: sorry for the smell...
  161. $reflection = new \ReflectionProperty($replication, 'sentinels');
  162. $reflection->setAccessible(true);
  163. $expected = array(
  164. array('host' => '127.0.0.1', 'port' => '5381'),
  165. array('host' => '127.0.0.1', 'port' => '5382'),
  166. array('host' => '127.0.0.1', 'port' => '5383'),
  167. );
  168. $this->assertSame($sentinel1, $replication->getSentinelConnection());
  169. $this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
  170. }
  171. /**
  172. * @group disconnected
  173. */
  174. public function testMethodUpdateSentinelsRemovesCurrentSentinelAndRetriesNextOneOnFailure()
  175. {
  176. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  177. $sentinel1->expects($this->once())
  178. ->method('executeCommand')
  179. ->with($this->isRedisCommand(
  180. 'SENTINEL', array('sentinels', 'svc')
  181. ))
  182. ->will($this->throwException(
  183. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  184. ));
  185. $sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?alias=sentinel2');
  186. $sentinel2->expects($this->once())
  187. ->method('executeCommand')
  188. ->with($this->isRedisCommand(
  189. 'SENTINEL', array('sentinels', 'svc')
  190. ))
  191. ->will($this->returnValue(
  192. array(
  193. array(
  194. 'name', '127.0.0.1:5383',
  195. 'ip', '127.0.0.1',
  196. 'port', '5383',
  197. 'runid', 'f53b52d281be5cdd4873700c94846af8dbe47209',
  198. 'flags', 'sentinel',
  199. ),
  200. )
  201. ));
  202. $replication = $this->getReplicationConnection('svc', array($sentinel1, $sentinel2));
  203. $replication->updateSentinels();
  204. // TODO: sorry for the smell...
  205. $reflection = new \ReflectionProperty($replication, 'sentinels');
  206. $reflection->setAccessible(true);
  207. $expected = array(
  208. array('host' => '127.0.0.1', 'port' => '5382'),
  209. array('host' => '127.0.0.1', 'port' => '5383'),
  210. );
  211. $this->assertSame($sentinel2, $replication->getSentinelConnection());
  212. $this->assertSame($expected, array_intersect_key($expected, $reflection->getValue($replication)));
  213. }
  214. /**
  215. * @group disconnected
  216. * @expectedException Predis\ClientException
  217. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  218. */
  219. public function testMethodUpdateSentinelsThrowsExceptionOnNoAvailableSentinel()
  220. {
  221. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  222. $sentinel1->expects($this->once())
  223. ->method('executeCommand')
  224. ->with($this->isRedisCommand(
  225. 'SENTINEL', array('sentinels', 'svc')
  226. ))
  227. ->will($this->throwException(
  228. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  229. ));
  230. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  231. $replication->updateSentinels();
  232. }
  233. /**
  234. * @group disconnected
  235. */
  236. public function testMethodQuerySentinelFetchesMasterNodeSlaveNodesAndSentinelNodes()
  237. {
  238. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  239. $sentinel1->expects($this->exactly(3))
  240. ->method('executeCommand')
  241. ->withConsecutive(
  242. $this->isRedisCommand('SENTINEL', array('sentinels', 'svc')),
  243. $this->isRedisCommand('SENTINEL', array('get-master-addr-by-name', 'svc')),
  244. $this->isRedisCommand('SENTINEL', array('slaves', 'svc'))
  245. )
  246. ->will($this->onConsecutiveCalls(
  247. // SENTINEL sentinels svc
  248. array(
  249. array(
  250. 'name', '127.0.0.1:5382',
  251. 'ip', '127.0.0.1',
  252. 'port', '5382',
  253. 'runid', 'a113aa7a0d4870a85bb22b4b605fd26eb93ed40e',
  254. 'flags', 'sentinel',
  255. ),
  256. ),
  257. // SENTINEL get-master-addr-by-name svc
  258. array('127.0.0.1', '6381'),
  259. // SENTINEL slaves svc
  260. array(
  261. array(
  262. 'name', '127.0.0.1:6382',
  263. 'ip', '127.0.0.1',
  264. 'port', '6382',
  265. 'runid', '112cdebd22924a7d962be496f3a1c4c7c9bad93f',
  266. 'flags', 'slave',
  267. 'master-host', '127.0.0.1',
  268. 'master-port', '6381',
  269. ),
  270. array(
  271. 'name', '127.0.0.1:6383',
  272. 'ip', '127.0.0.1',
  273. 'port', '6383',
  274. 'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
  275. 'flags', 'slave',
  276. 'master-host', '127.0.0.1',
  277. 'master-port', '6381',
  278. ),
  279. )
  280. ));
  281. $sentinel2 = $this->getMockSentinelConnection('tcp://127.0.0.1:5382?alias=sentinel2');
  282. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  283. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  284. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  285. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  286. $replication->querySentinel();
  287. // TODO: sorry for the smell...
  288. $reflection = new \ReflectionProperty($replication, 'sentinels');
  289. $reflection->setAccessible(true);
  290. $sentinels = array(
  291. array('host' => '127.0.0.1', 'port' => '5381'),
  292. array('host' => '127.0.0.1', 'port' => '5382'),
  293. );
  294. $this->assertSame($sentinel1, $replication->getSentinelConnection());
  295. $this->assertSame($sentinels, array_intersect_key($sentinels, $reflection->getValue($replication)));
  296. $master = $replication->getMaster();
  297. $slaves = $replication->getSlaves();
  298. $this->assertSame('127.0.0.1:6381', (string) $master);
  299. $this->assertCount(2, $slaves);
  300. $this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
  301. $this->assertSame('127.0.0.1:6383', (string) $slaves[1]);
  302. }
  303. /**
  304. * @group disconnected
  305. */
  306. public function testMethodGetMasterAsksSentinelForMasterOnMasterNotSet()
  307. {
  308. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  309. $sentinel1->expects($this->at(0))
  310. ->method('executeCommand')
  311. ->with($this->isRedisCommand(
  312. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  313. ))
  314. ->will($this->returnValue(
  315. array('127.0.0.1', '6381')
  316. ));
  317. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  318. $this->assertSame('127.0.0.1:6381', (string) $replication->getMaster());
  319. }
  320. /**
  321. * @group disconnected
  322. * @expectedException Predis\ClientException
  323. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  324. */
  325. public function testMethodGetMasterThrowsExceptionOnNoAvailableSentinels()
  326. {
  327. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  328. $sentinel1->expects($this->any())
  329. ->method('executeCommand')
  330. ->with($this->isRedisCommand(
  331. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  332. ))
  333. ->will($this->throwException(
  334. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  335. ));
  336. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  337. $replication->getMaster();
  338. }
  339. /**
  340. * @group disconnected
  341. */
  342. public function testMethodGetSlavesOnEmptySlavePoolAsksSentinelForSlaves()
  343. {
  344. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  345. $sentinel1->expects($this->at(0))
  346. ->method('executeCommand')
  347. ->with($this->isRedisCommand(
  348. 'SENTINEL', array('slaves', 'svc')
  349. ))
  350. ->will($this->returnValue(
  351. array(
  352. array(
  353. 'name', '127.0.0.1:6382',
  354. 'ip', '127.0.0.1',
  355. 'port', '6382',
  356. 'runid', '112cdebd22924a7d962be496f3a1c4c7c9bad93f',
  357. 'flags', 'slave',
  358. 'master-host', '127.0.0.1',
  359. 'master-port', '6381',
  360. ),
  361. array(
  362. 'name', '127.0.0.1:6383',
  363. 'ip', '127.0.0.1',
  364. 'port', '6383',
  365. 'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
  366. 'flags', 'slave',
  367. 'master-host', '127.0.0.1',
  368. 'master-port', '6381',
  369. ),
  370. )
  371. ));
  372. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  373. $slaves = $replication->getSlaves();
  374. $this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
  375. $this->assertSame('127.0.0.1:6383', (string) $slaves[1]);
  376. }
  377. /**
  378. * @group disconnected
  379. * @expectedException Predis\ClientException
  380. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  381. */
  382. public function testMethodGetSlavesThrowsExceptionOnNoAvailableSentinels()
  383. {
  384. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  385. $sentinel1->expects($this->any())
  386. ->method('executeCommand')
  387. ->with($this->isRedisCommand(
  388. 'SENTINEL', array('slaves', 'svc')
  389. ))
  390. ->will($this->throwException(
  391. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  392. ));
  393. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  394. $replication->getSlaves();
  395. }
  396. /**
  397. * @group disconnected
  398. * @expectedException Predis\ClientException
  399. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  400. */
  401. public function testMethodConnectThrowsExceptionOnConnectWithEmptySentinelsPool()
  402. {
  403. $replication = $this->getReplicationConnection('svc', array());
  404. $replication->connect();
  405. }
  406. /**
  407. * @group disconnected
  408. */
  409. public function testMethodConnectForcesConnectionToSlave()
  410. {
  411. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  412. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  413. $master->expects($this->never())
  414. ->method('connect');
  415. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  416. $slave1->expects($this->once())
  417. ->method('connect');
  418. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  419. $replication->add($master);
  420. $replication->add($slave1);
  421. $replication->connect();
  422. }
  423. /**
  424. * @group disconnected
  425. */
  426. public function testMethodConnectOnEmptySlavePoolAsksSentinelForSlavesAndForcesConnectionToSlave()
  427. {
  428. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  429. $sentinel1->expects($this->any())
  430. ->method('executeCommand')
  431. ->with($this->isRedisCommand(
  432. 'SENTINEL', array('slaves', 'svc')
  433. ))
  434. ->will($this->returnValue(
  435. array(
  436. array(
  437. 'name', '127.0.0.1:6382',
  438. 'ip', '127.0.0.1',
  439. 'port', '6382',
  440. 'runid', '112cdebd22924a7d962be496f3a1c4c7c9bad93f',
  441. 'flags', 'slave',
  442. 'master-host', '127.0.0.1',
  443. 'master-port', '6381',
  444. ),
  445. )
  446. ));
  447. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  448. $master->expects($this->never())
  449. ->method('connect');
  450. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  451. $slave1->expects($this->once())
  452. ->method('connect');
  453. $factory = $this->getMock('Predis\Connection\FactoryInterface');
  454. $factory->expects($this->once())
  455. ->method('create')
  456. ->with(array(
  457. 'host' => '127.0.0.1',
  458. 'port' => '6382',
  459. 'alias' => 'slave-127.0.0.1:6382',
  460. ))
  461. ->will($this->returnValue($slave1));
  462. $replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
  463. $replication->add($master);
  464. $replication->connect();
  465. }
  466. /**
  467. * @group disconnected
  468. */
  469. public function testMethodConnectOnEmptySlavePoolAsksSentinelForSlavesAndForcesConnectionToMasterIfStillEmpty()
  470. {
  471. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  472. $sentinel1->expects($this->at(0))
  473. ->method('executeCommand')
  474. ->with($this->isRedisCommand(
  475. 'SENTINEL', array('slaves', 'svc')
  476. ))
  477. ->will($this->returnValue(
  478. array()
  479. ));
  480. $sentinel1->expects($this->at(1))
  481. ->method('executeCommand')
  482. ->with($this->isRedisCommand(
  483. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  484. ))
  485. ->will($this->returnValue(
  486. array('127.0.0.1', '6381')
  487. ));
  488. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  489. $master->expects($this->once())
  490. ->method('connect');
  491. $factory = $this->getMock('Predis\Connection\FactoryInterface');
  492. $factory->expects($this->once())
  493. ->method('create')
  494. ->with(array(
  495. 'host' => '127.0.0.1',
  496. 'port' => '6381',
  497. 'alias' => 'master',
  498. ))
  499. ->will($this->returnValue($master));
  500. $replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
  501. $replication->connect();
  502. }
  503. /**
  504. * @group disconnected
  505. */
  506. public function testMethodDisconnectForcesDisconnectionOnAllConnectionsInPool()
  507. {
  508. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  509. $sentinel1->expects($this->never())->method('disconnect');
  510. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  511. $master->expects($this->once())->method('disconnect');
  512. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  513. $slave1->expects($this->once())->method('disconnect');
  514. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  515. $slave2->expects($this->once())->method('disconnect');
  516. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  517. $replication->add($master);
  518. $replication->add($slave1);
  519. $replication->add($slave2);
  520. $replication->disconnect();
  521. }
  522. /**
  523. * @group disconnected
  524. */
  525. public function testMethodIsConnectedReturnConnectionStatusOfCurrentConnection()
  526. {
  527. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  528. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  529. $slave1->expects($this->exactly(2))
  530. ->method('isConnected')
  531. ->will($this->onConsecutiveCalls(true, false));
  532. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  533. $replication->add($slave1);
  534. $this->assertFalse($replication->isConnected());
  535. $replication->connect();
  536. $this->assertTrue($replication->isConnected());
  537. $replication->getConnectionById('slave1')->disconnect();
  538. $this->assertFalse($replication->isConnected());
  539. }
  540. /**
  541. * @group disconnected
  542. */
  543. public function testMethodGetConnectionByIdReturnsConnectionWhenFound()
  544. {
  545. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  546. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  547. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  548. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  549. $replication->add($master);
  550. $replication->add($slave1);
  551. $this->assertSame($master, $replication->getConnectionById('master'));
  552. $this->assertSame($slave1, $replication->getConnectionById('slave1'));
  553. $this->assertNull($replication->getConnectionById('unknown'));
  554. }
  555. /**
  556. * @group disconnected
  557. */
  558. public function testMethodSwitchToSelectsCurrentConnectionByConnectionAlias()
  559. {
  560. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  561. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  562. $master->expects($this->once())->method('connect');
  563. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  564. $slave1->expects($this->never())->method('connect');
  565. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave2');
  566. $slave2->expects($this->once())->method('connect');
  567. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  568. $replication->add($master);
  569. $replication->add($slave1);
  570. $replication->add($slave2);
  571. $replication->switchTo('master');
  572. $this->assertSame($master, $replication->getCurrent());
  573. $replication->switchTo('slave2');
  574. $this->assertSame($slave2, $replication->getCurrent());
  575. }
  576. /**
  577. * @group disconnected
  578. * @expectedException InvalidArgumentException
  579. * @expectedExceptionMessage Invalid connection or connection not found.
  580. */
  581. public function testMethodSwitchToThrowsExceptionOnConnectionNotFound()
  582. {
  583. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  584. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  585. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  586. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  587. $replication->add($master);
  588. $replication->add($slave1);
  589. $replication->switchTo('unknown');
  590. }
  591. /**
  592. * @group disconnected
  593. */
  594. public function testMethodSwitchToMasterSelectsCurrentConnectionToMaster()
  595. {
  596. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  597. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  598. $master->expects($this->once())->method('connect');
  599. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  600. $slave1->expects($this->never())->method('connect');
  601. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  602. $replication->add($master);
  603. $replication->add($slave1);
  604. $replication->switchToMaster();
  605. $this->assertSame($master, $replication->getCurrent());
  606. }
  607. /**
  608. * @group disconnected
  609. */
  610. public function testMethodSwitchToSlaveSelectsCurrentConnectionToRandomSlave()
  611. {
  612. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  613. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  614. $master->expects($this->never())->method('connect');
  615. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  616. $slave1->expects($this->once())->method('connect');
  617. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  618. $replication->add($master);
  619. $replication->add($slave1);
  620. $replication->switchToSlave();
  621. $this->assertSame($slave1, $replication->getCurrent());
  622. }
  623. /**
  624. * @group disconnected
  625. */
  626. public function testGetConnectionReturnsMasterForWriteCommands()
  627. {
  628. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  629. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  630. $master->expects($this->exactly(2))
  631. ->method('isConnected')
  632. ->will($this->onConsecutiveCalls(false, true));
  633. $master->expects($this->at(2))
  634. ->method('executeCommand')
  635. ->with($this->isRedisCommand('ROLE'))
  636. ->will($this->returnValue(array(
  637. 'master', 3129659, array(array('127.0.0.1', 6382, 3129242)),
  638. )));
  639. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  640. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  641. $replication->add($master);
  642. $replication->add($slave1);
  643. $this->assertSame($master, $replication->getConnection(
  644. Command\RawCommand::create('set', 'key', 'value')
  645. ));
  646. $this->assertSame($master, $replication->getConnection(
  647. Command\RawCommand::create('del', 'key')
  648. ));
  649. }
  650. /**
  651. * @group disconnected
  652. */
  653. public function testGetConnectionReturnsSlaveForReadOnlyCommands()
  654. {
  655. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  656. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  657. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  658. $slave1->expects($this->exactly(2))
  659. ->method('isConnected')
  660. ->will($this->onConsecutiveCalls(false, true));
  661. $slave1->expects($this->at(2))
  662. ->method('executeCommand')
  663. ->with($this->isRedisCommand('ROLE'))
  664. ->will($this->returnValue(array(
  665. 'slave', '127.0.0.1', 9000, 'connected', 3167038,
  666. )));
  667. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  668. $replication->add($master);
  669. $replication->add($slave1);
  670. $this->assertSame($slave1, $replication->getConnection(
  671. Command\RawCommand::create('get', 'key')
  672. ));
  673. $this->assertSame($slave1, $replication->getConnection(
  674. Command\RawCommand::create('exists', 'key')
  675. ));
  676. }
  677. /**
  678. * @group disconnected
  679. */
  680. public function testGetConnectionSwitchesToMasterAfterWriteCommand()
  681. {
  682. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  683. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  684. $master->expects($this->exactly(2))
  685. ->method('isConnected')
  686. ->will($this->onConsecutiveCalls(false, true));
  687. $master->expects($this->at(2))
  688. ->method('executeCommand')
  689. ->with($this->isRedisCommand('ROLE'))
  690. ->will($this->returnValue(array(
  691. 'master', 3129659, array(array('127.0.0.1', 6382, 3129242)),
  692. )));
  693. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  694. $slave1->expects($this->exactly(1))
  695. ->method('isConnected')
  696. ->will($this->onConsecutiveCalls(false));
  697. $slave1->expects($this->at(2))
  698. ->method('executeCommand')
  699. ->with($this->isRedisCommand('ROLE'))
  700. ->will($this->returnValue(array(
  701. 'slave', '127.0.0.1', 9000, 'connected', 3167038,
  702. )));
  703. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  704. $replication->add($master);
  705. $replication->add($slave1);
  706. $this->assertSame($slave1, $replication->getConnection(
  707. Command\RawCommand::create('exists', 'key')
  708. ));
  709. $this->assertSame($master, $replication->getConnection(
  710. Command\RawCommand::create('set', 'key', 'value')
  711. ));
  712. $this->assertSame($master, $replication->getConnection(
  713. Command\RawCommand::create('get', 'key')
  714. ));
  715. }
  716. /**
  717. * @group disconnected
  718. * @expectedException Predis\Replication\RoleException
  719. * @expectedExceptionMessage Expected master but got slave [127.0.0.1:6381]
  720. */
  721. public function testGetConnectionThrowsExceptionOnNodeRoleMismatch()
  722. {
  723. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  724. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  725. $master->expects($this->once())
  726. ->method('isConnected')
  727. ->will($this->returnValue(false));
  728. $master->expects($this->at(2))
  729. ->method('executeCommand')
  730. ->with($this->isRedisCommand('ROLE'))
  731. ->will($this->returnValue(array(
  732. 'slave', '127.0.0.1', 9000, 'connected', 3167038,
  733. )));
  734. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  735. $replication->add($master);
  736. $replication->getConnection(Command\RawCommand::create('del', 'key'));
  737. }
  738. /**
  739. * @group disconnected
  740. */
  741. public function testGetConnectionReturnsMasterForReadOnlyOperationsOnUnavailableSlaves()
  742. {
  743. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  744. $sentinel1->expects($this->once())
  745. ->method('executeCommand')
  746. ->with($this->isRedisCommand(
  747. 'SENTINEL', array('slaves', 'svc')
  748. ))
  749. ->will($this->returnValue(
  750. array(
  751. array(
  752. 'name', '127.0.0.1:6382',
  753. 'ip', '127.0.0.1',
  754. 'port', '6382',
  755. 'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
  756. 'flags', 'slave,s_down,disconnected',
  757. 'master-host', '127.0.0.1',
  758. 'master-port', '6381',
  759. ),
  760. )
  761. ));
  762. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  763. $master->expects($this->once())
  764. ->method('isConnected')
  765. ->will($this->returnValue(false));
  766. $master->expects($this->at(2))
  767. ->method('executeCommand')
  768. ->with($this->isRedisCommand('ROLE'))
  769. ->will($this->returnValue(array(
  770. 'master', '0', array(),
  771. )));
  772. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  773. $replication->add($master);
  774. $replication->getConnection(Command\RawCommand::create('get', 'key'));
  775. }
  776. /**
  777. * @group disconnected
  778. */
  779. public function testMethodExecuteCommandSendsCommandToNodeAndReturnsResponse()
  780. {
  781. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  782. $cmdGet = Command\RawCommand::create('get', 'key');
  783. $cmdGetResponse = 'value';
  784. $cmdSet = Command\RawCommand::create('set', 'key', 'value');
  785. $cmdSetResponse = Response\Status::get('OK');
  786. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  787. $master->expects($this->any())
  788. ->method('isConnected')
  789. ->will($this->returnValue(true));
  790. $master->expects($this->at(2))
  791. ->method('executeCommand')
  792. ->with($this->isRedisCommand('SET', array('key', $cmdGetResponse)))
  793. ->will($this->returnValue($cmdSetResponse));
  794. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  795. $slave1->expects($this->any())
  796. ->method('isConnected')
  797. ->will($this->returnValue(true));
  798. $slave1->expects($this->at(2))
  799. ->method('executeCommand')
  800. ->with($this->isRedisCommand('GET', array('key')))
  801. ->will($this->returnValue($cmdGetResponse));
  802. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  803. $replication->add($master);
  804. $replication->add($slave1);
  805. $this->assertSame($cmdGetResponse, $replication->executeCommand($cmdGet));
  806. $this->assertSame($cmdSetResponse, $replication->executeCommand($cmdSet));
  807. }
  808. /**
  809. * @group disconnected
  810. */
  811. public function testMethodExecuteCommandRetriesReadOnlyCommandOnNextSlaveOnFailure()
  812. {
  813. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  814. $sentinel1->expects($this->any())
  815. ->method('executeCommand')
  816. ->with($this->isRedisCommand(
  817. 'SENTINEL', array('slaves', 'svc')
  818. ))
  819. ->will($this->returnValue(
  820. array(
  821. array(
  822. 'name', '127.0.0.1:6383',
  823. 'ip', '127.0.0.1',
  824. 'port', '6383',
  825. 'runid', '1c0bf1291797fbc5608c07a17da394147dc62817',
  826. 'flags', 'slave',
  827. 'master-host', '127.0.0.1',
  828. 'master-port', '6381',
  829. ),
  830. )
  831. ));
  832. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  833. $master->expects($this->any())
  834. ->method('isConnected')
  835. ->will($this->returnValue(true));
  836. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  837. $slave1->expects($this->any())
  838. ->method('isConnected')
  839. ->will($this->returnValue(true));
  840. $slave1->expects($this->at(2))
  841. ->method('executeCommand')
  842. ->with($this->isRedisCommand('GET', array('key')))
  843. ->will($this->throwException(
  844. new Connection\ConnectionException($slave1, 'Unknown connection error [127.0.0.1:6382]')
  845. ));
  846. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  847. $slave2->expects($this->any())
  848. ->method('isConnected')
  849. ->will($this->returnValue(true));
  850. $slave2->expects($this->at(2))
  851. ->method('executeCommand')
  852. ->with($this->isRedisCommand('GET', array('key')))
  853. ->will($this->returnValue('value'));
  854. $factory = $this->getMock('Predis\Connection\FactoryInterface');
  855. $factory->expects($this->once())
  856. ->method('create')
  857. ->with(array(
  858. 'host' => '127.0.0.1',
  859. 'port' => '6383',
  860. 'alias' => 'slave-127.0.0.1:6383',
  861. ))
  862. ->will($this->returnValue($slave2));
  863. $replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
  864. $replication->add($master);
  865. $replication->add($slave1);
  866. $this->assertSame('value', $replication->executeCommand(
  867. Command\RawCommand::create('get', 'key')
  868. ));
  869. }
  870. /**
  871. * @group disconnected
  872. */
  873. public function testMethodExecuteCommandRetriesWriteCommandOnNewMasterOnFailure()
  874. {
  875. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  876. $sentinel1->expects($this->any())
  877. ->method('executeCommand')
  878. ->with($this->isRedisCommand(
  879. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  880. ))
  881. ->will($this->returnValue(
  882. array('127.0.0.1', '6391')
  883. ));
  884. $masterOld = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  885. $masterOld->expects($this->any())
  886. ->method('isConnected')
  887. ->will($this->returnValue(true));
  888. $masterOld->expects($this->at(2))
  889. ->method('executeCommand')
  890. ->with($this->isRedisCommand('DEL', array('key')))
  891. ->will($this->throwException(
  892. new Connection\ConnectionException($masterOld, 'Unknown connection error [127.0.0.1:6381]')
  893. ));
  894. $masterNew = $this->getMockConnection('tcp://127.0.0.1:6391?alias=master');
  895. $masterNew->expects($this->any())
  896. ->method('isConnected')
  897. ->will($this->returnValue(true));
  898. $masterNew->expects($this->at(2))
  899. ->method('executeCommand')
  900. ->with($this->isRedisCommand('DEL', array('key')))
  901. ->will($this->returnValue(1));
  902. $factory = $this->getMock('Predis\Connection\FactoryInterface');
  903. $factory->expects($this->once())
  904. ->method('create')
  905. ->with(array(
  906. 'host' => '127.0.0.1',
  907. 'port' => '6391',
  908. 'alias' => 'master',
  909. ))
  910. ->will($this->returnValue($masterNew));
  911. $replication = $this->getReplicationConnection('svc', array($sentinel1), $factory);
  912. $replication->add($masterOld);
  913. $this->assertSame(1, $replication->executeCommand(
  914. Command\RawCommand::create('del', 'key')
  915. ));
  916. }
  917. /**
  918. * @group disconnected
  919. * @expectedException Predis\Response\ServerException
  920. * @expectedExceptionMessage ERR No such master with that name
  921. */
  922. public function testMethodExecuteCommandThrowsExceptionOnUnknownServiceName()
  923. {
  924. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  925. $sentinel1->expects($this->any())
  926. ->method('executeCommand')
  927. ->with($this->isRedisCommand(
  928. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  929. ))
  930. ->will($this->returnValue(null));
  931. $masterOld = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  932. $masterOld->expects($this->any())
  933. ->method('isConnected')
  934. ->will($this->returnValue(true));
  935. $masterOld->expects($this->at(2))
  936. ->method('executeCommand')
  937. ->with($this->isRedisCommand('DEL', array('key')))
  938. ->will($this->throwException(
  939. new Connection\ConnectionException($masterOld, 'Unknown connection error [127.0.0.1:6381]')
  940. ));
  941. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  942. $replication->add($masterOld);
  943. $replication->executeCommand(
  944. Command\RawCommand::create('del', 'key')
  945. );
  946. }
  947. /**
  948. * @group disconnected
  949. * @expectedException Predis\ClientException
  950. * @expectedExceptionMessage No sentinel server available for autodiscovery.
  951. */
  952. public function testMethodExecuteCommandThrowsExceptionOnConnectionFailureAndNoAvailableSentinels()
  953. {
  954. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  955. $sentinel1->expects($this->any())
  956. ->method('executeCommand')
  957. ->with($this->isRedisCommand(
  958. 'SENTINEL', array('get-master-addr-by-name', 'svc')
  959. ))
  960. ->will($this->throwException(
  961. new Connection\ConnectionException($sentinel1, 'Unknown connection error [127.0.0.1:5381]')
  962. ));
  963. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  964. $master->expects($this->any())
  965. ->method('isConnected')
  966. ->will($this->returnValue(true));
  967. $master->expects($this->at(2))
  968. ->method('executeCommand')
  969. ->with($this->isRedisCommand('DEL', array('key')))
  970. ->will($this->throwException(
  971. new Connection\ConnectionException($master, 'Unknown connection error [127.0.0.1:6381]')
  972. ));
  973. $replication = $this->getReplicationConnection('svc', array($sentinel1));
  974. $replication->add($master);
  975. $replication->executeCommand(
  976. Command\RawCommand::create('del', 'key')
  977. );
  978. }
  979. /**
  980. * @group disconnected
  981. */
  982. public function testMethodGetReplicationStrategyReturnsInstance()
  983. {
  984. $strategy = new Replication\ReplicationStrategy();
  985. $factory = new Connection\Factory();
  986. $replication = new SentinelReplication(
  987. 'svc', array('tcp://127.0.0.1:5381?alias=sentinel1'), $factory, $strategy
  988. );
  989. $this->assertSame($strategy, $replication->getReplicationStrategy());
  990. }
  991. /**
  992. * @group disconnected
  993. */
  994. public function testMethodSerializeCanSerializeWholeObject()
  995. {
  996. $sentinel1 = $this->getMockSentinelConnection('tcp://127.0.0.1:5381?alias=sentinel1');
  997. $master = $this->getMockConnection('tcp://127.0.0.1:6381?alias=master');
  998. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?alias=slave1');
  999. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?alias=slave2');
  1000. $strategy = new Replication\ReplicationStrategy();
  1001. $factory = new Connection\Factory();
  1002. $replication = new SentinelReplication('svc', array($sentinel1), $factory, $strategy);
  1003. $replication->add($master);
  1004. $replication->add($slave1);
  1005. $replication->add($slave2);
  1006. $unserialized = unserialize(serialize($replication));
  1007. $this->assertEquals($master, $unserialized->getConnectionById('master'));
  1008. $this->assertEquals($slave1, $unserialized->getConnectionById('slave1'));
  1009. $this->assertEquals($master, $unserialized->getConnectionById('slave2'));
  1010. $this->assertEquals($strategy, $unserialized->getReplicationStrategy());
  1011. }
  1012. // ******************************************************************** //
  1013. // ---- HELPER METHODS ------------------------------------------------ //
  1014. // ******************************************************************** //
  1015. /**
  1016. * Creates a new instance of replication connection.
  1017. *
  1018. * @param string $service Name of the service
  1019. * @param array $sentinels Array of sentinels
  1020. * @param ConnectionFactoryInterface|null $factory Optional connection factory instance.
  1021. *
  1022. * @return SentinelReplication
  1023. */
  1024. protected function getReplicationConnection($service, $sentinels, Connection\FactoryInterface $factory = null)
  1025. {
  1026. $factory = $factory ?: new Connection\Factory();
  1027. $replication = new SentinelReplication($service, $sentinels, $factory);
  1028. $replication->setRetryWait(0);
  1029. return $replication;
  1030. }
  1031. /**
  1032. * Returns a base mocked connection from Predis\Connection\NodeConnectionInterface.
  1033. *
  1034. * @param mixed $parameters Optional parameters.
  1035. *
  1036. * @return mixed
  1037. */
  1038. protected function getMockSentinelConnection($parameters = null)
  1039. {
  1040. $connection = $this->getMockConnection($parameters);
  1041. return $connection;
  1042. }
  1043. }