Fix bug in HSCAN-based iterator when hash have integer fields.

When iterating a hash containing integer fields our iterator abstraction
based on HSCAN was always returning "0" as a field name after the first
$field => $value pair due to a wrong assumption on how the PHP function
array_shift() (which is used internally to advance to the next pair in
our buffered response to HSCAN) works.

The ZSCAN-based iterator had this very same bug which was already fixed
in 24e19a9 so I am not sure how this one went unnoticed until now.
This commit is contained in:
Daniele Alessandri
2016-05-08 15:10:09 +02:00
parent 6bc1a38123
commit 0baad16064
2 changed files with 51 additions and 2 deletions
+6 -2
View File
@@ -50,7 +50,11 @@ class HashKey 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]);
}
}
}
@@ -56,6 +56,51 @@ class HashKeyTest extends PredisTestCase
$this->assertFalse($iterator->valid());
}
/**
* @link https://github.com/nrk/predis/pull/330
* @link https://github.com/nrk/predis/issues/331
* @group disconnected
*/
public function testIterationWithIntegerFields()
{
$client = $this->getMock('Predis\Client', array('getProfile', 'hscan'));
$client->expects($this->any())
->method('getProfile')
->will($this->returnValue(Profile\Factory::get('2.8')));
$client->expects($this->once())
->method('hscan')
->with('key:hash', 0, array())
->will($this->returnValue(array(0, array(
1 => 'a', 2 => 'b', 3 => 100, 'foo' => 'bar'
))));
$iterator = new HashKey($client, 'key:hash');
$iterator->rewind();
$this->assertTrue($iterator->valid());
$this->assertSame('a', $iterator->current());
$this->assertSame(1, $iterator->key());
$iterator->next();
$this->assertTrue($iterator->valid());
$this->assertSame('b', $iterator->current());
$this->assertSame(2, $iterator->key());
$iterator->next();
$this->assertTrue($iterator->valid());
$this->assertSame(100, $iterator->current());
$this->assertSame(3, $iterator->key());
$iterator->next();
$this->assertTrue($iterator->valid());
$this->assertSame('bar', $iterator->current());
$this->assertSame('foo', $iterator->key());
$iterator->next();
$this->assertFalse($iterator->valid());
}
/**
* @group disconnected
*/