From 24e19a9b766fd1e414459060a2bf5268d5f62cf3 Mon Sep 17 00:00:00 2001 From: Daniele Alessandri Date: Tue, 21 Oct 2014 11:43:53 +0200 Subject: [PATCH] Fix bug in ZSCAN-based iterator when sorted sets have integer members. When iterating a sorted set containing integer members, our iterator abstraction based on ZSCAN was always returning "0" as a member value after the first $member => $score pair because of a wrong assumption on how the PHP function array_shift() (used internally to advance to the next pair in our buffered response to ZSCAN) works. Fixes #216. --- CHANGELOG.md | 3 ++ src/Collection/Iterator/SortedSetKey.php | 8 +++- .../Collection/Iterator/SortedSetKeyTest.php | 39 +++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdfdc342..09864363 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ v1.0.1 (2014-xx-xx) ================================================================================ +- __FIX__: broken values returned by `Predis\Collection\Iterator\SortedSetKey` + when iterating sorted set containing integer members (ISSUE #216). + - __FIX__: applied a minor workaround for a bug in old versions of PHP < 5.3.9 affecting inheritance. diff --git a/src/Collection/Iterator/SortedSetKey.php b/src/Collection/Iterator/SortedSetKey.php index 7dc7b09e..f887c40c 100644 --- a/src/Collection/Iterator/SortedSetKey.php +++ b/src/Collection/Iterator/SortedSetKey.php @@ -49,7 +49,11 @@ class SortedSetKey extends CursorBasedIterator */ protected function extractNext() { - $this->position = key($this->elements); - $this->current = array_shift($this->elements); + if ($kv = each($this->elements)) { + $this->position = $kv[0]; + $this->current = $kv[1]; + + unset($this->elements[$this->position]); + } } } diff --git a/tests/Predis/Collection/Iterator/SortedSetKeyTest.php b/tests/Predis/Collection/Iterator/SortedSetKeyTest.php index e3fe9afd..b87d8d90 100644 --- a/tests/Predis/Collection/Iterator/SortedSetKeyTest.php +++ b/tests/Predis/Collection/Iterator/SortedSetKeyTest.php @@ -56,6 +56,45 @@ class SortedSetKeyTest extends PredisTestCase $this->assertFalse($iterator->valid()); } + /** + * @link https://github.com/nrk/predis/issues/216 + * @group disconnected + */ + public function testIterationWithIntegerMembers() + { + $client = $this->getMock('Predis\Client', array('getProfile', 'zscan')); + + $client->expects($this->any()) + ->method('getProfile') + ->will($this->returnValue(Profile\Factory::get('2.8'))); + $client->expects($this->once()) + ->method('zscan') + ->with('key:zset', 0, array()) + ->will($this->returnValue(array(0, array( + 0 => 0, 101 => 1, 102 => 2, + )))); + + $iterator = new SortedSetKey($client, 'key:zset'); + + $iterator->rewind(); + $this->assertTrue($iterator->valid()); + $this->assertSame(0, $iterator->current()); + $this->assertSame(0, $iterator->key()); + + $iterator->next(); + $this->assertTrue($iterator->valid()); + $this->assertSame(1, $iterator->current()); + $this->assertSame(101, $iterator->key()); + + $iterator->next(); + $this->assertTrue($iterator->valid()); + $this->assertSame(2, $iterator->current()); + $this->assertSame(102, $iterator->key()); + + $iterator->next(); + $this->assertFalse($iterator->valid()); + } + /** * @group disconnected */