HashKeyTest.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  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\Collection\Iterator;
  11. use PredisTestCase;
  12. /**
  13. * @group realm-iterators
  14. */
  15. class HashKeyTest extends PredisTestCase
  16. {
  17. /**
  18. * @group disconnected
  19. * @expectedException \Predis\NotSupportedException
  20. * @expectedExceptionMessage 'HSCAN' is not supported by the current command factory.
  21. */
  22. public function testThrowsExceptionOnMissingCommand()
  23. {
  24. $commands = $this->getMock('Predis\Command\FactoryInterface');
  25. $commands
  26. ->expects($this->any())
  27. ->method('supportsCommand')
  28. ->will($this->returnValue(false));
  29. $client = $this->getMock('Predis\ClientInterface');
  30. $client
  31. ->expects($this->any())
  32. ->method('getCommandFactory')
  33. ->will($this->returnValue($commands));
  34. new HashKey($client, 'key:hash');
  35. }
  36. /**
  37. * @group disconnected
  38. */
  39. public function testIterationWithNoResults()
  40. {
  41. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  42. $client
  43. ->expects($this->any())
  44. ->method('getCommandFactory')
  45. ->will($this->returnValue($this->getCommandFactory()));
  46. $client
  47. ->expects($this->once())
  48. ->method('hscan')
  49. ->with('key:hash', 0, array())
  50. ->will($this->returnValue(
  51. array(0, array(),
  52. )));
  53. $iterator = new HashKey($client, 'key:hash');
  54. $iterator->rewind();
  55. $this->assertFalse($iterator->valid());
  56. }
  57. /**
  58. * @link https://github.com/nrk/predis/pull/330
  59. * @link https://github.com/nrk/predis/issues/331
  60. * @group disconnected
  61. */
  62. public function testIterationWithIntegerFields()
  63. {
  64. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  65. $client
  66. ->expects($this->any())
  67. ->method('getCommandFactory')
  68. ->will($this->returnValue($this->getCommandFactory()));
  69. $client
  70. ->expects($this->once())
  71. ->method('hscan')
  72. ->with('key:hash', 0, array())
  73. ->will($this->returnValue(
  74. array(0, array(1 => 'a', 2 => 'b', 3 => 100, 'foo' => 'bar'))
  75. ));
  76. $iterator = new HashKey($client, 'key:hash');
  77. $iterator->rewind();
  78. $this->assertTrue($iterator->valid());
  79. $this->assertSame('a', $iterator->current());
  80. $this->assertSame(1, $iterator->key());
  81. $iterator->next();
  82. $this->assertTrue($iterator->valid());
  83. $this->assertSame('b', $iterator->current());
  84. $this->assertSame(2, $iterator->key());
  85. $iterator->next();
  86. $this->assertTrue($iterator->valid());
  87. $this->assertSame(100, $iterator->current());
  88. $this->assertSame(3, $iterator->key());
  89. $iterator->next();
  90. $this->assertTrue($iterator->valid());
  91. $this->assertSame('bar', $iterator->current());
  92. $this->assertSame('foo', $iterator->key());
  93. $iterator->next();
  94. $this->assertFalse($iterator->valid());
  95. }
  96. /**
  97. * @group disconnected
  98. */
  99. public function testIterationOnSingleFetch()
  100. {
  101. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  102. $client
  103. ->expects($this->any())
  104. ->method('getCommandFactory')
  105. ->will($this->returnValue($this->getCommandFactory()));
  106. $client
  107. ->expects($this->once())
  108. ->method('hscan')
  109. ->with('key:hash', 0, array())
  110. ->will($this->returnValue(
  111. array(0, array('field:1st' => 'value:1st', 'field:2nd' => 'value:2nd', 'field:3rd' => 'value:3rd'))
  112. ));
  113. $iterator = new HashKey($client, 'key:hash');
  114. $iterator->rewind();
  115. $this->assertTrue($iterator->valid());
  116. $this->assertSame('value:1st', $iterator->current());
  117. $this->assertSame('field:1st', $iterator->key());
  118. $iterator->next();
  119. $this->assertTrue($iterator->valid());
  120. $this->assertSame('value:2nd', $iterator->current());
  121. $this->assertSame('field:2nd', $iterator->key());
  122. $iterator->next();
  123. $this->assertTrue($iterator->valid());
  124. $this->assertSame('value:3rd', $iterator->current());
  125. $this->assertSame('field:3rd', $iterator->key());
  126. $iterator->next();
  127. $this->assertFalse($iterator->valid());
  128. }
  129. /**
  130. * @group disconnected
  131. */
  132. public function testIterationOnMultipleFetches()
  133. {
  134. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  135. $client
  136. ->expects($this->any())
  137. ->method('getCommandFactory')
  138. ->will($this->returnValue($this->getCommandFactory()));
  139. $client
  140. ->expects($this->at(1))
  141. ->method('hscan')
  142. ->with('key:hash', 0, array())
  143. ->will($this->returnValue(
  144. array(2, array('field:1st' => 'value:1st', 'field:2nd' => 'value:2nd'))
  145. ));
  146. $client
  147. ->expects($this->at(2))
  148. ->method('hscan')
  149. ->with('key:hash', 2, array())
  150. ->will($this->returnValue(
  151. array(0, array('field:3rd' => 'value:3rd'))
  152. ));
  153. $iterator = new HashKey($client, 'key:hash');
  154. $iterator->rewind();
  155. $this->assertTrue($iterator->valid());
  156. $this->assertSame('value:1st', $iterator->current());
  157. $this->assertSame('field:1st', $iterator->key());
  158. $iterator->next();
  159. $this->assertTrue($iterator->valid());
  160. $this->assertSame('value:2nd', $iterator->current());
  161. $this->assertSame('field:2nd', $iterator->key());
  162. $iterator->next();
  163. $this->assertTrue($iterator->valid());
  164. $this->assertSame('value:3rd', $iterator->current());
  165. $this->assertSame('field:3rd', $iterator->key());
  166. $iterator->next();
  167. $this->assertFalse($iterator->valid());
  168. }
  169. /**
  170. * @group disconnected
  171. */
  172. public function testIterationOnMultipleFetchesAndHoleInFirstFetch()
  173. {
  174. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  175. $client
  176. ->expects($this->any())
  177. ->method('getCommandFactory')
  178. ->will($this->returnValue($this->getCommandFactory()));
  179. $client
  180. ->expects($this->at(1))
  181. ->method('hscan')
  182. ->with('key:hash', 0, array())
  183. ->will($this->returnValue(
  184. array(4, array())
  185. ));
  186. $client
  187. ->expects($this->at(2))
  188. ->method('hscan')
  189. ->with('key:hash', 4, array())
  190. ->will($this->returnValue(
  191. array(0, array('field:1st' => 'value:1st', 'field:2nd' => 'value:2nd'))
  192. ));
  193. $iterator = new HashKey($client, 'key:hash');
  194. $iterator->rewind();
  195. $this->assertTrue($iterator->valid());
  196. $this->assertSame('value:1st', $iterator->current());
  197. $this->assertSame('field:1st', $iterator->key());
  198. $iterator->next();
  199. $this->assertTrue($iterator->valid());
  200. $this->assertSame('value:2nd', $iterator->current());
  201. $this->assertSame('field:2nd', $iterator->key());
  202. $iterator->next();
  203. $this->assertFalse($iterator->valid());
  204. }
  205. /**
  206. * @group disconnected
  207. */
  208. public function testIterationOnMultipleFetchesAndHoleInMidFetch()
  209. {
  210. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  211. $client
  212. ->expects($this->any())
  213. ->method('getCommandFactory')
  214. ->will($this->returnValue($this->getCommandFactory()));
  215. $client
  216. ->expects($this->at(1))
  217. ->method('hscan')
  218. ->with('key:hash', 0, array())
  219. ->will($this->returnValue(
  220. array(2, array('field:1st' => 'value:1st', 'field:2nd' => 'value:2nd'))
  221. ));
  222. $client
  223. ->expects($this->at(2))
  224. ->method('hscan')
  225. ->with('key:hash', 2, array())
  226. ->will($this->returnValue(
  227. array(5, array())
  228. ));
  229. $client
  230. ->expects($this->at(3))
  231. ->method('hscan')
  232. ->with('key:hash', 5, array())
  233. ->will($this->returnValue(
  234. array(0, array('field:3rd' => 'value:3rd'))
  235. ));
  236. $iterator = new HashKey($client, 'key:hash');
  237. $iterator->rewind();
  238. $this->assertTrue($iterator->valid());
  239. $this->assertSame('value:1st', $iterator->current());
  240. $this->assertSame('field:1st', $iterator->key());
  241. $iterator->next();
  242. $this->assertTrue($iterator->valid());
  243. $this->assertSame('value:2nd', $iterator->current());
  244. $this->assertSame('field:2nd', $iterator->key());
  245. $iterator->next();
  246. $this->assertTrue($iterator->valid());
  247. $this->assertSame('value:3rd', $iterator->current());
  248. $this->assertSame('field:3rd', $iterator->key());
  249. $iterator->next();
  250. $this->assertFalse($iterator->valid());
  251. }
  252. /**
  253. * @group disconnected
  254. */
  255. public function testIterationWithOptionMatch()
  256. {
  257. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  258. $client
  259. ->expects($this->any())
  260. ->method('getCommandFactory')
  261. ->will($this->returnValue($this->getCommandFactory()));
  262. $client
  263. ->expects($this->at(1))
  264. ->method('hscan')
  265. ->with('key:hash', 0, array('MATCH' => 'field:*'))
  266. ->will($this->returnValue(
  267. array(2, array('field:1st' => 'value:1st', 'field:2nd' => 'value:2nd'))
  268. ));
  269. $iterator = new HashKey($client, 'key:hash', 'field:*');
  270. $iterator->rewind();
  271. $this->assertTrue($iterator->valid());
  272. $this->assertSame('value:1st', $iterator->current());
  273. $this->assertSame('field:1st', $iterator->key());
  274. $iterator->next();
  275. $this->assertTrue($iterator->valid());
  276. $this->assertSame('value:2nd', $iterator->current());
  277. $this->assertSame('field:2nd', $iterator->key());
  278. $iterator->next();
  279. $this->assertFalse($iterator->valid());
  280. }
  281. /**
  282. * @group disconnected
  283. */
  284. public function testIterationWithOptionMatchOnMultipleFetches()
  285. {
  286. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  287. $client
  288. ->expects($this->any())
  289. ->method('getCommandFactory')
  290. ->will($this->returnValue($this->getCommandFactory()));
  291. $client
  292. ->expects($this->at(1))
  293. ->method('hscan')
  294. ->with('key:hash', 0, array('MATCH' => 'field:*'))
  295. ->will($this->returnValue(
  296. array(1, array('field:1st' => 'value:1st'))
  297. ));
  298. $client
  299. ->expects($this->at(2))
  300. ->method('hscan')
  301. ->with('key:hash', 1, array('MATCH' => 'field:*'))
  302. ->will($this->returnValue(
  303. array(0, array('field:2nd' => 'value:2nd'))
  304. ));
  305. $iterator = new HashKey($client, 'key:hash', 'field:*');
  306. $iterator->rewind();
  307. $this->assertTrue($iterator->valid());
  308. $this->assertSame('value:1st', $iterator->current());
  309. $this->assertSame('field:1st', $iterator->key());
  310. $iterator->next();
  311. $this->assertTrue($iterator->valid());
  312. $this->assertSame('value:2nd', $iterator->current());
  313. $this->assertSame('field:2nd', $iterator->key());
  314. $iterator->next();
  315. $this->assertFalse($iterator->valid());
  316. }
  317. /**
  318. * @group disconnected
  319. */
  320. public function testIterationWithOptionCount()
  321. {
  322. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  323. $client
  324. ->expects($this->any())
  325. ->method('getCommandFactory')
  326. ->will($this->returnValue($this->getCommandFactory()));
  327. $client
  328. ->expects($this->at(1))
  329. ->method('hscan')
  330. ->with('key:hash', 0, array('COUNT' => 2))
  331. ->will($this->returnValue(
  332. array(0, array('field:1st' => 'value:1st', 'field:2nd' => 'value:2nd'))
  333. ));
  334. $iterator = new HashKey($client, 'key:hash', null, 2);
  335. $iterator->rewind();
  336. $this->assertTrue($iterator->valid());
  337. $this->assertSame('value:1st', $iterator->current());
  338. $this->assertSame('field:1st', $iterator->key());
  339. $iterator->next();
  340. $this->assertTrue($iterator->valid());
  341. $this->assertSame('value:2nd', $iterator->current());
  342. $this->assertSame('field:2nd', $iterator->key());
  343. $iterator->next();
  344. $this->assertFalse($iterator->valid());
  345. }
  346. /**
  347. * @group disconnected
  348. */
  349. public function testIterationWithOptionCountOnMultipleFetches()
  350. {
  351. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  352. $client
  353. ->expects($this->any())
  354. ->method('getCommandFactory')
  355. ->will($this->returnValue($this->getCommandFactory()));
  356. $client
  357. ->expects($this->at(1))
  358. ->method('hscan')
  359. ->with('key:hash', 0, array('COUNT' => 1))
  360. ->will($this->returnValue(
  361. array(1, array('field:1st' => 'value:1st'))
  362. ));
  363. $client
  364. ->expects($this->at(2))
  365. ->method('hscan')
  366. ->with('key:hash', 1, array('COUNT' => 1))
  367. ->will($this->returnValue(
  368. array(0, array('field:2nd' => 'value:2nd'))
  369. ));
  370. $iterator = new HashKey($client, 'key:hash', null, 1);
  371. $iterator->rewind();
  372. $this->assertTrue($iterator->valid());
  373. $this->assertSame('value:1st', $iterator->current());
  374. $this->assertSame('field:1st', $iterator->key());
  375. $iterator->next();
  376. $this->assertTrue($iterator->valid());
  377. $this->assertSame('value:2nd', $iterator->current());
  378. $this->assertSame('field:2nd', $iterator->key());
  379. $iterator->next();
  380. $this->assertFalse($iterator->valid());
  381. }
  382. /**
  383. * @group disconnected
  384. */
  385. public function testIterationWithOptionsMatchAndCount()
  386. {
  387. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  388. $client
  389. ->expects($this->any())
  390. ->method('getCommandFactory')
  391. ->will($this->returnValue($this->getCommandFactory()));
  392. $client
  393. ->expects($this->at(1))
  394. ->method('hscan')
  395. ->with('key:hash', 0, array('MATCH' => 'field:*', 'COUNT' => 2))
  396. ->will($this->returnValue(
  397. array(0, array('field:1st' => 'value:1st', 'field:2nd' => 'value:2nd'))
  398. ));
  399. $iterator = new HashKey($client, 'key:hash', 'field:*', 2);
  400. $iterator->rewind();
  401. $this->assertTrue($iterator->valid());
  402. $this->assertSame('value:1st', $iterator->current());
  403. $this->assertSame('field:1st', $iterator->key());
  404. $iterator->next();
  405. $this->assertTrue($iterator->valid());
  406. $this->assertSame('value:2nd', $iterator->current());
  407. $this->assertSame('field:2nd', $iterator->key());
  408. $iterator->next();
  409. $this->assertFalse($iterator->valid());
  410. }
  411. /**
  412. * @group disconnected
  413. */
  414. public function testIterationWithOptionsMatchAndCountOnMultipleFetches()
  415. {
  416. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  417. $client
  418. ->expects($this->any())
  419. ->method('getCommandFactory')
  420. ->will($this->returnValue($this->getCommandFactory()));
  421. $client
  422. ->expects($this->at(1))
  423. ->method('hscan')
  424. ->with('key:hash', 0, array('MATCH' => 'field:*', 'COUNT' => 1))
  425. ->will($this->returnValue(
  426. array(1, array('field:1st' => 'value:1st'))
  427. ));
  428. $client
  429. ->expects($this->at(2))
  430. ->method('hscan')
  431. ->with('key:hash', 1, array('MATCH' => 'field:*', 'COUNT' => 1))
  432. ->will($this->returnValue(
  433. array(0, array('field:2nd' => 'value:2nd'))
  434. ));
  435. $iterator = new HashKey($client, 'key:hash', 'field:*', 1);
  436. $iterator->rewind();
  437. $this->assertTrue($iterator->valid());
  438. $this->assertSame('value:1st', $iterator->current());
  439. $this->assertSame('field:1st', $iterator->key());
  440. $iterator->next();
  441. $this->assertTrue($iterator->valid());
  442. $this->assertSame('value:2nd', $iterator->current());
  443. $this->assertSame('field:2nd', $iterator->key());
  444. $iterator->next();
  445. $this->assertFalse($iterator->valid());
  446. }
  447. /**
  448. * @group disconnected
  449. */
  450. public function testIterationRewindable()
  451. {
  452. $client = $this->getMock('Predis\Client', array('getCommandFactory', 'hscan'));
  453. $client
  454. ->expects($this->any())
  455. ->method('getCommandFactory')
  456. ->will($this->returnValue($this->getCommandFactory()));
  457. $client
  458. ->expects($this->exactly(2))
  459. ->method('hscan')
  460. ->with('key:hash', 0, array())
  461. ->will($this->returnValue(
  462. array(0, array('field:1st' => 'value:1st', 'field:2nd' => 'value:2nd'))
  463. ));
  464. $iterator = new HashKey($client, 'key:hash');
  465. $iterator->rewind();
  466. $this->assertTrue($iterator->valid());
  467. $this->assertSame('value:1st', $iterator->current());
  468. $this->assertSame('field:1st', $iterator->key());
  469. $iterator->rewind();
  470. $this->assertTrue($iterator->valid());
  471. $this->assertSame('value:1st', $iterator->current());
  472. $this->assertSame('field:1st', $iterator->key());
  473. $iterator->next();
  474. $this->assertTrue($iterator->valid());
  475. $this->assertSame('value:2nd', $iterator->current());
  476. $this->assertSame('field:2nd', $iterator->key());
  477. $iterator->next();
  478. $this->assertFalse($iterator->valid());
  479. }
  480. }