From f8748af154f80c23a32e851317463129aeb45e2f Mon Sep 17 00:00:00 2001 From: Ghlen Nagels Date: Mon, 11 Dec 2023 17:22:57 +0530 Subject: [PATCH] tested edge cases fixes #193 --- src/Types/AbstractCypherSequence.php | 19 ++++++++------- src/Types/ArrayList.php | 29 +++++++++------------- tests/Unit/CypherListTest.php | 36 ++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/Types/AbstractCypherSequence.php b/src/Types/AbstractCypherSequence.php index 992b5489..f7271197 100644 --- a/src/Types/AbstractCypherSequence.php +++ b/src/Types/AbstractCypherSequence.php @@ -446,15 +446,16 @@ public function current(): mixed public function valid(): bool { - return $this->currentPosition < $this->generatorPosition || $this->getGenerator()->valid(); + return $this->currentPosition < $this->generatorPosition || array_key_exists($this->currentPosition, $this->keyCache) || $this->getGenerator()->valid(); } public function rewind(): void { - $this->currentPosition = max( - $this->currentPosition - $this->cacheLimit - 1, - 0 - ); + if ($this->currentPosition > $this->cacheLimit) { + throw new BadMethodCallException('Cannot rewind cursor: limit exceeded. In order to increase the amount of prefetched (and consequently cached) rows, increase the fetch limit in the session configuration.'); + } + + $this->currentPosition = 0; } public function next(): void @@ -489,7 +490,7 @@ public function key(): mixed */ protected function cacheKey() { - return $this->keyCache[$this->currentPosition % max($this->cacheLimit - 1, 1)]; + return $this->keyCache[$this->currentPosition % max($this->cacheLimit, 1)]; } /** @@ -519,9 +520,9 @@ private function setupCache(): void { $generator = $this->getGenerator(); - if (count($this->cache) % $this->cacheLimit === 0) { - $this->cache = []; - $this->keyCache = []; + if (count($this->cache) !== 0 && count($this->cache) % ($this->cacheLimit + 1) === 0) { + $this->cache = [array_key_last($this->cache) => $this->cache[array_key_last($this->cache)]]; + $this->keyCache = [$this->keyCache[array_key_last($this->keyCache)]]; } if ($this->cache === [] && $generator->valid()) { diff --git a/src/Types/ArrayList.php b/src/Types/ArrayList.php index 9ea75ed6..0738fa55 100644 --- a/src/Types/ArrayList.php +++ b/src/Types/ArrayList.php @@ -14,9 +14,6 @@ namespace Laudis\Neo4j\Types; use AppendIterator; - -use function array_values; - use ArrayIterator; use Generator; @@ -45,22 +42,18 @@ class ArrayList extends AbstractCypherSequence public function __construct($iterable = []) { if (is_array($iterable)) { - /** @var array $iterable */ - $this->keyCache = count($iterable) === 0 ? [] : range(0, count($iterable) - 1); - $this->cache = array_values($iterable); - $this->generator = new ArrayIterator([]); - $this->generatorPosition = count($this->keyCache); - } else { - $this->generator = static function () use ($iterable): Generator { - $i = 0; - /** @var Generator $it */ - $it = is_callable($iterable) ? $iterable() : $iterable; - foreach ($it as $value) { - yield $i => $value; - ++$i; - } - }; + $iterable = new ArrayIterator($iterable); } + + $this->generator = static function () use ($iterable): Generator { + $i = 0; + /** @var Generator $it */ + $it = is_callable($iterable) ? $iterable() : $iterable; + foreach ($it as $value) { + yield $i => $value; + ++$i; + } + }; } /** diff --git a/tests/Unit/CypherListTest.php b/tests/Unit/CypherListTest.php index 2ecd17cf..d10fc496 100644 --- a/tests/Unit/CypherListTest.php +++ b/tests/Unit/CypherListTest.php @@ -459,6 +459,42 @@ public function testSlice(): void self::assertEquals(array_sum(range(5, 7)), $sumAfter); } + public function testRewindValid(): void + { + $list = $this->list->withCacheLimit(4); + + $x = iterator_to_array($list); + $y = iterator_to_array($list); + + $this->assertEquals(['A', 'B', 'C'], $x); + $this->assertEquals(['A', 'B', 'C'], $y); + } + + public function testRewindValidExact(): void + { + $list = $this->list->withCacheLimit(3); + + $x = iterator_to_array($list); + $y = iterator_to_array($list); + + $this->assertEquals(['A', 'B', 'C'], $x); + $this->assertEquals(['A', 'B', 'C'], $y); + } + + public function testRewindInValid(): void + { + $list = $this->list->withCacheLimit(2); + + $x = iterator_to_array($list); + + $this->assertEquals(['A', 'B', 'C'], $x); + + $this->expectException(BadMethodCallException::class); + $this->expectExceptionMessage('Cannot rewind cursor: limit exceeded. In order to increase the amount of prefetched (and consequently cached) rows, increase the fetch limit in the session configuration.'); + + iterator_to_array($list); + } + /** * @return Generator */