HashKeyTest.php 18 KB

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