MasterSlaveReplicationTest.php 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432
  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\Replication;
  11. use Predis\Command;
  12. use Predis\Connection;
  13. use Predis\Replication\ReplicationStrategy;
  14. use Predis\Response;
  15. use PredisTestCase;
  16. /**
  17. *
  18. */
  19. class MasterSlaveReplicationTest extends PredisTestCase
  20. {
  21. /**
  22. * @group disconnected
  23. */
  24. public function testAddingConnectionsToReplication()
  25. {
  26. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  27. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  28. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6381?role=slave');
  29. $replication = new MasterSlaveReplication();
  30. $replication->add($master);
  31. $replication->add($slave1);
  32. $replication->add($slave2);
  33. $this->assertSame($master, $replication->getConnectionById('127.0.0.1:6379'));
  34. $this->assertSame($slave1, $replication->getConnectionById('127.0.0.1:6380'));
  35. $this->assertSame($slave2, $replication->getConnectionById('127.0.0.1:6381'));
  36. $this->assertSame($master, $replication->getMaster());
  37. $this->assertSame(array($slave1, $slave2), $replication->getSlaves());
  38. }
  39. /**
  40. * @group disconnected
  41. */
  42. public function testAddingConnectionsWithoutRoleParameterDefaultsToSlaveRole()
  43. {
  44. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380');
  45. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6381');
  46. $replication = new MasterSlaveReplication();
  47. $replication->add($slave1);
  48. $replication->add($slave2);
  49. $this->assertSame(array($slave1, $slave2), $replication->getSlaves());
  50. }
  51. /**
  52. * @group disconnected
  53. */
  54. public function testRemovingConnectionsFromReplication()
  55. {
  56. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  57. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  58. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6381?role=slave');
  59. $replication = new MasterSlaveReplication();
  60. $replication->add($master);
  61. $replication->add($slave1);
  62. $this->assertTrue($replication->remove($slave1));
  63. $this->assertFalse($replication->remove($slave2));
  64. $this->assertSame($master, $replication->getMaster());
  65. $this->assertSame(array(), $replication->getSlaves());
  66. }
  67. /**
  68. * @group disconnected
  69. */
  70. public function testGetConnectionByIdOnEmptyReplication()
  71. {
  72. $replication = new MasterSlaveReplication();
  73. $this->assertNull($replication->getConnectionById('127.0.0.1:6379'));
  74. }
  75. /**
  76. * @group disconnected
  77. */
  78. public function testGetConnectionByAlias()
  79. {
  80. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6379?alias=aliased');
  81. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6380');
  82. $replication = new MasterSlaveReplication();
  83. $replication->add($slave1);
  84. $replication->add($slave2);
  85. $this->assertSame($slave1, $replication->getConnectionByAlias('aliased'));
  86. $this->assertNull($replication->getConnectionByAlias('127.0.0.1:6380'));
  87. $this->assertNull($replication->getConnectionByAlias('unkswn'));
  88. }
  89. /**
  90. * @group disconnected
  91. */
  92. public function testGetConnectionByAliasOnEmptyReplication()
  93. {
  94. $replication = new MasterSlaveReplication();
  95. $this->assertNull($replication->getConnectionByAlias('unknown'));
  96. }
  97. /**
  98. * @group disconnected
  99. */
  100. public function testGetConnectionByRole()
  101. {
  102. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  103. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  104. $replication = new MasterSlaveReplication();
  105. $replication->add($master);
  106. $replication->add($slave1);
  107. $this->assertSame($master, $replication->getConnectionByRole('master'));
  108. $this->assertSame($slave1, $replication->getConnectionByRole('slave'));
  109. }
  110. /**
  111. * @group disconnected
  112. */
  113. public function testGetConnectionByRoleOnEmptyReplication()
  114. {
  115. $replication = new MasterSlaveReplication();
  116. $this->assertNull($replication->getConnectionByRole('master'));
  117. $this->assertNull($replication->getConnectionByRole('slave'));
  118. }
  119. /**
  120. * @group disconnected
  121. */
  122. public function testGetConnectionByRoleUnknown()
  123. {
  124. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  125. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  126. $replication = new MasterSlaveReplication();
  127. $replication->add($master);
  128. $replication->add($slave1);
  129. $this->assertNull($replication->getConnectionByRole('unknown'));
  130. }
  131. /**
  132. * @group disconnected
  133. * @expectedException \Predis\ClientException
  134. * @expectedExceptionMessage No available connection for replication
  135. */
  136. public function testThrowsExceptionOnEmptyReplication()
  137. {
  138. $replication = new MasterSlaveReplication();
  139. $replication->connect();
  140. }
  141. /**
  142. * @group disconnected
  143. */
  144. public function testConnectsToOneOfSlaves()
  145. {
  146. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  147. $master
  148. ->expects($this->never())
  149. ->method('connect');
  150. $slave = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  151. $slave
  152. ->expects($this->once())
  153. ->method('connect');
  154. $replication = new MasterSlaveReplication();
  155. $replication->add($master);
  156. $replication->add($slave);
  157. $replication->connect();
  158. }
  159. /**
  160. * @group disconnected
  161. */
  162. public function testConnectsToMasterOnMissingSlaves()
  163. {
  164. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  165. $replication = new MasterSlaveReplication();
  166. $replication->add($master);
  167. $replication->connect();
  168. $this->assertSame($master, $replication->getCurrent());
  169. }
  170. /**
  171. * @group disconnected
  172. */
  173. public function testIsConnectedReturnsTrueIfAtLeastOneConnectionIsOpen()
  174. {
  175. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  176. $master
  177. ->expects($this->never())
  178. ->method('isConnected')
  179. ->will($this->returnValue(false));
  180. $slave = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  181. $slave
  182. ->expects($this->once())
  183. ->method('isConnected')
  184. ->will($this->returnValue(true));
  185. $replication = new MasterSlaveReplication();
  186. $replication->add($master);
  187. $replication->add($slave);
  188. $replication->connect();
  189. $this->assertTrue($replication->isConnected());
  190. }
  191. /**
  192. * @group disconnected
  193. */
  194. public function testIsConnectedReturnsFalseIfAllConnectionsAreClosed()
  195. {
  196. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  197. $master
  198. ->expects($this->any())
  199. ->method('isConnected')
  200. ->will($this->returnValue(false));
  201. $slave = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  202. $slave
  203. ->expects($this->any())
  204. ->method('isConnected')
  205. ->will($this->returnValue(false));
  206. $replication = new MasterSlaveReplication();
  207. $replication->add($master);
  208. $replication->add($slave);
  209. $this->assertFalse($replication->isConnected());
  210. $replication->connect();
  211. $replication->disconnect();
  212. $this->assertFalse($replication->isConnected());
  213. }
  214. /**
  215. * @group disconnected
  216. */
  217. public function testDisconnectForcesCurrentConnectionToDisconnect()
  218. {
  219. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  220. $master
  221. ->expects($this->once())
  222. ->method('disconnect');
  223. $slave = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  224. $slave
  225. ->expects($this->once())
  226. ->method('disconnect');
  227. $replication = new MasterSlaveReplication();
  228. $replication->add($master);
  229. $replication->add($slave);
  230. $replication->disconnect();
  231. }
  232. /**
  233. * @group disconnected
  234. */
  235. public function testCanSwitchConnection()
  236. {
  237. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  238. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  239. $replication = new MasterSlaveReplication();
  240. $replication->add($master);
  241. $replication->add($slave1);
  242. $this->assertNull($replication->getCurrent());
  243. $replication->switchTo($master);
  244. $this->assertSame($master, $replication->getCurrent());
  245. $replication->switchTo($slave1);
  246. $this->assertSame($slave1, $replication->getCurrent());
  247. }
  248. /**
  249. * @group disconnected
  250. * @expectedException \InvalidArgumentException
  251. * @expectedExceptionMessage Invalid connection or connection not found.
  252. */
  253. public function testThrowsErrorWhenSwitchingToConnectionNotInPool()
  254. {
  255. $replication = new MasterSlaveReplication();
  256. $replication->add($this->getMockConnection('tcp://127.0.0.1:6379?role=master'));
  257. $replication->add($this->getMockConnection('tcp://127.0.0.1:6380?role=slave'));
  258. $unknown = $this->getMockConnection('tcp://127.0.0.1:6381');
  259. $replication->switchTo($unknown);
  260. }
  261. /**
  262. * @group disconnected
  263. */
  264. public function testCanSwitchConnectionByInstance()
  265. {
  266. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  267. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  268. $replication = new MasterSlaveReplication();
  269. $replication->add($master);
  270. $replication->add($slave1);
  271. $this->assertNull($replication->getCurrent());
  272. $replication->switchTo($master);
  273. $this->assertSame($master, $replication->getCurrent());
  274. $replication->switchTo($slave1);
  275. $this->assertSame($slave1, $replication->getCurrent());
  276. }
  277. /**
  278. * @group disconnected
  279. * @expectedException \InvalidArgumentException
  280. * @expectedExceptionMessage Invalid connection or connection not found.
  281. */
  282. public function testThrowsErrorWhenSwitchingToUnknownConnectionByInstance()
  283. {
  284. $replication = new MasterSlaveReplication();
  285. $replication->add($this->getMockConnection('tcp://127.0.0.1:6379?role=master'));
  286. $replication->add($this->getMockConnection('tcp://127.0.0.1:6380?role=slave'));
  287. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6381');
  288. $replication->switchTo($slave2);
  289. }
  290. /**
  291. * @group disconnected
  292. */
  293. public function testCanSwitchToMaster()
  294. {
  295. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  296. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  297. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6381?role=slave');
  298. $replication = new MasterSlaveReplication();
  299. $replication->add($master);
  300. $replication->add($slave1);
  301. $replication->add($slave2);
  302. $this->assertNull($replication->getCurrent());
  303. $replication->switchToMaster();
  304. $this->assertSame($master, $replication->getCurrent());
  305. }
  306. /**
  307. * @group disconnected
  308. * @expectedException \InvalidArgumentException
  309. * @expectedExceptionMessage Invalid connection or connection not found.
  310. */
  311. public function testThrowsErrorOnSwitchToMasterWithNoMasterDefined()
  312. {
  313. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  314. $replication = new MasterSlaveReplication();
  315. $replication->add($slave1);
  316. $replication->switchToMaster();
  317. }
  318. /**
  319. * @group disconnected
  320. *
  321. * @todo We should find a way to test that the slave is indeed randomly selected.
  322. */
  323. public function testCanSwitchToRandomSlave()
  324. {
  325. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  326. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  327. $replication = new MasterSlaveReplication();
  328. $replication->add($master);
  329. $replication->add($slave1);
  330. $this->assertNull($replication->getCurrent());
  331. $replication->switchToSlave();
  332. $this->assertSame($slave1, $replication->getCurrent());
  333. }
  334. /**
  335. * @group disconnected
  336. * @expectedException \InvalidArgumentException
  337. * @expectedExceptionMessage Invalid connection or connection not found.
  338. */
  339. public function testThrowsErrorOnSwitchToRandomSlaveWithNoSlavesDefined()
  340. {
  341. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  342. $replication = new MasterSlaveReplication();
  343. $replication->add($master);
  344. $replication->switchToSlave();
  345. }
  346. /**
  347. * @group disconnected
  348. */
  349. public function testUsesSlavesOnReadOnlyCommands()
  350. {
  351. $commands = $this->getCommandFactory();
  352. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  353. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  354. $replication = new MasterSlaveReplication();
  355. $replication->add($master);
  356. $replication->add($slave1);
  357. $cmd = $commands->createCommand('exists', array('foo'));
  358. $this->assertSame($slave1, $replication->getConnectionByCommand($cmd));
  359. $cmd = $commands->createCommand('get', array('foo'));
  360. $this->assertSame($slave1, $replication->getConnectionByCommand($cmd));
  361. }
  362. /**
  363. * @group disconnected
  364. */
  365. public function testUsesMasterOnWriteRequests()
  366. {
  367. $commands = $this->getCommandFactory();
  368. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  369. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  370. $replication = new MasterSlaveReplication();
  371. $replication->add($master);
  372. $replication->add($slave1);
  373. $cmd = $commands->createCommand('set', array('foo', 'bar'));
  374. $this->assertSame($master, $replication->getConnectionByCommand($cmd));
  375. $cmd = $commands->createCommand('get', array('foo'));
  376. $this->assertSame($master, $replication->getConnectionByCommand($cmd));
  377. }
  378. /**
  379. * @group disconnected
  380. */
  381. public function testUsesMasterOnReadRequestsWhenNoSlavesAvailable()
  382. {
  383. $commands = $this->getCommandFactory();
  384. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  385. $replication = new MasterSlaveReplication();
  386. $replication->add($master);
  387. $cmd = $commands->createCommand('exists', array('foo'));
  388. $this->assertSame($master, $replication->getConnectionByCommand($cmd));
  389. $cmd = $commands->createCommand('set', array('foo', 'bar'));
  390. $this->assertSame($master, $replication->getConnectionByCommand($cmd));
  391. }
  392. /**
  393. * @group disconnected
  394. */
  395. public function testSwitchesFromSlaveToMasterOnWriteRequests()
  396. {
  397. $commands = $this->getCommandFactory();
  398. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  399. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave1');
  400. $replication = new MasterSlaveReplication();
  401. $replication->add($master);
  402. $replication->add($slave1);
  403. $cmd = $commands->createCommand('exists', array('foo'));
  404. $this->assertSame($slave1, $replication->getConnectionByCommand($cmd));
  405. $cmd = $commands->createCommand('set', array('foo', 'bar'));
  406. $this->assertSame($master, $replication->getConnectionByCommand($cmd));
  407. $cmd = $commands->createCommand('exists', array('foo'));
  408. $this->assertSame($master, $replication->getConnectionByCommand($cmd));
  409. }
  410. /**
  411. * @group disconnected
  412. */
  413. public function testWritesCommandToCorrectConnection()
  414. {
  415. $commands = $this->getCommandFactory();
  416. $cmdExists = $commands->createCommand('exists', array('foo'));
  417. $cmdSet = $commands->createCommand('set', array('foo', 'bar'));
  418. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  419. $master
  420. ->expects($this->once())
  421. ->method('writeRequest')
  422. ->with($cmdSet);
  423. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  424. $slave1
  425. ->expects($this->once())
  426. ->method('writeRequest')
  427. ->with($cmdExists);
  428. $replication = new MasterSlaveReplication();
  429. $replication->add($master);
  430. $replication->add($slave1);
  431. $replication->writeRequest($cmdExists);
  432. $replication->writeRequest($cmdSet);
  433. }
  434. /**
  435. * @group disconnected
  436. */
  437. public function testReadsCommandFromCorrectConnection()
  438. {
  439. $commands = $this->getCommandFactory();
  440. $cmdExists = $commands->createCommand('exists', array('foo'));
  441. $cmdSet = $commands->createCommand('set', array('foo', 'bar'));
  442. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  443. $master
  444. ->expects($this->once())
  445. ->method('readResponse')
  446. ->with($cmdSet);
  447. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  448. $slave1
  449. ->expects($this->once())
  450. ->method('readResponse')
  451. ->with($cmdExists);
  452. $replication = new MasterSlaveReplication();
  453. $replication->add($master);
  454. $replication->add($slave1);
  455. $replication->readResponse($cmdExists);
  456. $replication->readResponse($cmdSet);
  457. }
  458. /**
  459. * @group disconnected
  460. */
  461. public function testExecutesCommandOnCorrectConnection()
  462. {
  463. $commands = $this->getCommandFactory();
  464. $cmdExists = $commands->createCommand('exists', array('foo'));
  465. $cmdSet = $commands->createCommand('set', array('foo', 'bar'));
  466. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  467. $master
  468. ->expects($this->once())
  469. ->method('executeCommand')
  470. ->with($cmdSet);
  471. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  472. $slave1
  473. ->expects($this->once())
  474. ->method('executeCommand')
  475. ->with($cmdExists);
  476. $replication = new MasterSlaveReplication();
  477. $replication->add($master);
  478. $replication->add($slave1);
  479. $replication->executeCommand($cmdExists);
  480. $replication->executeCommand($cmdSet);
  481. }
  482. /**
  483. * @group disconnected
  484. */
  485. public function testWatchTriggersSwitchToMasterConnection()
  486. {
  487. $commands = $this->getCommandFactory();
  488. $cmdWatch = $commands->createCommand('watch', array('foo'));
  489. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  490. $master
  491. ->expects($this->once())
  492. ->method('executeCommand')
  493. ->with($cmdWatch);
  494. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  495. $slave1
  496. ->expects($this->never())
  497. ->method('executeCommand');
  498. $replication = new MasterSlaveReplication();
  499. $replication->add($master);
  500. $replication->add($slave1);
  501. $replication->executeCommand($cmdWatch);
  502. }
  503. /**
  504. * @group disconnected
  505. */
  506. public function testMultiTriggersSwitchToMasterConnection()
  507. {
  508. $commands = $this->getCommandFactory();
  509. $cmdMulti = $commands->createCommand('multi');
  510. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  511. $master
  512. ->expects($this->once())
  513. ->method('executeCommand')
  514. ->with($cmdMulti);
  515. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  516. $slave1
  517. ->expects($this->never())
  518. ->method('executeCommand');
  519. $replication = new MasterSlaveReplication();
  520. $replication->add($master);
  521. $replication->add($slave1);
  522. $replication->executeCommand($cmdMulti);
  523. }
  524. /**
  525. * @group disconnected
  526. */
  527. public function testEvalTriggersSwitchToMasterConnection()
  528. {
  529. $commands = $this->getCommandFactory();
  530. $cmdEval = $commands->createCommand('eval', array("return redis.call('info')"));
  531. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  532. $master
  533. ->expects($this->once())
  534. ->method('executeCommand')
  535. ->with($cmdEval);
  536. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  537. $slave1
  538. ->expects($this->never())
  539. ->method('executeCommand');
  540. $replication = new MasterSlaveReplication();
  541. $replication->add($master);
  542. $replication->add($slave1);
  543. $replication->executeCommand($cmdEval);
  544. }
  545. /**
  546. * @group disconnected
  547. */
  548. public function testSortTriggersSwitchToMasterConnectionOnStoreModifier()
  549. {
  550. $commands = $this->getCommandFactory();
  551. $cmdSortNormal = $commands->createCommand('sort', array('key'));
  552. $cmdSortStore = $commands->createCommand('sort', array('key', array('store' => 'key:store')));
  553. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  554. $master
  555. ->expects($this->once())
  556. ->method('executeCommand')
  557. ->with($cmdSortStore);
  558. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  559. $slave1
  560. ->expects($this->once())
  561. ->method('executeCommand')
  562. ->with($cmdSortNormal);
  563. $replication = new MasterSlaveReplication();
  564. $replication->add($master);
  565. $replication->add($slave1);
  566. $replication->executeCommand($cmdSortNormal);
  567. $replication->executeCommand($cmdSortStore);
  568. }
  569. /**
  570. * @group disconnected
  571. */
  572. public function testDiscardsUnreachableSlaveAndExecutesReadOnlyCommandOnNextSlave()
  573. {
  574. $commands = $this->getCommandFactory();
  575. $cmdExists = $commands->createCommand('exists', array('key'));
  576. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  577. $master
  578. ->expects($this->never())
  579. ->method('executeCommand');
  580. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave&role=slave');
  581. $slave1
  582. ->expects($this->once())
  583. ->method('executeCommand')
  584. ->with($cmdExists)
  585. ->will($this->throwException(
  586. new Connection\ConnectionException($slave1)
  587. ));
  588. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6381?role=slave&alias=slave2');
  589. $slave2
  590. ->expects($this->once())
  591. ->method('executeCommand')
  592. ->with($cmdExists)
  593. ->will($this->returnValue(1));
  594. $replication = new MasterSlaveReplication();
  595. $replication->add($master);
  596. $replication->add($slave1);
  597. $replication->add($slave2);
  598. $replication->switchTo($slave1);
  599. $response = $replication->executeCommand($cmdExists);
  600. $this->assertSame(1, $response);
  601. $this->assertNull($replication->getConnectionByAlias('slave1'));
  602. $this->assertSame($slave2, $replication->getConnectionByAlias('slave2'));
  603. }
  604. /**
  605. * @group disconnected
  606. */
  607. public function testDiscardsUnreachableSlavesAndExecutesReadOnlyCommandOnMaster()
  608. {
  609. $commands = $this->getCommandFactory();
  610. $cmdExists = $commands->createCommand('exists', array('key'));
  611. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  612. $master
  613. ->expects($this->once())
  614. ->method('executeCommand')
  615. ->with($cmdExists)
  616. ->will($this->returnValue(1));
  617. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  618. $slave1
  619. ->expects($this->once())
  620. ->method('executeCommand')
  621. ->with($cmdExists)
  622. ->will($this->throwException(new Connection\ConnectionException($slave1)));
  623. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6381?role=slave');
  624. $slave2
  625. ->expects($this->once())
  626. ->method('executeCommand')
  627. ->with($cmdExists)
  628. ->will($this->throwException(
  629. new Connection\ConnectionException($slave2)
  630. ));
  631. $replication = new MasterSlaveReplication();
  632. $replication->add($master);
  633. $replication->add($slave1);
  634. $replication->add($slave2);
  635. $replication->switchTo($slave1);
  636. $response = $replication->executeCommand($cmdExists);
  637. $this->assertSame(1, $response);
  638. $this->assertNull($replication->getConnectionById('127.0.0.1:6380'));
  639. $this->assertNull($replication->getConnectionById('127.0.0.1:6381'));
  640. }
  641. /**
  642. * @group disconnected
  643. */
  644. public function testSucceedOnReadOnlyCommandAndNoConnectionSetAsMaster()
  645. {
  646. $commands = $this->getCommandFactory();
  647. $cmdExists = $commands->createCommand('exists', array('key'));
  648. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6379?role=slave');
  649. $slave1
  650. ->expects($this->once())
  651. ->method('executeCommand')
  652. ->with($cmdExists)
  653. ->will($this->returnValue(1));
  654. $replication = new MasterSlaveReplication();
  655. $replication->add($slave1);
  656. $response = $replication->executeCommand($cmdExists);
  657. $this->assertSame(1, $response);
  658. }
  659. /**
  660. * @group disconnected
  661. * @expectedException \Predis\Replication\MissingMasterException
  662. * @expectedMessage No master server available for replication
  663. */
  664. public function testFailsOnWriteCommandAndNoConnectionSetAsMaster()
  665. {
  666. $commands = $this->getCommandFactory();
  667. $cmdSet = $commands->createCommand('set', array('key', 'value'));
  668. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6379?role=slave');
  669. $slave1
  670. ->expects($this->never())
  671. ->method('executeCommand');
  672. $replication = new MasterSlaveReplication();
  673. $replication->add($slave1);
  674. $replication->executeCommand($cmdSet);
  675. }
  676. /**
  677. * @group disconnected
  678. */
  679. public function testDiscardsSlaveWhenRespondsLOADINGAndExecutesReadOnlyCommandOnNextSlave()
  680. {
  681. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  682. $master->expects($this->never())
  683. ->method('executeCommand');
  684. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  685. $slave1
  686. ->expects($this->once())
  687. ->method('executeCommand')
  688. ->with($this->isRedisCommand(
  689. 'EXISTS', array('key')
  690. ))
  691. ->will($this->returnValue(
  692. new Response\Error('LOADING')
  693. ));
  694. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6381?role=slave');
  695. $slave2
  696. ->expects($this->once())
  697. ->method('executeCommand')
  698. ->with($this->isRedisCommand(
  699. 'EXISTS', array('key')
  700. ))
  701. ->will($this->returnValue(1));
  702. $replication = new MasterSlaveReplication();
  703. $replication->add($master);
  704. $replication->add($slave1);
  705. $replication->add($slave2);
  706. $replication->switchTo($slave1);
  707. $response = $replication->executeCommand(
  708. Command\RawCommand::create('exists', 'key')
  709. );
  710. $this->assertSame(1, $response);
  711. $this->assertNull($replication->getConnectionById('127.0.0.1:6380'));
  712. $this->assertSame($slave2, $replication->getConnectionById('127.0.0.1:6381'));
  713. }
  714. /**
  715. * @group disconnected
  716. * @expectedException \Predis\Connection\ConnectionException
  717. */
  718. public function testFailsOnUnreachableMaster()
  719. {
  720. $commands = $this->getCommandFactory();
  721. $cmdSet = $commands->createCommand('set', array('key', 'value'));
  722. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  723. $master
  724. ->expects($this->once())
  725. ->method('executeCommand')
  726. ->with($cmdSet)
  727. ->will($this->throwException(
  728. new Connection\ConnectionException($master)
  729. ));
  730. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  731. $slave1
  732. ->expects($this->never())
  733. ->method('executeCommand');
  734. $replication = new MasterSlaveReplication();
  735. $replication->add($master);
  736. $replication->add($slave1);
  737. $replication->executeCommand($cmdSet);
  738. }
  739. /**
  740. * @group disconnected
  741. * @expectedException \Predis\NotSupportedException
  742. * @expectedExceptionMessage The command 'INFO' is not allowed in replication mode.
  743. */
  744. public function testThrowsExceptionOnNonSupportedCommand()
  745. {
  746. $cmd = $this->getCommandFactory()->createCommand('info');
  747. $replication = new MasterSlaveReplication();
  748. $replication->add($this->getMockConnection('tcp://127.0.0.1:6379?role=master'));
  749. $replication->add($this->getMockConnection('tcp://127.0.0.1:6380?role=slave'));
  750. $replication->getConnectionByCommand($cmd);
  751. }
  752. /**
  753. * @group disconnected
  754. */
  755. public function testCanOverrideReadOnlyFlagForCommands()
  756. {
  757. $commands = $this->getCommandFactory();
  758. $cmdSet = $commands->createCommand('set', array('foo', 'bar'));
  759. $cmdGet = $commands->createCommand('get', array('foo'));
  760. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  761. $master
  762. ->expects($this->once())
  763. ->method('executeCommand')
  764. ->with($cmdGet);
  765. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  766. $slave1
  767. ->expects($this->once())
  768. ->method('executeCommand')
  769. ->with($cmdSet);
  770. $replication = new MasterSlaveReplication();
  771. $replication->add($master);
  772. $replication->add($slave1);
  773. $replication->getReplicationStrategy()->setCommandReadOnly($cmdSet->getId(), true);
  774. $replication->getReplicationStrategy()->setCommandReadOnly($cmdGet->getId(), false);
  775. $replication->executeCommand($cmdSet);
  776. $replication->executeCommand($cmdGet);
  777. }
  778. /**
  779. * @group disconnected
  780. */
  781. public function testAcceptsCallableToOverrideReadOnlyFlagForCommands()
  782. {
  783. $commands = $this->getCommandFactory();
  784. $cmdExistsFoo = $commands->createCommand('exists', array('foo'));
  785. $cmdExistsBar = $commands->createCommand('exists', array('bar'));
  786. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  787. $master
  788. ->expects($this->once())
  789. ->method('executeCommand')
  790. ->with($cmdExistsBar);
  791. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  792. $slave1
  793. ->expects($this->once())
  794. ->method('executeCommand')
  795. ->with($cmdExistsFoo);
  796. $replication = new MasterSlaveReplication();
  797. $replication->add($master);
  798. $replication->add($slave1);
  799. $replication
  800. ->getReplicationStrategy()
  801. ->setCommandReadOnly('exists', function ($cmd) {
  802. list($arg1) = $cmd->getArguments();
  803. return $arg1 === 'foo';
  804. });
  805. $replication->executeCommand($cmdExistsFoo);
  806. $replication->executeCommand($cmdExistsBar);
  807. }
  808. /**
  809. * @group disconnected
  810. */
  811. public function testCanSetReadOnlyFlagForEvalScripts()
  812. {
  813. $commands = $this->getCommandFactory();
  814. $cmdEval = $commands->createCommand('eval', array($script = "return redis.call('info');"));
  815. $cmdEvalSha = $commands->createCommand('evalsha', array($scriptSHA1 = sha1($script)));
  816. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  817. $master
  818. ->expects($this->never())
  819. ->method('executeCommand');
  820. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  821. $slave1
  822. ->expects($this->exactly(2))
  823. ->method('executeCommand')
  824. ->with(
  825. $this->logicalOr($cmdEval, $cmdEvalSha)
  826. );
  827. $replication = new MasterSlaveReplication();
  828. $replication->add($master);
  829. $replication->add($slave1);
  830. $replication
  831. ->getReplicationStrategy()
  832. ->setScriptReadOnly($script);
  833. $replication->executeCommand($cmdEval);
  834. $replication->executeCommand($cmdEvalSha);
  835. }
  836. /**
  837. * @group disconnected
  838. * @expectedException \Predis\ClientException
  839. * @expectedMessage Discovery requires a connection factory
  840. */
  841. public function testDiscoveryRequiresConnectionFactory()
  842. {
  843. $replication = new MasterSlaveReplication();
  844. $replication->add($this->getMockConnection('tcp://127.0.0.1:6379?role=master'));
  845. $replication->discover();
  846. }
  847. /**
  848. * @group disconnected
  849. */
  850. public function testDiscoversReplicationConfigurationFromMaster()
  851. {
  852. $connFactory = new Connection\Factory();
  853. $cmdInfo = Command\RawCommand::create('INFO', 'REPLICATION');
  854. $master = $this->getMockConnection('tcp://127.0.0.1:6381?role=master');
  855. $master
  856. ->expects($this->once())
  857. ->method('executeCommand')
  858. ->with($cmdInfo)
  859. ->will($this->returnValue('
  860. # Replication
  861. role:master
  862. connected_slaves:2
  863. slave0:ip=127.0.0.1,port=6382,state=online,offset=12979,lag=0
  864. slave1:ip=127.0.0.1,port=6383,state=online,offset=12979,lag=1
  865. master_repl_offset:12979
  866. repl_backlog_active:1
  867. repl_backlog_size:1048576
  868. repl_backlog_first_byte_offset:2
  869. repl_backlog_histlen:12978
  870. '
  871. ));
  872. $replication = new MasterSlaveReplication();
  873. $replication->setConnectionFactory($connFactory);
  874. $replication->add($master);
  875. $replication->discover();
  876. $this->assertCount(2, $slaves = $replication->getSlaves());
  877. $this->assertContainsOnlyInstancesOf('Predis\Connection\ConnectionInterface', $slaves);
  878. $this->assertSame('127.0.0.1:6381', (string) $replication->getMaster());
  879. $this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
  880. $this->assertSame('127.0.0.1:6383', (string) $slaves[1]);
  881. }
  882. /**
  883. * @group disconnected
  884. */
  885. public function testDiscoversReplicationConfigurationFromSlave()
  886. {
  887. $cmdInfo = $command = Command\RawCommand::create('INFO', 'REPLICATION');
  888. $master = $this->getMockConnection('tcp://127.0.0.1:6381?role=master');
  889. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?role=slave');
  890. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?role=slave');
  891. $connFactory = $this->getMock('Predis\Connection\Factory');
  892. $connFactory
  893. ->expects($this->at(0))
  894. ->method('create')
  895. ->with(array(
  896. 'host' => '127.0.0.1',
  897. 'port' => '6381',
  898. 'role' => 'master',
  899. ))
  900. ->will($this->returnValue($master));
  901. $connFactory
  902. ->expects($this->at(1))
  903. ->method('create')
  904. ->with(array(
  905. 'host' => '127.0.0.1',
  906. 'port' => '6382',
  907. 'role' => 'slave',
  908. ))
  909. ->will($this->returnValue($slave1));
  910. $connFactory
  911. ->expects($this->at(2))
  912. ->method('create')
  913. ->with(array(
  914. 'host' => '127.0.0.1',
  915. 'port' => '6383',
  916. 'role' => 'slave',
  917. ))
  918. ->will($this->returnValue($slave2));
  919. $slave1
  920. ->expects($this->once())
  921. ->method('executeCommand')
  922. ->with($cmdInfo)
  923. ->will($this->returnValue('
  924. # Replication
  925. role:slave
  926. master_host:127.0.0.1
  927. master_port:6381
  928. master_link_status:up
  929. master_last_io_seconds_ago:8
  930. master_sync_in_progress:0
  931. slave_repl_offset:17715532
  932. slave_priority:100
  933. slave_read_only:1
  934. connected_slaves:0
  935. master_repl_offset:0
  936. repl_backlog_active:0
  937. repl_backlog_size:1048576
  938. repl_backlog_first_byte_offset:0
  939. repl_backlog_histlen:0
  940. '
  941. ));
  942. $master
  943. ->expects($this->once())
  944. ->method('executeCommand')
  945. ->with($cmdInfo)
  946. ->will($this->returnValue('
  947. # Replication
  948. role:master
  949. connected_slaves:2
  950. slave0:ip=127.0.0.1,port=6382,state=online,offset=12979,lag=0
  951. slave1:ip=127.0.0.1,port=6383,state=online,offset=12979,lag=1
  952. master_repl_offset:12979
  953. repl_backlog_active:1
  954. repl_backlog_size:1048576
  955. repl_backlog_first_byte_offset:2
  956. repl_backlog_histlen:12978
  957. '
  958. ));
  959. $replication = new MasterSlaveReplication();
  960. $replication->setConnectionFactory($connFactory);
  961. $replication->add($slave1);
  962. $replication->discover();
  963. $this->assertCount(2, $slaves = $replication->getSlaves());
  964. $this->assertContainsOnlyInstancesOf('Predis\Connection\ConnectionInterface', $slaves);
  965. $this->assertSame('127.0.0.1:6381', (string) $replication->getMaster());
  966. $this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
  967. $this->assertSame('127.0.0.1:6383', (string) $slaves[1]);
  968. }
  969. /**
  970. * @group disconnected
  971. */
  972. public function testDiscoversReplicationConfigurationFromSlaveIfMasterFails()
  973. {
  974. $cmdInfo = $command = Command\RawCommand::create('INFO', 'REPLICATION');
  975. $masterKO = $this->getMockConnection('tcp://127.0.0.1:7381?role=master');
  976. $master = $this->getMockConnection('tcp://127.0.0.1:6381?role=master');
  977. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?role=slave');
  978. $slave2 = $this->getMockConnection('tcp://127.0.0.1:6383?role=slave');
  979. $connFactory = $this->getMock('Predis\Connection\Factory');
  980. $connFactory
  981. ->expects($this->at(0))
  982. ->method('create')
  983. ->with(array(
  984. 'host' => '127.0.0.1',
  985. 'port' => '6381',
  986. 'role' => 'master',
  987. ))
  988. ->will($this->returnValue($master));
  989. $connFactory
  990. ->expects($this->at(1))
  991. ->method('create')
  992. ->with(array(
  993. 'host' => '127.0.0.1',
  994. 'port' => '6382',
  995. 'role' => 'slave',
  996. ))
  997. ->will($this->returnValue($slave1));
  998. $connFactory
  999. ->expects($this->at(2))
  1000. ->method('create')
  1001. ->with(array(
  1002. 'host' => '127.0.0.1',
  1003. 'port' => '6383',
  1004. 'role' => 'slave',
  1005. ))
  1006. ->will($this->returnValue($slave2));
  1007. $masterKO
  1008. ->expects($this->once())
  1009. ->method('executeCommand')
  1010. ->with($cmdInfo)
  1011. ->will($this->throwException(
  1012. new Connection\ConnectionException($masterKO)
  1013. ));
  1014. $slave1
  1015. ->expects($this->once())
  1016. ->method('executeCommand')
  1017. ->with($cmdInfo)
  1018. ->will($this->returnValue('
  1019. # Replication
  1020. role:slave
  1021. master_host:127.0.0.1
  1022. master_port:6381
  1023. master_link_status:up
  1024. master_last_io_seconds_ago:8
  1025. master_sync_in_progress:0
  1026. slave_repl_offset:17715532
  1027. slave_priority:100
  1028. slave_read_only:1
  1029. connected_slaves:0
  1030. master_repl_offset:0
  1031. repl_backlog_active:0
  1032. repl_backlog_size:1048576
  1033. repl_backlog_first_byte_offset:0
  1034. repl_backlog_histlen:0
  1035. '
  1036. ));
  1037. $master
  1038. ->expects($this->once())
  1039. ->method('executeCommand')
  1040. ->with($cmdInfo)
  1041. ->will($this->returnValue('
  1042. # Replication
  1043. role:master
  1044. connected_slaves:2
  1045. slave0:ip=127.0.0.1,port=6382,state=online,offset=12979,lag=0
  1046. slave1:ip=127.0.0.1,port=6383,state=online,offset=12979,lag=1
  1047. master_repl_offset:12979
  1048. repl_backlog_active:1
  1049. repl_backlog_size:1048576
  1050. repl_backlog_first_byte_offset:2
  1051. repl_backlog_histlen:12978
  1052. '
  1053. ));
  1054. $replication = new MasterSlaveReplication();
  1055. $replication->setConnectionFactory($connFactory);
  1056. $replication->add($masterKO);
  1057. $replication->add($slave1);
  1058. $replication->discover();
  1059. $this->assertCount(2, $slaves = $replication->getSlaves());
  1060. $this->assertContainsOnlyInstancesOf('Predis\Connection\ConnectionInterface', $slaves);
  1061. $this->assertSame('127.0.0.1:6381', (string) $replication->getMaster());
  1062. $this->assertSame('127.0.0.1:6382', (string) $slaves[0]);
  1063. $this->assertSame('127.0.0.1:6383', (string) $slaves[1]);
  1064. }
  1065. /**
  1066. * @group disconnected
  1067. * @expectedException \Predis\ClientException
  1068. * @expectedMessage Automatic discovery requires a connection factory
  1069. */
  1070. public function testAutomaticDiscoveryRequiresConnectionFactory()
  1071. {
  1072. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  1073. $replication = new MasterSlaveReplication();
  1074. $replication->add($master);
  1075. $replication->setAutoDiscovery(true);
  1076. }
  1077. /**
  1078. * @group disconnected
  1079. */
  1080. public function testAutomaticDiscoveryOnUnreachableServer()
  1081. {
  1082. $cmdInfo = $command = Command\RawCommand::create('INFO', 'REPLICATION');
  1083. $cmdExists = $command = Command\RawCommand::create('EXISTS', 'key');
  1084. $slaveKO = $this->getMockConnection('tcp://127.0.0.1:7382?role=slave');
  1085. $master = $this->getMockConnection('tcp://127.0.0.1:6381?role=master');
  1086. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6382?role=slave');
  1087. $connFactory = $this->getMock('Predis\Connection\Factory');
  1088. $connFactory
  1089. ->expects($this->once())
  1090. ->method('create')
  1091. ->with(array(
  1092. 'host' => '127.0.0.1',
  1093. 'port' => '6382',
  1094. 'role' => 'slave',
  1095. ))
  1096. ->will($this->returnValue($slave1));
  1097. $slaveKO
  1098. ->expects($this->once())
  1099. ->method('executeCommand')
  1100. ->with($cmdExists)
  1101. ->will($this->throwException(
  1102. new Connection\ConnectionException($slaveKO)
  1103. ));
  1104. $slave1
  1105. ->expects($this->once())
  1106. ->method('executeCommand')
  1107. ->with($cmdExists)
  1108. ->will($this->returnValue(1));
  1109. $master
  1110. ->expects($this->once())
  1111. ->method('executeCommand')
  1112. ->with($cmdInfo)
  1113. ->will($this->returnValue('
  1114. # Replication
  1115. role:master
  1116. connected_slaves:2
  1117. slave0:ip=127.0.0.1,port=6382,state=online,offset=12979,lag=0
  1118. master_repl_offset:12979
  1119. repl_backlog_active:1
  1120. repl_backlog_size:1048576
  1121. repl_backlog_first_byte_offset:2
  1122. repl_backlog_histlen:12978
  1123. '
  1124. ));
  1125. $replication = new MasterSlaveReplication();
  1126. $replication->setConnectionFactory($connFactory);
  1127. $replication->setAutoDiscovery(true);
  1128. $replication->add($master);
  1129. $replication->add($slaveKO);
  1130. $replication->executeCommand($cmdExists);
  1131. }
  1132. /**
  1133. * @group disconnected
  1134. */
  1135. public function testExposesReplicationStrategy()
  1136. {
  1137. $replication = new MasterSlaveReplication();
  1138. $this->assertInstanceOf('Predis\Replication\ReplicationStrategy', $replication->getReplicationStrategy());
  1139. $strategy = new ReplicationStrategy();
  1140. $replication = new MasterSlaveReplication($strategy);
  1141. $this->assertSame($strategy, $replication->getReplicationStrategy());
  1142. }
  1143. /**
  1144. * @group disconnected
  1145. */
  1146. public function testCanBeSerialized()
  1147. {
  1148. $master = $this->getMockConnection('tcp://127.0.0.1:6379?role=master');
  1149. $slave1 = $this->getMockConnection('tcp://127.0.0.1:6380?role=slave');
  1150. $replication = new MasterSlaveReplication();
  1151. $replication->add($master);
  1152. $replication->add($slave1);
  1153. $unserialized = unserialize(serialize($replication));
  1154. $this->assertEquals($master, $unserialized->getConnectionByRole('master'));
  1155. $this->assertEquals($slave1, $unserialized->getConnectionByRole('slave'));
  1156. }
  1157. }