HashKeyTest.php 18 KB

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