diff --git a/composer.json b/composer.json index 0fe3128a519cffc0173d836673b7013132074330..459762ec0c57e485b1c852f81bcd44130fd799f0 100644 --- a/composer.json +++ b/composer.json @@ -3,10 +3,10 @@ "require": { "php": ">=7.0.0", "dibi/dibi": "^3.0", - "tracy/tracy": "^2.3" + "tracy/tracy": "^2.3", + "marc-mabe/php-enum": "^2.2" }, "require-dev": { - "nette/tester": "^1.7", "mockery/mockery": "^0.9.4", "kdyby/tester-extras": "dev-master@dev" }, diff --git a/src/PostgresDriver/CursorDriver.php b/src/PostgresDriver/CursorDriver.php index 65e4e5d53cd3a1334f53187ad026c4d203745c47..7ecfa98ace30e6fcc23c31c63330673be04d451e 100644 --- a/src/PostgresDriver/CursorDriver.php +++ b/src/PostgresDriver/CursorDriver.php @@ -128,7 +128,7 @@ final class CursorDriver implements ICursorDriver return $this->convertRows($recs); } - public function fetchOneAt(int $index) : array + public function fetchOneAt(int $index) { $row = $this->connection->query( "FETCH ABSOLUTE %i FROM %n", @@ -142,7 +142,7 @@ final class CursorDriver implements ICursorDriver return $this->convertRow($row); } - public function fetchOneBy(int $rows) : array + public function fetchOneBy(int $rows) { $row = $this->connection->query( "FETCH RELATIVE %i FROM %n", diff --git a/src/PostgresDriver/CursorPosition.php b/src/PostgresDriver/CursorPosition.php index 5745aae40e4f68420c6fefa94fc177a99722b2d6..b1defb1df505a50876695cc2db0a5a1b74a4cea5 100644 --- a/src/PostgresDriver/CursorPosition.php +++ b/src/PostgresDriver/CursorPosition.php @@ -93,4 +93,8 @@ final class CursorPosition return $this->position; } + function __toString() : string + { + return ($this->origin->getValue() === CursorPositionOrigin::FROM_LEFT ? "left:" : "right:") . $this->position; + } } \ No newline at end of file diff --git a/src/PostgresDriver/ICursor.php b/src/PostgresDriver/ICursor.php deleted file mode 100644 index 623fc25a3d18cb63276e423af0e82928314cf4d7..0000000000000000000000000000000000000000 --- a/src/PostgresDriver/ICursor.php +++ /dev/null @@ -1,108 +0,0 @@ -<?php -/** - * This file is part of mappi/store. - */ -namespace Grifart\Mappi\Store\PostgresDriver; -use Dibi\Connection; - -/** - * Represents PostgreSQL cursor - * @link http://www.postgresql.org/docs/9.5/static/plpgsql-cursors.html - * @link http://www.postgresql.org/docs/8.1/static/sql-fetch.html - * @link http://www.postgresql.org/docs/8.1/static/sql-move.html - * @package Grifart\Mappi\Store\PostgresDriver - */ -interface ICursor -{ - // ---- shared with ICursorDriver ---- - public function getName() : string; - - public function isOnRecord() : bool; - - /** - * @param int $rows - * @return void - */ - public function moveBy(int $rows); - - /** - * @param int $index - * @return void - */ - public function moveTo(int $index); - - /** - * @param int $index - * @return mixed - */ - public function moveFromEndTo(int $index); - - /** - * Fetch the next/previous count rows. FORWARD 0 re-fetches the current row. - * @param int $rows - * @return array - */ - public function fetchRange(int $rows) : array; - - /** - * Fetch the count'th row of the query, or the abs(count)'th row from the end if count is negative. Position before first row or after last row if count is out of range; in particular, ABSOLUTE 0 positions before the first row. - * @param int $index - * @return array - */ - public function fetchOneAt(int $index) : array; - - /** - * Fetch the count'th succeeding row, or the abs(count)'th prior row if count is negative. RELATIVE 0 re-fetches the current row, if any. - * @param int $rows - * @return array - */ - public function fetchOneBy(int $rows) : array; - - - // ---- The UX part: ---- - /** - * Move cursor on the last row - * @see fetchCurrent() - * @see fetchCurrentSingle() - * @return void - */ - public function moveToLast(); - - /** - * Move cursor on the first row (index=1) - * @see fetchCurrent() - * @see fetchCurrentSingle() - * @return void - */ - public function moveToFirst(); - - /** - * Moves cursor to position BEFORE first row (index=0) - * @see fetchNext() - * @see fetchNextSingle() - * @return void - */ - public function moveToBeginning(); - - /** - * Moves cursor to position AFTER last row - * @return void - */ - public function moveToEnd(); - - /** - * Moves cursor to the next position, then returns rows. - * @return mixed - */ - public function fetchNext(); - public function fetchNextSingle(); - - public function fetchCurrent(); - public function fetchCurrentSingle(); - - public function fetchPrevious(); - public function fetchPreviousSingle(); - - public function fetchRemaining(); - public function fetchForegoing(); -} \ No newline at end of file diff --git a/src/PostgresDriver/ICursorDriver.php b/src/PostgresDriver/ICursorDriver.php index c4914ad09efbb676a14848a204af73ad02f426b3..697c27469b73338e5296a52323fb28c34ee70738 100644 --- a/src/PostgresDriver/ICursorDriver.php +++ b/src/PostgresDriver/ICursorDriver.php @@ -29,12 +29,14 @@ interface ICursorDriver /** * @param int $index + * @throws CursorException Negative indexes not supported * @return void */ public function moveTo(int $index); /** * @param int $index + * @throws CursorException Negative indexes not supported * @return mixed */ public function moveFromEndTo(int $index); @@ -48,16 +50,16 @@ interface ICursorDriver /** * Fetch the count'th row of the query, or the abs(count)'th row from the end if count is negative. Position before first row or after last row if count is out of range; in particular, ABSOLUTE 0 positions before the first row. - * @param int $index - * @return array + * @param int $index Positive means from left; negative from right + * @return array|NULL */ - public function fetchOneAt(int $index) : array; + public function fetchOneAt(int $index); /** * Fetch the count'th succeeding row, or the abs(count)'th prior row if count is negative. RELATIVE 0 re-fetches the current row, if any. * @param int $rows - * @return array + * @return array|NULL */ - public function fetchOneBy(int $rows) : array; + public function fetchOneBy(int $rows); } \ No newline at end of file diff --git a/src/PostgresDriver/TrackedCursor.php b/src/PostgresDriver/TrackedCursor.php index 4ef618bc330e78b8f00cb4c09abbbdaaac08e43b..fc4aaf66e2cc57c980c74ea3b13686cbcdc9e6d2 100644 --- a/src/PostgresDriver/TrackedCursor.php +++ b/src/PostgresDriver/TrackedCursor.php @@ -17,7 +17,7 @@ class TrackedCursor implements ICursorDriver */ private $position; - /** @var ICursor */ + /** @var ICursorDriver */ private $cursor; /** @var Connection */ @@ -42,7 +42,7 @@ class TrackedCursor implements ICursorDriver */ public function getPosition() { - return $this->position; + return clone $this->position; } public function getConnection() : Connection @@ -126,21 +126,32 @@ class TrackedCursor implements ICursorDriver public function fetchRange(int $rows): array { - // todo: fixme overriding parameter $result = $this->cursor->fetchRange($rows); + if($rows === 0) { // zero does not move cursor + return $result; + } - if($rows !== 0) { // zero does not move cursor - $forward = $rows > 0; + $forward = $rows > 0; + $count = count($result); + $reachedEnd = $count < abs($rows); + if(!$reachedEnd) { $this->position->movePositionBy( - count($result) * ($forward ? 1 : -1) + $count * ($forward ? 1 : -1) ); + return $result; } - return $result; + if($forward) { + $this->position->setPositionFromRight(0); // right END + return $result; + } else { + $this->position->setPositionFromLeft(0); // left END + return $result; + } } - public function fetchOneAt(int $index) : array - { + public function fetchOneAt(int $index) + { // todo: content tests $row = $this->cursor->fetchOneAt($index); if ($row !== NULL) { if($index < 0) { @@ -168,8 +179,8 @@ class TrackedCursor implements ICursorDriver throw CursorException::cursorPosition_unknownError(); } - public function fetchOneBy(int $rows): array - { + public function fetchOneBy(int $rows) + { // todo: content tests $row = $this->cursor->fetchOneBy($rows); if ($row !== NULL) { $this->position->movePositionBy($rows); diff --git a/tests/Store/PostgresDriver/CursorDriverTest.phpt b/tests/Store/PostgresDriver/CursorDriverTest.phpt index 00c50fb0c4f9b604eee6ca3a0aa1e59a403223d0..0b77abea0470042e60e30d653dd4506be11b78f0 100644 --- a/tests/Store/PostgresDriver/CursorDriverTest.phpt +++ b/tests/Store/PostgresDriver/CursorDriverTest.phpt @@ -14,11 +14,12 @@ use Grifart\Mappi\Tests\Store\BaseTest; use Tester\Assert; require_once __DIR__ . "/../../bootstrap.php"; +require_once __DIR__ . "/CursorInterfaceTest.php"; -class CursorDriverTest extends BaseTest +class CursorDriverTest extends CursorInterfaceTest { /** @var ICursorDriver */ - private $uut; + protected $uut; protected function setUp() { @@ -38,299 +39,6 @@ class CursorDriverTest extends BaseTest // parent::tearDown(); } - - private function helper_fetchNextSingle() - { - $rows = $this->uut->fetchRange(1); - if(count($rows) === 0) return NULL; - return $rows[0]["n"]; - } - - private function helper_fetchCurrentSingle() - { - $rows = $this->uut->fetchRange(0); - if(count($rows) === 0) return NULL; - return $rows[0]["n"]; - } - - private function helper_fetchPrevSingle() - { - $rows = $this->uut->fetchRange(-1); - if(count($rows) === 0) return NULL; - return $rows[0]["n"]; - } - - - - // initial position - public function test_givenCursor_whenGetCurrentRow_thenGetNothing() - { - Assert::count(0, $this->uut->fetchRange(0)); // must fail because initial position is 0 - Assert::count(0, $this->uut->fetchRange(-1)); - Assert::count(1, $this->uut->fetchRange(1)); - } - - public function test_givenInitialPosition_whenFetch_thenGetFirstRow() - { - Assert::same(1, $this->helper_fetchNextSingle()); - } - - // fetch( x == 0 ) - public function test_givenSecondPosition_whenFetch0_thenGetCurrentRow() - { - // head: . - // index: 0 1 2 3 4 - // value: 1 2 3 4 - $this->uut->moveTo(3); - Assert::same(3, $this->helper_fetchCurrentSingle()); - - $result = $this->uut->fetchRange(0); // rows backwards + read current - - Assert::count(1, $result); - Assert::same(3, current($result[0])); - } - - // fetch( x > 0 ) - public function test_givenSecondPosition_whenFetchForward_thenGetRowsAfterCursor() - { - // head: . - // index: 0 1 2 3 4 - // value: 1 2 3 4 - $this->uut->moveTo(3); - Assert::same(3, $this->helper_fetchCurrentSingle()); - - // head: . - // index: 0 1 2 3 4 5 6 - // value: 1 2 3 4 5 6 - $result = $this->uut->fetchRange(2); // rows backwards + read current - // todo: split into fetch decorator for those special fetch* methods - - Assert::count(2, $result); - Assert::same(4, current($result[0])); - Assert::same(5, current($result[1])); - Assert::same(5, $this->helper_fetchCurrentSingle()); - } - - // fetch( x < 0 ) - public function test_givenSecondPosition_whenFetchBackwards_thenGetRowsBeforeCursor() - { - // head: . - // index: 0 1 2 3 4 - // value: 1 2 3 4 - $this->uut->moveTo(3); - Assert::same(3, $this->helper_fetchCurrentSingle()); - - // head: . - // index: 0 1 2 3 4 - // value: 1 2 3 4 - $result = $this->uut->fetchRange(-2); // rows backwards + read current - // todo: split into fetch decorator for those special fetch* methods - - Assert::count(2, $result); - Assert::same(2, current($result[0])); - Assert::same(1, current($result[1])); - Assert::same(1, $this->helper_fetchCurrentSingle()); - } - - - // moveToBeginning() - public function test_givenLastPosition_whenMoveToTheBeginning_thenFetchingNextRowWillBeFirstRow() - { - // Arrange - $this->uut->moveFromEndTo(1); - - // Act - $this->uut->moveTo(0); - - //Assert - Assert::same(1, $this->helper_fetchNextSingle()); - } - - - // moveToFirst() - public function test_givenLastPosition_whenMoveToTheFirst_thenFetchingCurrentWillBeFirstRow() - { - // Arrange - $this->uut->moveFromEndTo(1); - - // Act - $this->uut->moveTo(1); - - //Assert - Assert::same(1, $this->helper_fetchCurrentSingle()); - } - - - // moveToEnd() - public function test_givenInitialPosition_whenMoveToEnd_thenFetchingOneBacwardsWillBeTheLastRow() - { - $this->uut->moveFromEndTo(0); - - Assert::null($this->helper_fetchCurrentSingle()); - - $data = $this->helper_fetchPrevSingle(); - Assert::same(1000, $data); - } - - - // moveToLast() - public function test_givenInitialPosition_whenMoveToLast_thenFetchingCurrentWillBeLastRow() - { - $this->uut->moveFromEndTo(1); - Assert::same(1000, $this->helper_fetchCurrentSingle()); - - Assert::null($this->helper_fetchNextSingle()); - } - - - // moveBy() - public function test_givenInitialPosition_whenMoveBy2_thenGetSecondValue() - { - $this->uut->moveBy(2); - Assert::same(2, $this->helper_fetchCurrentSingle()); - } - - public function test_givenSecondPosition_whenMoveOneBack_thenGetFirstValue() - { - $this->uut->moveTo(2); - $this->uut->moveBy(-1); - Assert::same(1, $this->helper_fetchCurrentSingle()); - $this->uut->moveBy(-1); - Assert::null($this->helper_fetchCurrentSingle()); - } - - - // fetchOneAt() - public function test_givenInitialPosition_whenFetch5_thenGetFive() - { - $data = $this->uut->fetchOneAt(5); - Assert::same(5, $data["n"]); - } - - public function test_givenNonInitialPosition_whenFetch5_thenGetFive() - { - $this->uut->moveTo(234); // wherever - - $data = $this->uut->fetchOneAt(5); - Assert::same(5, $data["n"]); - } - - // fetchRemaining() - public function test_given5BeforeEndPosition_whenFetchRemaining_thenGetLastFile() - { - $this->uut->moveTo(995); - - $result = $this->uut->fetchRange(ICursorDriver::FETCH_REMAINING); - - Assert::count(5, $result); - Assert::same(996, current($result[0])); - Assert::same(997, current($result[1])); - Assert::same(998, current($result[2])); - Assert::same(999, current($result[3])); - Assert::same(1000, current($result[4])); - - Assert::null($this->helper_fetchCurrentSingle()); - Assert::equal(1000, $this->helper_fetchPrevSingle()); - - } - - - // fetchRemaining() - public function test_given5AfterStart_whenFetchForegoing_thenGetFirstFive() - { - $this->uut->moveTo(6); - - $result = $this->uut->fetchRange(ICursorDriver::FETCH_FOREGOING); - - Assert::count(5, $result); - Assert::same(5, current($result[0])); - Assert::same(4, current($result[1])); - Assert::same(3, current($result[2])); - Assert::same(2, current($result[3])); - Assert::same(1, current($result[4])); - - Assert::null($this->helper_fetchCurrentSingle()); - } - - - // edge cases: - public function test_givenInitialPosition_whenMoveToLeft_thenGetError() - { - Assert::false($this->uut->isOnRecord()); // initial position - - // start: index === 0 - $this->uut->moveBy(-1); - Assert::false($this->uut->isOnRecord()); - - // index === 0 - $data = $this->uut->fetchRange(-1); - Assert::count(0, $data); - - $firstValue = $this->helper_fetchNextSingle(); - Assert::equal(1, $firstValue); - // index === 1 - } - - public function test_givenEndPosition_whenMoveToRight_thenStayInPlace() - { - $this->uut->moveFromEndTo(0); - - Assert::null($this->helper_fetchNextSingle()); - Assert::null($this->helper_fetchCurrentSingle()); - Assert::equal(1000, $this->helper_fetchPrevSingle()); - } - - - public function test_giveSomePosition_whenMoveToAfterEnd_thenWillBeAtTheEnd() - { - $this->uut->moveTo(25); // some position - - $this->uut->moveTo(9999); - - Assert::null($this->helper_fetchCurrentSingle()); - Assert::equal(1000, $this->helper_fetchPrevSingle()); - } - - public function test_givenFirstPosition_whenMoveToLeft_thenWillBeAtBeginning() - { - // Arrange - Assert::false($this->uut->isOnRecord()); - $this->uut->moveTo(1); - Assert::true($this->uut->isOnRecord()); - - // Act - $this->uut->moveBy(-1); - - // Assert - Assert::false($this->uut->isOnRecord()); - Assert::null($this->helper_fetchCurrentSingle()); - Assert::null($this->helper_fetchPrevSingle()); - - Assert::equal(1, $this->helper_fetchNextSingle()); - Assert::true($this->uut->isOnRecord()); - } - - public function test_givenLastPosition_whenMoveToRight_thenReachTheEnd() - { - $this->uut->moveFromEndTo(1); - Assert::true($this->uut->isOnRecord()); - - $this->uut->moveBy(1); - - Assert::false($this->uut->isOnRecord()); - Assert::null($this->helper_fetchCurrentSingle()); - Assert::null($this->helper_fetchNextSingle()); - - Assert::equal(1000, $this->helper_fetchPrevSingle()); - Assert::true($this->uut->isOnRecord()); - } - - public function test_giveSomePosition_whenMoveToBeginning_thenWillBeAtBeginning() - { - $this->uut->moveTo(42); - $this->uut->moveTo(0); - Assert::equal(1,$this->helper_fetchNextSingle()); - } } (new CursorDriverTest())->run(); diff --git a/tests/Store/PostgresDriver/CursorInterfaceTest.php b/tests/Store/PostgresDriver/CursorInterfaceTest.php index 7cdfb2f26661dca4a1e58d0c9075972e03bd13f9..76ff3145dfef1559a3f4249ead4e42173918749b 100644 --- a/tests/Store/PostgresDriver/CursorInterfaceTest.php +++ b/tests/Store/PostgresDriver/CursorInterfaceTest.php @@ -5,28 +5,59 @@ namespace Grifart\Mappi\Tests\Store\Store\PostgresDriver; -use Grifart\Mappi\Store\PostgresDriver\CursorException; -use Grifart\Mappi\Store\PostgresDriver\ICursor; +use Grifart\Mappi\Store\PostgresDriver\ICursorDriver; use Grifart\Mappi\Tests\Store\BaseTest; use Tester\Assert; +/** + * Every implementation of ICursorDriver must pass this test. + * + * This file is using Given-When-Then naming convention. + * @link http://martinfowler.com/bliki/GivenWhenThen.html + * + * @package Grifart\Mappi\Tests\Store\Store\PostgresDriver + */ abstract class CursorInterfaceTest extends BaseTest { - /** @var ICursor */ + /** @var ICursorDriver */ protected $uut; + + + protected function helper_fetchNextSingle() + { + $rows = $this->uut->fetchRange(1); + if(count($rows) === 0) return NULL; + return $rows[0]["n"]; + } + + protected function helper_fetchCurrentSingle() + { + $rows = $this->uut->fetchRange(0); + if(count($rows) === 0) return NULL; + return $rows[0]["n"]; + } + + protected function helper_fetchPrevSingle() + { + $rows = $this->uut->fetchRange(-1); + if(count($rows) === 0) return NULL; + return $rows[0]["n"]; + } + + + // initial position - public function test_givenCursor_whenGetCurrentRow_thenMustFail() + public function test_givenCursor_whenGetCurrentRow_thenGetNothing() { - // must fail because initial position is 0 - Assert::exception(function() { - $this->uut->fetchCurrentSingle(); - }, CursorException::class); + Assert::count(0, $this->uut->fetchRange(0)); // must fail because initial position is 0 + Assert::count(0, $this->uut->fetchRange(-1)); + Assert::count(1, $this->uut->fetchRange(1)); } public function test_givenInitialPosition_whenFetch_thenGetFirstRow() { - Assert::same(1, $this->uut->fetchNextSingle()); + Assert::same(1, $this->helper_fetchNextSingle()); } // fetch( x == 0 ) @@ -36,12 +67,12 @@ abstract class CursorInterfaceTest extends BaseTest // index: 0 1 2 3 4 // value: 1 2 3 4 $this->uut->moveTo(3); - Assert::same(3, $this->uut->fetchCurrentSingle()); + Assert::same(3, $this->helper_fetchCurrentSingle()); - $result = $this->uut->fetch(0); // rows backwards + read current + $result = $this->uut->fetchRange(0); // rows backwards + read current Assert::count(1, $result); - Assert::same(3, current($result[0]->toArray())); + Assert::same(3, current($result[0])); } // fetch( x > 0 ) @@ -51,18 +82,18 @@ abstract class CursorInterfaceTest extends BaseTest // index: 0 1 2 3 4 // value: 1 2 3 4 $this->uut->moveTo(3); - Assert::same(3, $this->uut->fetchCurrentSingle()); + Assert::same(3, $this->helper_fetchCurrentSingle()); // head: . // index: 0 1 2 3 4 5 6 // value: 1 2 3 4 5 6 - $result = $this->uut->fetch(2); // rows backwards + read current + $result = $this->uut->fetchRange(2); // rows backwards + read current // todo: split into fetch decorator for those special fetch* methods Assert::count(2, $result); - Assert::same(4, current($result[0]->toArray())); - Assert::same(5, current($result[1]->toArray())); - Assert::same(5, $this->uut->fetchCurrentSingle()); + Assert::same(4, current($result[0])); + Assert::same(5, current($result[1])); + Assert::same(5, $this->helper_fetchCurrentSingle()); } // fetch( x < 0 ) @@ -72,71 +103,68 @@ abstract class CursorInterfaceTest extends BaseTest // index: 0 1 2 3 4 // value: 1 2 3 4 $this->uut->moveTo(3); - Assert::same(3, $this->uut->fetchCurrentSingle()); + Assert::same(3, $this->helper_fetchCurrentSingle()); // head: . // index: 0 1 2 3 4 // value: 1 2 3 4 - $result = $this->uut->fetch(-2); // rows backwards + read current + $result = $this->uut->fetchRange(-2); // rows backwards + read current // todo: split into fetch decorator for those special fetch* methods Assert::count(2, $result); - Assert::same(2, current($result[0]->toArray())); - Assert::same(1, current($result[1]->toArray())); - Assert::same(1, $this->uut->fetchCurrentSingle()); + Assert::same(2, current($result[0])); + Assert::same(1, current($result[1])); + Assert::same(1, $this->helper_fetchCurrentSingle()); } // moveToBeginning() - public function test_givenEndPosition_whenMoveToTheBeginning_thenFetchingNextRowWillBeFirstRow() + public function test_givenLastPosition_whenMoveToTheBeginning_thenFetchingNextRowWillBeFirstRow() { // Arrange - $this->uut->moveToLast(); + $this->uut->moveFromEndTo(1); // Act - $this->uut->moveToBeginning(); + $this->uut->moveTo(0); //Assert - Assert::same(1, $this->uut->fetchNextSingle()); + Assert::same(1, $this->helper_fetchNextSingle()); } // moveToFirst() - public function test_givenEndPosition_whenMoveToTheFirst_thenFetchingCurrentWillBeFirstRow() + public function test_givenLastPosition_whenMoveToTheFirst_thenFetchingCurrentWillBeFirstRow() { // Arrange - $this->uut->moveToLast(); + $this->uut->moveFromEndTo(1); // Act - $this->uut->moveToFirst(); + $this->uut->moveTo(1); //Assert - Assert::same(1, $this->uut->fetchCurrentSingle()); + Assert::same(1, $this->helper_fetchCurrentSingle()); } // moveToEnd() public function test_givenInitialPosition_whenMoveToEnd_thenFetchingOneBacwardsWillBeTheLastRow() { - $this->uut->moveToEnd(); + $this->uut->moveFromEndTo(0); + + Assert::null($this->helper_fetchCurrentSingle()); - Assert::exception(function() { - $this->uut->fetchCurrentSingle(); - }, CursorException::class, CursorException::MESSAGE_NO_DATA_TO_FETCH); - $data = $this->uut->fetch(-1); - Assert::count(1, $data); - Assert::same(1000, current($data[0]->toArray())); + $data = $this->helper_fetchPrevSingle(); + Assert::same(1000, $data); } // moveToLast() public function test_givenInitialPosition_whenMoveToLast_thenFetchingCurrentWillBeLastRow() { - $this->uut->moveToLast(); - Assert::same(1000, $this->uut->fetchCurrentSingle()); - Assert::exception(function() { - $this->uut->fetchNextSingle(); - }, CursorException::class, CursorException::MESSAGE_NO_DATA_TO_FETCH); + $this->uut->moveFromEndTo(1); + Assert::same(1000, $this->helper_fetchCurrentSingle()); + + Assert::null($this->helper_fetchNextSingle()); } @@ -144,22 +172,42 @@ abstract class CursorInterfaceTest extends BaseTest public function test_givenInitialPosition_whenMoveBy2_thenGetSecondValue() { $this->uut->moveBy(2); - Assert::same(2, $this->uut->fetchCurrentSingle()); + Assert::same(2, $this->helper_fetchCurrentSingle()); } public function test_givenSecondPosition_whenMoveOneBack_thenGetFirstValue() { $this->uut->moveTo(2); $this->uut->moveBy(-1); - Assert::same(1, $this->uut->fetchCurrentSingle()); + Assert::same(1, $this->helper_fetchCurrentSingle()); + $this->uut->moveBy(-1); + Assert::null($this->helper_fetchCurrentSingle()); } // fetchOneAt() + public function test_givenInitialPosition_whenFetchBeginning_thenGetNull() + { + $data = $this->uut->fetchOneAt(0); + Assert::null($data); + } + + public function test_givenInitialPosition_whenFetchEnd_thenGetNull() + { + $data = $this->uut->fetchOneAt(1001); + Assert::null($data); + } + + public function test_givenInitialPosition_whenFetchLast_thenGetLast() + { + $data = $this->uut->fetchOneAt(1000); + Assert::same(1000, $data["n"]); + } + public function test_givenInitialPosition_whenFetch5_thenGetFive() { $data = $this->uut->fetchOneAt(5); - Assert::same(5, current($data->toArray())); + Assert::same(5, $data["n"]); } public function test_givenNonInitialPosition_whenFetch5_thenGetFive() @@ -167,7 +215,50 @@ abstract class CursorInterfaceTest extends BaseTest $this->uut->moveTo(234); // wherever $data = $this->uut->fetchOneAt(5); - Assert::same(5, current($data->toArray())); + Assert::same(5, $data["n"]); + } + + + // fetchOneBy() + public function test_givenInitialPosition_whenFetchCurrent_thenGetNull() + { + Assert::null($this->uut->fetchOneBy(0)); + } + + public function test_givenInitialPosition_whenFetchFirst_thenGetFirst() + { + $data = $this->uut->fetchOneBy(1); + Assert::same(1, $data["n"]); + } + + public function test_givenFirstPosition_whenFetchLeft_thenGetNull() + { + $this->uut->moveTo(1); + Assert::null($this->uut->fetchOneBy(-1)); + } + + public function test_givenMiddlePosition_whenFetchNext_thenGetNextPostion() + { + $this->uut->moveTo(500); + Assert::same(501, $this->uut->fetchOneBy(1)["n"]); + } + + public function test_givenLastPosition_whenFetchNext_thenGetNull() + { + $this->uut->moveFromEndTo(1); + Assert::null($this->uut->fetchOneBy(1)); + } + + public function test_givenLastPosition_whenFetchCurrent_thenGetLastRow() + { + $this->uut->moveFromEndTo(1); + Assert::same(1000, $this->uut->fetchOneBy(0)["n"]); + } + + public function test_givenLastPosition_whenFetchLeft_thenGetLeftRow() + { + $this->uut->moveFromEndTo(1); + Assert::same(999, $this->uut->fetchOneBy(-1)["n"]); } // fetchRemaining() @@ -175,18 +266,18 @@ abstract class CursorInterfaceTest extends BaseTest { $this->uut->moveTo(995); - $result = $this->uut->fetchRemaining(); + $result = $this->uut->fetchRange(ICursorDriver::FETCH_REMAINING); Assert::count(5, $result); - Assert::same(996, current($result[0]->toArray())); - Assert::same(997, current($result[1]->toArray())); - Assert::same(998, current($result[2]->toArray())); - Assert::same(999, current($result[3]->toArray())); - Assert::same(1000, current($result[4]->toArray())); + Assert::same(996, current($result[0])); + Assert::same(997, current($result[1])); + Assert::same(998, current($result[2])); + Assert::same(999, current($result[3])); + Assert::same(1000, current($result[4])); + + Assert::null($this->helper_fetchCurrentSingle()); + Assert::equal(1000, $this->helper_fetchPrevSingle()); - Assert::exception(function() { - $this->uut->fetchCurrentSingle(); - }, CursorException::class, CursorException::MESSAGE_NO_DATA_TO_FETCH); } @@ -195,56 +286,97 @@ abstract class CursorInterfaceTest extends BaseTest { $this->uut->moveTo(6); - $result = $this->uut->fetchForegoing(); + $result = $this->uut->fetchRange(ICursorDriver::FETCH_FOREGOING); Assert::count(5, $result); - Assert::same(5, current($result[0]->toArray())); - Assert::same(4, current($result[1]->toArray())); - Assert::same(3, current($result[2]->toArray())); - Assert::same(2, current($result[3]->toArray())); - Assert::same(1, current($result[4]->toArray())); + Assert::same(5, current($result[0])); + Assert::same(4, current($result[1])); + Assert::same(3, current($result[2])); + Assert::same(2, current($result[3])); + Assert::same(1, current($result[4])); - Assert::exception(function() { - $this->uut->fetchCurrentSingle(); - }, CursorException::class, CursorException::MESSAGE_NO_DATA_TO_FETCH); + Assert::null($this->helper_fetchCurrentSingle()); } // edge cases: public function test_givenInitialPosition_whenMoveToLeft_thenGetError() { + Assert::false($this->uut->isOnRecord()); // initial position + // start: index === 0 - Assert::exception(function() { - $this->uut->moveBy(-1); - }, CursorException::class, CursorException::MESSAGE_OVERFLOW); + $this->uut->moveBy(-1); + Assert::false($this->uut->isOnRecord()); // index === 0 - $data = $this->uut->fetch(-1); + $data = $this->uut->fetchRange(-1); Assert::count(0, $data); - $firstValue = $this->uut->fetchNextSingle(); + $firstValue = $this->helper_fetchNextSingle(); Assert::equal(1, $firstValue); + // index === 1 + } + public function test_givenEndPosition_whenMoveToRight_thenStayInPlace() + { + $this->uut->moveFromEndTo(0); + + Assert::null($this->helper_fetchNextSingle()); + Assert::null($this->helper_fetchCurrentSingle()); + Assert::equal(1000, $this->helper_fetchPrevSingle()); } - public function test_givenEndPosition_whenMoveToRight_thenGetError() + + public function test_giveSomePosition_whenMoveToAfterEnd_thenWillBeAtTheEnd() { - $this->uut->moveToEnd(); + $this->uut->moveTo(25); // some position - Assert::exception(function() { - $this->uut->moveBy(1); - }, CursorException::class, CursorException::MESSAGE_OVERFLOW); + $this->uut->moveTo(9999); + + Assert::null($this->helper_fetchCurrentSingle()); + Assert::equal(1000, $this->helper_fetchPrevSingle()); } + public function test_givenFirstPosition_whenMoveToLeft_thenWillBeAtBeginning() + { + // Arrange + Assert::false($this->uut->isOnRecord()); + $this->uut->moveTo(1); + Assert::true($this->uut->isOnRecord()); + + // Act + $this->uut->moveBy(-1); - public function test_giveSomePosition_whenMoveToAfterEnd_thenGetError() + // Assert + Assert::false($this->uut->isOnRecord()); + Assert::null($this->helper_fetchCurrentSingle()); + Assert::null($this->helper_fetchPrevSingle()); + + Assert::equal(1, $this->helper_fetchNextSingle()); + Assert::true($this->uut->isOnRecord()); + } + + public function test_givenLastPosition_whenMoveToRight_thenReachTheEnd() { - $this->uut->moveTo(1000); - Assert::exception(function() { - $this->uut->moveTo(1001); - }, CursorException::class, CursorException::MESSAGE_OVERFLOW); + $this->uut->moveFromEndTo(1); + Assert::true($this->uut->isOnRecord()); + + $this->uut->moveBy(1); + + Assert::false($this->uut->isOnRecord()); + Assert::null($this->helper_fetchCurrentSingle()); + Assert::null($this->helper_fetchNextSingle()); + + Assert::equal(1000, $this->helper_fetchPrevSingle()); + Assert::true($this->uut->isOnRecord()); } + public function test_giveSomePosition_whenMoveToBeginning_thenWillBeAtBeginning() + { + $this->uut->moveTo(42); + $this->uut->moveTo(0); + Assert::equal(1,$this->helper_fetchNextSingle()); + } } diff --git a/tests/Store/PostgresDriver/CursorTest.phpt b/tests/Store/PostgresDriver/CursorTest.phpt index 20bd98c3dc782c4a458678d57b0e2b25a332b159..076f0c10585863f2110b7bf73b4e58f990d14a9f 100644 --- a/tests/Store/PostgresDriver/CursorTest.phpt +++ b/tests/Store/PostgresDriver/CursorTest.phpt @@ -9,10 +9,12 @@ use Grifart\Mappi\Store\PostgresDriver\CursorException; use Grifart\Mappi\Store\PostgresDriver\CursorDriver; use Grifart\Mappi\Store\PostgresDriver\CursorFactory; use Tester\Assert; +use Tester\Environment; require_once __DIR__ . "/../../bootstrap.php"; require_once __DIR__ . "/CursorInterfaceTest.php"; +Environment::skip(); class CursorTest extends CursorInterfaceTest { protected function setUp() diff --git a/tests/Store/PostgresDriver/TrackedCursorTest.phpt b/tests/Store/PostgresDriver/TrackedCursorTest.phpt index 2d05d39ee484cc8bbc9f03a7cefcc929f292deb1..4e0af673a3387ecf855a5a0247c88610e3ad651d 100644 --- a/tests/Store/PostgresDriver/TrackedCursorTest.phpt +++ b/tests/Store/PostgresDriver/TrackedCursorTest.phpt @@ -3,11 +3,8 @@ * @testCase */ -// TODO: Add boundary checks! // TODO: moveBy() ->isOnRecord() ->moveBy() ->isOnRecord() (now I see state before and after command) -// TODO: Cursor should have dedicated method for overriding data processing // TODO: Maybe construct Cursor class in TrackedCursor constructor? -// TODO: Consistency check of inner cursor (headOnRecord === FALSE) namespace Grifart\Mappi\Tests\Store\Store\PostgresDriver; @@ -21,7 +18,7 @@ use Tester\Assert; require_once __DIR__ . "/../../bootstrap.php"; require_once __DIR__ . "/CursorInterfaceTest.php"; -class TrackedCursorTest extends BaseTest +class TrackedCursorTest extends CursorInterfaceTest { /** @link https://en.wikipedia.org/wiki/42_(number)#Hitchhiker.27s_Guide_to_the_Galaxy */ const THE_MAGIC_NUMBER = 42; @@ -51,412 +48,314 @@ class TrackedCursorTest extends BaseTest parent::tearDown(); } - private function helper_fetchNextSingle() + private function assertPosition(string $position) { - $rows = $this->uut->fetchRange(1); - if (count($rows) === 0) { - return NULL; - } - return $rows[0]["n"]; + Assert::equal($position, (string)$this->uut->getPosition()); } - private function helper_fetchCurrentSingle() + public function test_getPosition_left_initial() { - $rows = $this->uut->fetchRange(0); - if (count($rows) === 0) { - return NULL; - } - return $rows[0]["n"]; + $this->assertPosition("left:0"); } - private function helper_fetchPrevSingle() + public function test_getPosition_right_initial() { - $rows = $this->uut->fetchRange(-1); - if (count($rows) === 0) { - return NULL; - } - return $rows[0]["n"]; + $this->uut->moveFromEndTo(0); + $this->assertPosition("right:0"); } - // initial position - public function test_givenCursor_whenGetCurrentRow_thenGetNothing() + public function test_getPosition_moveTo() { - Assert::count(0, $this->uut->fetchRange(0)); // must fail because initial position is 0 - Assert::count(0, $this->uut->fetchRange(-1)); - Assert::count(1, $this->uut->fetchRange(1)); - } + $this->uut->moveTo(0); + $this->assertPosition("left:0"); + $this->uut->moveTo(1); + $this->assertPosition("left:1"); + $this->uut->moveTo(5); + $this->assertPosition("left:5"); + $this->uut->moveTo(0); + $this->assertPosition("left:0"); - public function test_givenInitialPosition_whenFetch_thenGetFirstRow() - { - Assert::same(1, $this->helper_fetchNextSingle()); + $this->uut->moveTo(1000); + $this->assertPosition("left:1000"); + + $this->uut->moveTo(1001); + $this->assertPosition("right:0"); + + $this->uut->moveTo(9999); + $this->assertPosition("right:0"); } - // fetch( x == 0 ) - public function test_givenSecondPosition_whenFetch0_thenGetCurrentRow() + public function test_getPosition_moveFromEndTo() { - // head: . - // index: 0 1 2 3 4 - // value: 1 2 3 4 - $this->uut->moveTo(3); - Assert::same(3, $this->helper_fetchCurrentSingle()); + $this->uut->moveFromEndTo(0); + $this->assertPosition("right:0"); + $this->uut->moveFromEndTo(1); + $this->assertPosition("right:1"); + $this->uut->moveFromEndTo(5); + $this->assertPosition("right:5"); + $this->uut->moveFromEndTo(0); + $this->assertPosition("right:0"); - $result = $this->uut->fetchRange(0); // rows backwards + read current + $this->uut->moveFromEndTo(1000); + $this->assertPosition("right:1000"); - Assert::count(1, $result); - Assert::same(3, current($result[0])); - } + $this->uut->moveFromEndTo(1001); + $this->assertPosition("left:0"); - // fetch( x > 0 ) - public function test_givenSecondPosition_whenFetchForward_thenGetRowsAfterCursor() - { - // head: . - // index: 0 1 2 3 4 - // value: 1 2 3 4 - $this->uut->moveTo(3); - Assert::same(3, $this->helper_fetchCurrentSingle()); - - // head: . - // index: 0 1 2 3 4 5 6 - // value: 1 2 3 4 5 6 - $result = $this->uut->fetchRange(2); // rows backwards + read current - // todo: split into fetch decorator for those special fetch* methods - - Assert::count(2, $result); - Assert::same(4, current($result[0])); - Assert::same(5, current($result[1])); - Assert::same(5, $this->helper_fetchCurrentSingle()); + $this->uut->moveFromEndTo(9999); + $this->assertPosition("left:0"); } - // fetch( x < 0 ) - public function test_givenSecondPosition_whenFetchBackwards_thenGetRowsBeforeCursor() + public function test_getPosition_left_moveBy() { - // head: . - // index: 0 1 2 3 4 - // value: 1 2 3 4 - $this->uut->moveTo(3); - Assert::same(3, $this->helper_fetchCurrentSingle()); - - // head: . - // index: 0 1 2 3 4 - // value: 1 2 3 4 - $result = $this->uut->fetchRange(-2); // rows backwards + read current - // todo: split into fetch decorator for those special fetch* methods - - Assert::count(2, $result); - Assert::same(2, current($result[0])); - Assert::same(1, current($result[1])); - Assert::same(1, $this->helper_fetchCurrentSingle()); - } + $this->uut->moveBy(-5); + $this->assertPosition("left:0"); - // moveToBeginning() - public function test_givenLastPosition_whenMoveToTheBeginning_thenFetchingNextRowWillBeFirstRow() - { - // Arrange - $this->uut->moveFromEndTo(1); + $this->uut->moveBy(0); + $this->assertPosition("left:0"); - // Act - $this->uut->moveTo(0); + $this->uut->moveBy(1); + $this->assertPosition("left:1"); - //Assert - Assert::same(1, $this->helper_fetchNextSingle()); - } + $this->uut->moveBy(0); + $this->assertPosition("left:1"); - // moveToFirst() - public function test_givenLastPosition_whenMoveToTheFirst_thenFetchingCurrentWillBeFirstRow() - { - // Arrange - $this->uut->moveFromEndTo(1); + $this->uut->moveBy(999); + $this->assertPosition("left:1000"); - // Act - $this->uut->moveTo(1); + $this->uut->moveBy(1); + $this->assertPosition("right:0"); - //Assert - Assert::same(1, $this->helper_fetchCurrentSingle()); + $this->uut->moveBy(1); + $this->assertPosition("right:0"); } - // moveToEnd() - public function test_givenInitialPosition_whenMoveToEnd_thenFetchingOneBacwardsWillBeTheLastRow() + public function test_getPosition_right_moveBy() { $this->uut->moveFromEndTo(0); + $this->assertPosition("right:0"); - Assert::null($this->helper_fetchCurrentSingle()); - - $data = $this->helper_fetchPrevSingle(); - Assert::same(1000, $data); - } + $this->uut->moveBy(1); + $this->assertPosition("right:0"); - // moveToLast() - public function test_givenInitialPosition_whenMoveToLast_thenFetchingCurrentWillBeLastRow() - { - $this->uut->moveFromEndTo(1); - Assert::same(1000, $this->helper_fetchCurrentSingle()); + $this->uut->moveBy(0); + $this->assertPosition("right:0"); - Assert::null($this->helper_fetchNextSingle()); - } + $this->uut->moveBy(-5); + $this->assertPosition("right:5"); - // moveBy() - public function test_givenInitialPosition_whenMoveBy2_thenGetSecondValue() - { - $this->uut->moveBy(2); - Assert::same(2, $this->helper_fetchCurrentSingle()); - } + $this->uut->moveBy(-995); + $this->assertPosition("right:1000"); + Assert::equal(1, $this->helper_fetchCurrentSingle()); // regression - public function test_givenSecondPosition_whenMoveOneBack_thenGetFirstValue() - { - $this->uut->moveTo(2); $this->uut->moveBy(-1); - Assert::same(1, $this->helper_fetchCurrentSingle()); + $this->assertPosition("left:0"); + Assert::null($this->helper_fetchCurrentSingle()); // regression + $this->uut->moveBy(-1); - Assert::null($this->helper_fetchCurrentSingle()); + $this->assertPosition("left:0"); } - // fetchOneAt() - public function test_givenInitialPosition_whenFetch5_thenGetFive() + public function test_getPosition_left_fetchRange() { - $data = $this->uut->fetchOneAt(5); - Assert::same(5, $data["n"]); + $this->assertPosition("left:0"); + $this->uut->fetchRange(0); + $this->assertPosition("left:0"); + + $this->uut->fetchRange(1); + $this->assertPosition("left:1"); + $this->uut->fetchRange(0); + $this->assertPosition("left:1"); + $this->uut->fetchRange(-1); + $this->assertPosition("left:0"); + + $this->uut->fetchRange(1000); + $this->assertPosition("left:1000"); + + $this->uut->fetchRange(1); + $this->assertPosition("right:0"); + + $this->uut->moveTo(999); + $this->assertPosition("left:999"); + + $this->uut->fetchRange(500); + $this->assertPosition("right:0"); } - public function test_givenNonInitialPosition_whenFetch5_thenGetFive() + public function test_getPosition_right_fetchRange() { - $this->uut->moveTo(234); // wherever + $this->uut->moveFromEndTo(0); + + $this->assertPosition("right:0"); + $this->uut->fetchRange(0); + $this->assertPosition("right:0"); + + $this->uut->fetchRange(-1); + $this->assertPosition("right:1"); + $this->uut->fetchRange(0); + $this->assertPosition("right:1"); + $this->uut->fetchRange(+1); + $this->assertPosition("right:0"); + + $this->uut->fetchRange(-1000); + $this->assertPosition("right:1000"); + + $this->uut->fetchRange(-1); + $this->assertPosition("left:0"); - $data = $this->uut->fetchOneAt(5); - Assert::same(5, $data["n"]); + $this->uut->moveFromEndTo(999); + $this->assertPosition("right:999"); + + $this->uut->fetchRange(-500); + $this->assertPosition("left:0"); } - // fetchRemaining() - public function test_given5BeforeEndPosition_whenFetchRemaining_thenGetLastFile() + public function test_getPosition_left_fetchOneAt() { - $this->uut->moveTo(995); + $this->assertPosition("left:0"); + $this->uut->fetchOneAt(0); + $this->assertPosition("left:0"); + + $this->uut->fetchOneAt(1); + $this->assertPosition("left:1"); - $result = $this->uut->fetchRange(ICursorDriver::FETCH_REMAINING); + $this->uut->fetchOneAt(500); + $this->assertPosition("left:500"); - Assert::count(5, $result); - Assert::same(996, current($result[0])); - Assert::same(997, current($result[1])); - Assert::same(998, current($result[2])); - Assert::same(999, current($result[3])); - Assert::same(1000, current($result[4])); + $this->uut->fetchOneAt(1000); + $this->assertPosition("left:1000"); - Assert::null($this->helper_fetchCurrentSingle()); - Assert::equal(1000, $this->helper_fetchPrevSingle()); + $this->uut->fetchOneAt(1001); + $this->assertPosition("right:0"); } - // fetchRemaining() - public function test_given5AfterStart_whenFetchForegoing_thenGetFirstFive() + public function test_getPosition_right_fetchOneAt() { - $this->uut->moveTo(6); + $this->assertPosition("left:0"); + $this->uut->fetchOneAt(-1); + $this->assertPosition("right:1"); + + $this->uut->fetchOneAt(-1); + $this->assertPosition("right:1"); - $result = $this->uut->fetchRange(ICursorDriver::FETCH_FOREGOING); + $this->uut->fetchOneAt(-500); + $this->assertPosition("right:500"); - Assert::count(5, $result); - Assert::same(5, current($result[0])); - Assert::same(4, current($result[1])); - Assert::same(3, current($result[2])); - Assert::same(2, current($result[3])); - Assert::same(1, current($result[4])); + $this->uut->fetchOneAt(-1000); + $this->assertPosition("right:1000"); - Assert::null($this->helper_fetchCurrentSingle()); + $this->uut->fetchOneAt(-1001); + $this->assertPosition("left:0"); } - // edge cases: - public function test_givenInitialPosition_whenMoveToLeft_thenGetError() + public function test_getPosition_left_fetchOneBy() { - Assert::false($this->uut->isOnRecord()); // initial position + $this->uut->fetchOneBy(0); + $this->assertPosition("left:0"); - // start: index === 0 - $this->uut->moveBy(-1); - Assert::false($this->uut->isOnRecord()); + $this->uut->fetchOneBy(-1); + $this->assertPosition("left:0"); + + $this->uut->fetchOneBy(1); + $this->assertPosition("left:1"); - // index === 0 - $data = $this->uut->fetchRange(-1); - Assert::count(0, $data); + $this->uut->fetchOneBy(0); + $this->assertPosition("left:1"); - $firstValue = $this->helper_fetchNextSingle(); - Assert::equal(1, $firstValue); - // index === 1 + $this->uut->fetchOneBy(-1); + $this->assertPosition("left:0"); + + $this->uut->fetchOneBy(20); + $this->uut->fetchOneBy(480); + $this->assertPosition("left:500"); + + $this->uut->fetchOneBy(500); + $this->assertPosition("left:1000"); + + $this->uut->fetchOneBy(1); + $this->assertPosition("right:0"); } - public function test_givenEndPosition_whenMoveToRight_thenStayInPlace() + public function test_getPosition_right_fetchOneBy() { $this->uut->moveFromEndTo(0); - Assert::null($this->helper_fetchNextSingle()); - Assert::null($this->helper_fetchCurrentSingle()); - Assert::equal(1000, $this->helper_fetchPrevSingle()); - } + $this->uut->fetchOneBy(0); + $this->assertPosition("right:0"); - public function test_giveSomePosition_whenMoveToAfterEnd_thenWillBeAtTheEnd() - { - $this->uut->moveTo(25); // some position + $this->uut->fetchOneBy(1); + $this->assertPosition("right:0"); - $this->uut->moveTo(9999); + $this->uut->fetchOneBy(-1); + $this->assertPosition("right:1"); - Assert::null($this->helper_fetchCurrentSingle()); - Assert::equal(1000, $this->helper_fetchPrevSingle()); - } + $this->uut->fetchOneBy(0); + $this->assertPosition("right:1"); - public function test_givenFirstPosition_whenMoveToLeft_thenWillBeAtBeginning() - { - // Arrange - Assert::false($this->uut->isOnRecord()); - $this->uut->moveTo(1); - Assert::true($this->uut->isOnRecord()); + $this->uut->fetchOneBy(1); + $this->assertPosition("right:0"); - // Act - $this->uut->moveBy(-1); + $this->uut->fetchOneBy(-20); + $this->uut->fetchOneBy(-480); + $this->assertPosition("right:500"); - // Assert - Assert::false($this->uut->isOnRecord()); - Assert::null($this->helper_fetchCurrentSingle()); - Assert::null($this->helper_fetchPrevSingle()); + $this->uut->fetchOneBy(-500); + $this->assertPosition("right:1000"); - Assert::equal(1, $this->helper_fetchNextSingle()); - Assert::true($this->uut->isOnRecord()); + $this->uut->fetchOneBy(-1); + $this->assertPosition("left:0"); } - public function test_givenLastPosition_whenMoveToRight_thenReachTheEnd() + + + public function test_getPosition_givenInitialPosition_whenMove8Right_thenWillGet8Right() { - $this->uut->moveFromEndTo(1); - Assert::true($this->uut->isOnRecord()); + $this->uut->moveBy(8); + $this->assertPosition("left:8"); + } + + public function test_getPosition_givenInitialPosition_whenMove1Right_thenWillGet1Right() + { + $this->uut->moveBy(0); $this->uut->moveBy(1); + $this->uut->moveBy(0); - Assert::false($this->uut->isOnRecord()); - Assert::null($this->helper_fetchCurrentSingle()); - Assert::null($this->helper_fetchNextSingle()); + $this->assertPosition("left:1"); + } - Assert::equal(1000, $this->helper_fetchPrevSingle()); - Assert::true($this->uut->isOnRecord()); + public function test_getPosition_givenInitialPosition_whenFetch3_thenWillBe3Right() + { + $this->uut->fetchRange(1); + $this->uut->fetchRange(2); + + $this->assertPosition("left:3"); } - public function test_giveSomePosition_whenMoveToBeginning_thenWillBeAtBeginning() + public function test_getPosition_givenRightEnd_whenFetch3Back_thenWillBe3Back() { - $this->uut->moveTo(42); - $this->uut->moveTo(0); - Assert::equal(1, $this->helper_fetchNextSingle()); + $this->uut->moveFromEndTo(0); + + $this->uut->fetchRange(-1); + $this->uut->fetchRange(-2); + + $this->assertPosition("right:3"); } + public function test_getPosition_givenRightEnd_whenGetPosition_thenOnRightEnd() + { + $this->uut->moveFromEndTo(0); + + $this->assertPosition("right:0"); + } + public function test_getPosition_givenInMiddleFromRight_whenReadToRight_thenShou() + { + $this->uut->moveFromEndTo(0); + $this->assertPosition("right:0"); + } -// -// public function test_givenBeginningPosition_whenMoveLeft_thenGetError() -// { -// $this->uut->moveToBeginning(); -// -// Assert::exception(function() { -// // todo: what to do with this non-uniformity with original CursorDriver? -// $this->uut->moveBy(-1); -// }, CursorException::class, CursorException::MESSAGE_OVERFLOW); -// -// $this->uut->moveBy(1); -// Assert::equal(1, $this->uut->fetchCurrentSingle()); -// } -// -// public function test_givenEndPosition_whenMoveToRight_thenGetError() -// { -// $this->uut->moveToEnd(); -// -// Assert::exception(function() { -// // todo: what to do with this non-uniformity with original CursorDriver? -// $this->uut->moveBy(1); -// }, CursorException::class, CursorException::MESSAGE_OVERFLOW); -// -// $this->uut->moveBy(-1); -// Assert::equal(1000, $this->uut->fetchCurrentSingle()); -// } -// -// // corrected behaviour of original cursor -// public function test_givenFirstPosition_whenMoveToLeft_thenImOnFirstValue() -// { -// $this->uut->moveToFirst(); -// -// $this->uut->moveBy(-1); -// // todo: what to do with this non-uniformity with original CursorDriver? -// Assert::equal(1, $this->uut->fetchNextSingle()); -// } -// -// public function test_givenLastPosition_whenMoveToRight_thenGetError() -// { -// // todo: what to do with this non-uniformity with original CursorDriver? -// $this->uut->moveToLast(); -// $this->uut->moveBy(1); // here is ok, now in original cursor -// -// $this->uut->moveBy(-1); // todo: make decorator which will make this nicer -// Assert::equal(1000, $this->uut->fetchCurrentSingle()); -// } -// -// -// -// // ->getPosition() tests: -// -// // moveToBeginning() -// public function test_givenInitialPosition_whenGetPosition_thenGetZero() -// { -// Assert::equal(0, $this->uut->getPosition()); -// -// $this->uut->moveToBeginning(); -// Assert::equal(0, $this->uut->getPosition()); -// -// $this->uut->moveToFirst(); -// Assert::equal(1, $this->uut->getPosition()); -// } -// -// public function test_givenMiddlePosition_whenMoveAround_thenGetCorrectPosition() -// { -// $this->uut->moveTo(self::THE_MAGIC_NUMBER); -// $this->uut->moveTo(self::THE_MAGIC_NUMBER + self::THE_MAGIC_NUMBER); -// $this->uut->moveBy(-self::THE_MAGIC_NUMBER); -// $this->uut->moveBy(+self::THE_MAGIC_NUMBER); -// $this->uut->moveBy(-self::THE_MAGIC_NUMBER); -// Assert::equal(self::THE_MAGIC_NUMBER, $this->uut->getPosition()); -// } -// -// public function test_givenEndPosition_whenGetPosition_thenGetTotalPlusOne() -// { -// $this->uut->moveToEnd(); -// Assert::equal(1001, $this->uut->getPosition()); -// } -// -// public function test_givenInitialPosition_whenMoveToLast_thenGetTotal() -// { -// $this->uut->moveToLast(); -// Assert::equal(1000, $this->uut->getPosition()); -// } -// -// // nasty edge cases: -// public function test_givenLastPosition_whenMoveToEnd_thenGetEndPosition() -// { -// $this->uut->moveToLast(); -// $this->uut->moveToEnd(); -// Assert::equal(1001, $this->uut->getPosition()); -// -// // regression test: -// $this->uut->moveToEnd(); -// Assert::equal(1001, $this->uut->getPosition()); -// } -// -// public function test_givenEndPosition_whenMoveToLast_thenGetLastPosition() -// { -// $this->uut->moveToEnd(); -// $this->uut->moveToLast(); -// Assert::equal(1000, $this->uut->getPosition()); -// -// // regression test: -// $this->uut->moveToLast(); -// Assert::equal(1000, $this->uut->getPosition()); -// } -// -// public function test_giveSomePosition_whenMoveToBeginning_thenGetToBeginning() -// { -// $this->uut->moveTo(42); -// $this->uut->moveTo(0); -// -// Assert::equal(0, $this->uut->getPosition()); -// Assert::equal(1, $this->uut->fetchNextSingle()); -// } } (new TrackedCursorTest())->run(); \ No newline at end of file