diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 75fe27a..40639f1 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['7.1', '7.2', '7.3', '7.4'] + php-versions: ['7.3', '7.4', '8.0'] name: Testing with PHP ${{ matrix.php-versions }} steps: diff --git a/composer.json b/composer.json index db37332..a899383 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Collections library for php language", "minimum-stability": "dev", "license": "MIT", - "version": "1.0.9", + "version": "1.1.7", "authors": [ { "name": "Maxim Sokolovsky", @@ -19,11 +19,11 @@ } ], "require": { - "php": ">=7.1", + "php": "^7.3 || ~8.0", "ext-json": "*" }, "require-dev": { - "phpunit/phpunit": "^7.5" + "phpunit/phpunit": "^9.5" }, "suggest": { "phpbench/phpbench": "Uses only for benchmark purposes" diff --git a/src/WS/Utils/Collections/CollectionFactory.php b/src/WS/Utils/Collections/CollectionFactory.php index 19206cd..de019ad 100644 --- a/src/WS/Utils/Collections/CollectionFactory.php +++ b/src/WS/Utils/Collections/CollectionFactory.php @@ -5,7 +5,10 @@ namespace WS\Utils\Collections; +use Iterator; +use IteratorAggregate; use RuntimeException; +use WS\Utils\Collections\Exception\UnsupportedException; class CollectionFactory { @@ -37,7 +40,7 @@ public static function generate(int $times, ?callable $generator = null): Collec /** * Generate collection of int numbers between $from and $to. If $to arg is absent $from - is count of numbers * @param int $from - * @param int $to + * @param int|null $to * @return Collection */ public static function numbers(int $from, ?int $to = null): Collection @@ -68,11 +71,25 @@ public static function fromStrict(array $values): Collection return new ArrayStrictList($values); } + /** + * @throws UnsupportedException + */ public static function fromIterable(iterable $iterable): Collection { $list = ArrayList::of(); + $count = 0; + $lastItem = null; + foreach ($iterable as $item) { + if ($count <= 1) { + $isObject = is_object($item); + if ($item === $lastItem && $isObject) { + return self::createIterableCollection($iterable); + } + $lastItem = $item; + } $list->add($item); + $count++; } return $list; @@ -82,4 +99,16 @@ public static function empty(): Collection { return ArrayList::of(); } + + private static function createIterableCollection(iterable $iterable): IteratorCollection + { + if ($iterable instanceof IteratorAggregate) { + /** @noinspection PhpUnhandledExceptionInspection */ + $iterable = $iterable->getIterator(); + } + if (!$iterable instanceof Iterator) { + throw new UnsupportedException('Only Iterator interface can be applied to IteratorCollection'); + } + return new IteratorCollection($iterable); + } } diff --git a/src/WS/Utils/Collections/Exception/UnsupportedException.php b/src/WS/Utils/Collections/Exception/UnsupportedException.php new file mode 100644 index 0000000..19c866c --- /dev/null +++ b/src/WS/Utils/Collections/Exception/UnsupportedException.php @@ -0,0 +1,9 @@ +stream() - ->each(static function ($el) use ($size, $chunkCollection, & $currentChunk, & $pointer) { - $pointer--; - $currentChunk->add($el); - - if ($pointer === 0) { - $chunkCollection->add($currentChunk); - $currentChunk = self::collectionConstructor(); - $pointer = $size; - } - }) - ; - return $chunkCollection; + $array = $collection->toArray(); + $chunkedArray = array_chunk($array, $size); + $result = self::collectionConstructor(); + foreach ($chunkedArray as $items) { + $result->add(self::collectionConstructor($items)); + }; + + return $result; }; } diff --git a/src/WS/Utils/Collections/IteratorCollection.php b/src/WS/Utils/Collections/IteratorCollection.php new file mode 100644 index 0000000..35136fd --- /dev/null +++ b/src/WS/Utils/Collections/IteratorCollection.php @@ -0,0 +1,135 @@ +iterator = $iterator; + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function add($element): bool + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function addAll(iterable $elements): bool + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function merge(Collection $collection): bool + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function clear(): void + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function remove($element): bool + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function contains($element): bool + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function equals(Collection $collection): bool + { + throw new UnsupportedException(); + } + + public function size(): int + { + $this->iterator->rewind(); + $count = 0; + while ($this->iterator->valid()) { + $this->iterator->next(); + $count++; + } + + return $count; + } + + /** + * @codeCoverageIgnore + * @return bool + */ + public function isEmpty(): bool + { + return $this->size() === 0; + } + + public function stream(): Stream + { + return new IteratorStream($this); + } + + /** + * @codeCoverageIgnore + * @return array + */ + public function toArray(): array + { + throw new UnsupportedException(); + } + + /** + * @codeCoverageIgnore + * @return Collection + */ + public function copy(): Collection + { + throw new UnsupportedException(); + } + + public function getIterator() + { + return $this->iterator; + } +} diff --git a/src/WS/Utils/Collections/IteratorStream.php b/src/WS/Utils/Collections/IteratorStream.php new file mode 100644 index 0000000..4c02115 --- /dev/null +++ b/src/WS/Utils/Collections/IteratorStream.php @@ -0,0 +1,348 @@ +collection = $collection; + } + + public function each(callable $consumer): Stream + { + /** @noinspection PhpUnhandledExceptionInspection */ + $iterator = $this->collection->getIterator(); + $iterator->rewind(); + $i = 0; + while ($iterator->valid()) { + if (!$this->isExcluded($i)) { + $item = $iterator->current(); + $consumer($item); + } + $iterator->next(); + $i++; + } + + return $this; + } + + public function walk(callable $consumer, ?int $limit = null): Stream + { + $iterationsCount = $limit ?? $this->collection->size(); + /** @noinspection PhpUnhandledExceptionInspection */ + $iterator = $this->collection->getIterator(); + $iterator->rewind(); + + $i = 0; + while ($iterator->valid()) { + if (!$this->isExcluded($i)) { + $item = $iterator->current(); + $consumerRes = $consumer($item, $i); + if ($consumerRes === false) { + break; + } + if ($i + 1 >= $iterationsCount) { + break; + } + } + + $iterator->next(); + $i++; + } + return $this; + } + + public function filter(callable $predicate): Stream + { + /** @noinspection PhpUnhandledExceptionInspection */ + $iterator = $this->collection->getIterator(); + $iterator->rewind(); + $i = 0; + while ($iterator->valid()) { + if (!$this->isExcluded($i)) { + $item = $iterator->current(); + !$predicate($item) && $this->exclude($i); + } + $iterator->next(); + $i++; + } + + return $this; + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function reorganize(callable $reorganizer): Stream + { + throw new UnsupportedException(); + } + + public function allMatch(callable $predicate): bool + { + /** @noinspection PhpUnhandledExceptionInspection */ + $iterator = $this->collection->getIterator(); + $iterator->rewind(); + $i = 0; + while ($iterator->valid()) { + if (!$this->isExcluded($i)) { + $current = $iterator->current(); + if (!$predicate($current)) { + return false; + } + } + $iterator->next(); + $i++; + } + return true; + } + + public function anyMatch(callable $predicate): bool + { + /** @noinspection PhpUnhandledExceptionInspection */ + $iterator = $this->collection->getIterator(); + $iterator->rewind(); + $i = 0; + while ($iterator->valid()) { + if (!$this->isExcluded($i)) { + $current = $iterator->current(); + if ($predicate($current)) { + return true; + } + } + $iterator->next(); + $i++; + } + return false; + } + + /** + * @throws UnsupportedException + */ + public function map(callable $converter): Stream + { + /** @noinspection PhpUnhandledExceptionInspection */ + $iterator = $this->collection->getIterator(); + $iterator->rewind(); + $i = 0; + $list = new ArrayList(); + while ($iterator->valid()) { + if (!$this->isExcluded($i)) { + $item = $iterator->current(); + $converterRes = $converter($item); + if ($converterRes === $item) { + throw new UnsupportedException('Item must be another different from sourced'); + } + $list->add($converterRes); + } + $iterator->next(); + $i++; + } + + return new SerialStream($list); + } + + /** + * @codeCoverageIgnore + */ + public function collect(callable $collector) + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function findAny() + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function findFirst(callable $filter = null) + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function findLast() + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function min(callable $comparator) + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function max(callable $comparator) + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function sort(callable $comparator): Stream + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function sortBy(callable $extractor): Stream + { + throw new UnsupportedException(); + } + + /** + * @codeCoverageIgnore + */ + public function sortDesc(callable $comparator): Stream + { + throw new UnsupportedException(); + } + + /** + * @codeCoverageIgnore + */ + public function sortByDesc(callable $extractor): Stream + { + throw new UnsupportedException(); + } + + /** + * @codeCoverageIgnore + */ + public function reverse(): Stream + { + throw new UnsupportedException(); + } + + public function reduce(callable $accumulator, $initialValue = null) + { + /** @noinspection PhpUnhandledExceptionInspection */ + $iterator = $this->collection->getIterator(); + $iterator->rewind(); + $i = 0; + $accumulate = $initialValue; + while ($iterator->valid()) { + if (!$this->isExcluded($i)) { + $accumulate = $accumulator($iterator->current(), $accumulate); + } + + $i++; + $iterator->next(); + } + + return $accumulate; + } + + public function limit(int $size): Stream + { + /** @noinspection PhpUnhandledExceptionInspection */ + $iterator = $this->collection->getIterator(); + $iterator->rewind(); + $i = 0; + $countdown = $size; + while ($iterator->valid()) { + if (!$this->isExcluded($i)) { + if ($countdown <= 0) { + $this->exclude($i); + } + $countdown--; + } + $iterator->next(); + $i++; + } + + return $this; + } + + public function when(bool $condition): Stream + { + if (!$condition) { + return new DummyStreamDecorator($this); + } + + return $this; + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function getCollection(): Collection + { + throw new UnsupportedException(); + } + + public function always(): Stream + { + return $this; + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function toArray(): array + { + throw new UnsupportedException(); + } + + /** + * @throws UnsupportedException + * @codeCoverageIgnore + */ + public function getSet(): Set + { + throw new UnsupportedException(); + } + + /** + * @param int $index + * @return void + */ + private function exclude(int $index): void + { + $this->excluded[$index] = $index; + } + + private function isExcluded(int $index): bool + { + return isset($this->excluded[$index]); + } +} diff --git a/src/WS/Utils/Collections/SerialStream.php b/src/WS/Utils/Collections/SerialStream.php index b06eef3..2bc429a 100644 --- a/src/WS/Utils/Collections/SerialStream.php +++ b/src/WS/Utils/Collections/SerialStream.php @@ -137,8 +137,10 @@ public function sortBy(callable $extractor): Stream sort($values); $newList = $this->emptyList(); foreach ($values as $value) { - $els = $map[$value] ?? []; + $key = $value.''; + $els = $map[$key] ?? []; $newList->addAll($els); + unset($map[$key]); } $this->list = $newList; diff --git a/src/WS/Utils/Collections/Stream.php b/src/WS/Utils/Collections/Stream.php index 3248840..e15bad6 100644 --- a/src/WS/Utils/Collections/Stream.php +++ b/src/WS/Utils/Collections/Stream.php @@ -8,14 +8,14 @@ interface Stream { /** - * Call function for each element in collection + * Calls function for each element in collection * @param callable $consumer Function with f(mixed $element, int $index): void interface * @return Stream */ public function each(callable $consumer): Stream; /** - * Call function for $limit element in collection. If limit is null all elements will. If consumer will return false walk stop + * Call function for $limit element in collection. If limit is null all elements will. If consumer return false walk stop * @param callable $consumer Function with f(mixed $element, int $index): ?false|mixed interface. * @param int|null $limit * @return Stream @@ -57,7 +57,7 @@ public function anyMatch(callable $predicate): bool; public function map(callable $converter): Stream; /** - * Call collector function for collection. It is terminate function + * Call collector function for collection. It is terminated function * @param callable $collector Function f(Collection $c): mixed * @return mixed */ @@ -130,7 +130,7 @@ public function reverse(): Stream; /** * Reduce collection to single value with accumulator - * @param callable $accumulator + * @param callable $accumulator * @param mixed|null $initialValue * @return mixed */ diff --git a/tests/WS/Utils/Collections/ConditionsStreamTest.php b/tests/WS/Utils/Collections/ConditionsStreamTest.php index 5e9cd17..e27e8d8 100644 --- a/tests/WS/Utils/Collections/ConditionsStreamTest.php +++ b/tests/WS/Utils/Collections/ConditionsStreamTest.php @@ -5,8 +5,8 @@ namespace WS\Utils\Collections; -use PHPUnit\Framework\MockObject\Matcher\InvokedCount; use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\Rule\InvokedCount; use PHPUnit\Framework\TestCase; use WS\Utils\Collections\Functions\Predicates; use WS\Utils\Collections\UnitConstraints\CollectionIsEqual; diff --git a/tests/WS/Utils/Collections/Iterator/IteratorHandlingTest.php b/tests/WS/Utils/Collections/Iterator/IteratorHandlingTest.php new file mode 100644 index 0000000..15fa58d --- /dev/null +++ b/tests/WS/Utils/Collections/Iterator/IteratorHandlingTest.php @@ -0,0 +1,341 @@ +stream() + ->each(static function ($i) use ($intGenerator) { + self::assertEquals($intGenerator()->getValue(), $i); + }) + ; + } + + /** + * @test + */ + public function checkPhpDirectoryIterator() + { + $iterable = new DirectoryIterator(__DIR__); + $files = CollectionFactory::fromIterable($iterable) + ->stream() + ->map(static function (DirectoryIterator $current) { + return $current->getBasename(); + }) + ->filter(Predicates::lockDuplicated()) + ->toArray() + ; + self::assertTrue(count($files) > 3); + } + + /** + * @test + */ + public function checkCustomIterator() + { + $iterable = new StatePatternIterator(5); + $differenceCount = CollectionFactory::fromIterable($iterable) + ->stream() + ->map(static function (ValueKeeper $valueKeeper) { + return $valueKeeper->getValue(); + }) + ->filter(Predicates::lockDuplicated()) + ->getCollection() + ->size() + ; + self::assertEquals(5, $differenceCount); + } + + /** + * @test + */ + public function checkStateIteratorFilter() + { + $iterable = new StatePatternIterator(6); + $result = CollectionFactory::fromIterable($iterable) + ->stream() + ->filter(static function (ValueKeeper $valueKeeper) { + return $valueKeeper->getValue() <= 3; + }) + ->map(static function (ValueKeeper $valueKeeper) { + return $valueKeeper->getValue(); + }) + ->toArray() + ; + self::assertEquals([0, 1, 2, 3], $result); + } + + /** + * @test + */ + public function checkSizeCutting() + { + $iterable = new StatePatternIterator(6); + $result = CollectionFactory::fromIterable($iterable) + ->stream() + ->filter(static function (ValueKeeper $valueKeeper) { + return $valueKeeper->getValue() > 0; + }) + ->limit(2) + ->map(static function (ValueKeeper $valueKeeper) { + return $valueKeeper->getValue(); + }) + ->toArray() + ; + self::assertEquals([1, 2], $result); + } + + /** + * @test + */ + public function checkRightSizeInStateIterator() + { + $iterable = new StatePatternIterator(3); + $size = CollectionFactory::fromIterable($iterable)->size(); + self::assertEquals(3, $size); + } + + /** + * @test + */ + public function checkEmptyIterator() + { + $iterable = new StatePatternIterator(0); + self::assertTrue(CollectionFactory::fromIterable($iterable)->isEmpty()); + } + + /** + * @test + */ + public function checkEachBehavior() + { + $iterable = new StatePatternIterator(6); + $i = 1; + CollectionFactory::fromIterable($iterable) + ->stream() + ->filter(static function (ValueKeeper $valueKeeper) { + return $valueKeeper->getValue() > 0; + }) + ->limit(4) + ->each(static function (ValueKeeper $valueKeeper) use (& $i) { + self::assertEquals($i++, $valueKeeper->getValue()); + }) + ; + } + + /** + * @test + */ + public function checkWalkingByStateIterator() + { + $iterable = new StatePatternIterator(6); + $i = 2; + $result = CollectionFactory::fromIterable($iterable) + ->stream() + ->filter(static function (ValueKeeper $keeper) { + return $keeper->getValue() > 1; + }) + ->walk(static function (ValueKeeper $keeper) use (& $i) { + self::assertTrue($keeper->getValue() === $i); + $i++; + }, 2) + ->map(static function (ValueKeeper $keeper) { + return $keeper->getValue(); + }) + ->toArray() + ; + self::assertEquals([2, 3, 4, 5], $result); + } + + /** + * @test + */ + public function checkWalkingWithStopping() + { + $iterable = new StatePatternIterator(6); + $i = 2; + $result = CollectionFactory::fromIterable($iterable) + ->stream() + ->walk(static function () use (& $i) { + if ($i <= 0) { + return false; + } + $i--; + return true; + }) + ->map(static function (ValueKeeper $keeper) { + return $keeper->getValue(); + }) + ->getCollection() + ; + self::assertEquals(6, $result->size()); + self::assertEquals(0, $i); + } + + /** + * @test + */ + public function withTwoElementsChecking() + { + $iterable = new StatePatternIterator(2); + $collection = CollectionFactory::fromIterable($iterable); + + self::assertInstanceOf(IteratorCollection::class, $collection); + self::assertInstanceOf(IteratorStream::class, $collection->stream()); + } + + /** + * @test + */ + public function checkReduceMethod() + { + $iterator = new StatePatternIterator(5); + $sumOfThree = CollectionFactory::fromIterable($iterator) + ->stream() + ->filter(static function (ValueKeeper $keeper) { + return $keeper->getValue() > 1; + }) + ->reduce(static function (ValueKeeper $keeper, $sum) { + return $sum + $keeper->getValue(); + }, 0) + ; + self::assertEquals(9, $sumOfThree); + } + + /** + * @test + */ + public function allMatchIteratorChecking() + { + $iterator = new StatePatternIterator(5); + $collection = CollectionFactory::fromIterable($iterator); + + $everythingIsInt = $collection + ->stream() + ->allMatch(static function (ValueKeeper $keeper) { + return is_int($keeper->getValue()); + }) + ; + + $greatThanTwoPredicate = static function (ValueKeeper $keeper) { + return $keeper->getValue() > 2; + }; + $everythingIsGreatThanTwo = $collection + ->stream() + ->allMatch($greatThanTwoPredicate) + ; + + $everythingIsGreatThanTwoWithFilter = $collection + ->stream() + ->filter($greatThanTwoPredicate) + ->allMatch($greatThanTwoPredicate) + ; + + self::assertTrue($everythingIsInt); + self::assertFalse($everythingIsGreatThanTwo); + self::assertTrue($everythingIsGreatThanTwoWithFilter); + } + + /** + * @test + */ + public function anyMatchIteratorChecking() + { + $greatThanTwoPredicate = static function (ValueKeeper $keeper) { + return $keeper->getValue() > 2; + }; + $greatThanTenPredicate = static function (ValueKeeper $keeper) { + return $keeper->getValue() > 10; + }; + + $iterator = new StatePatternIterator(5); + $collection = CollectionFactory::fromIterable($iterator); + + $hasElementsWithGreatThanWho = $collection + ->stream() + ->anyMatch($greatThanTwoPredicate) + ; + + $hasElementsWithGreatThanTen = $collection + ->stream() + ->anyMatch($greatThanTenPredicate) + ; + + $hasLessThanTwoFiltered = $collection + ->stream() + ->filter($greatThanTwoPredicate) + ->anyMatch(static function (ValueKeeper $keeper) { + return $keeper->getValue() <= 2; + }) + ; + + self::assertTrue($hasElementsWithGreatThanWho); + self::assertFalse($hasElementsWithGreatThanTen); + self::assertFalse($hasLessThanTwoFiltered); + } + + /** + * @test + */ + public function cunningMapChecking() + { + $iterator = new StatePatternIterator(3); + self::expectException(UnsupportedException::class); + CollectionFactory::fromIterable($iterator) + ->stream() + ->map(static function ($item) { + return $item; + }) + ->getCollection() + ; + } + + /** + * @test + */ + public function iterableStreamFlowChecking() + { + $greatThanTwoPredicate = static function (ValueKeeper $keeper) { + return $keeper->getValue() > 2; + }; + + $iterator = new StatePatternIterator(5); + + $array = CollectionFactory::fromIterable($iterator) + ->stream() + ->when(false) + ->filter($greatThanTwoPredicate) + ->always() + ->map(static function (ValueKeeper $keeper) { + return $keeper->getValue(); + }) + ->toArray() + ; + self::assertCount(5, $array); + + $stream = CollectionFactory::fromIterable($iterator) + ->stream() + ->when(true) + ->always() + ; + self::assertInstanceOf(IteratorStream::class, $stream); + } +} + diff --git a/tests/WS/Utils/Collections/Iterator/StatePatternIterator.php b/tests/WS/Utils/Collections/Iterator/StatePatternIterator.php new file mode 100644 index 0000000..c02f65c --- /dev/null +++ b/tests/WS/Utils/Collections/Iterator/StatePatternIterator.php @@ -0,0 +1,63 @@ +count = $count; + } + + public function getIterator() + { + return new class($this->count) implements Iterator, ValueKeeper { + private $current; + private $count; + + public function __construct(int $count) + { + $this->count = $count; + $this->rewind(); + } + + public function current() + { + return $this; + } + + public function next() + { + $this->current++; + } + + public function key() + { + return $this->current; + } + + public function valid(): bool + { + return $this->current < $this->count; + } + + public function rewind() + { + $this->current = 0; + } + + public function getValue() + { + return $this->current; + } + }; + } +} diff --git a/tests/WS/Utils/Collections/Iterator/ValueKeeper.php b/tests/WS/Utils/Collections/Iterator/ValueKeeper.php new file mode 100644 index 0000000..a2b8964 --- /dev/null +++ b/tests/WS/Utils/Collections/Iterator/ValueKeeper.php @@ -0,0 +1,8 @@ +assertThat($chunkedCollection->stream()->findLast(), CollectionIsEqual::to([5, 6])); } + /** + * @test + * @return void + */ + public function chunkingWhitTail(): void + { + $collection = self::toCollection(1, 2, 3, 4, 5); + $chunkedCollection = $collection + ->stream() + ->reorganize(Reorganizers::chunk(2)) + ->getCollection() + ; + $this->assertEquals(3, $chunkedCollection->size()); + $this->assertThat($chunkedCollection->stream()->findFirst(), CollectionIsEqual::to([1, 2])); + $this->assertThat($chunkedCollection->stream()->findLast(), CollectionIsEqual::to([5])); + } + /** * @test */ diff --git a/tests/WS/Utils/Collections/SerialStreamTest.php b/tests/WS/Utils/Collections/SerialStreamTest.php index fac1ae9..340dfa4 100644 --- a/tests/WS/Utils/Collections/SerialStreamTest.php +++ b/tests/WS/Utils/Collections/SerialStreamTest.php @@ -8,13 +8,13 @@ use Exception; use PHPUnit\Framework\TestCase; use WS\Utils\Collections\UnitConstraints\CollectionIsEqual; +use WS\Utils\Collections\Utils\ExampleObject; use WS\Utils\Collections\Utils\InvokeCounter; use WS\Utils\Collections\Utils\TestInteger; class SerialStreamTest extends TestCase { - /** @noinspection PhpUnusedParameterInspection */ private static function fCountAggregator(): callable { return static function (int $_, ?int $accumulate) { @@ -324,7 +324,6 @@ public function minPickChecking($input, $comparator, $expected): void * @param $comparator * @param $_ * @param $expected - * @noinspection PhpUnusedParameterInspection */ public function maxPickChecking($input, $comparator, $_, $expected): void { @@ -343,7 +342,6 @@ public function maxPickChecking($input, $comparator, $_, $expected): void * @param $_1 * @param $_2 * @param $expected - * @noinspection PhpUnusedParameterInspection */ public function sortChecking($input, $comparator, $_1, $_2, $expected): void { @@ -365,7 +363,6 @@ public function sortChecking($input, $comparator, $_1, $_2, $expected): void * @param $_1 * @param $_2 * @param $expected - * @noinspection PhpUnusedParameterInspection */ public function sortDescChecking($input, $comparator, $_1, $_2, $expected): void { @@ -431,7 +428,6 @@ public function findFirstElementWithFilter(array $input, $first, $expected): voi $this->assertEquals($expected, $actual); } - /** @noinspection PhpUnusedParameterInspection */ /** * @dataProvider firstLastElementCases * @test @@ -484,6 +480,7 @@ public function sortingWithExtractor($input, $min, $max): void $this->assertEquals($min, $actualMin->getValue()); $this->assertEquals($max, $actualMax->getValue()); + $this->assertEquals(count($input), $sortedCollection->size()); } /** @@ -502,6 +499,23 @@ public function sortingWithNotScalarValue(): void ; } + /** + * @test + */ + public function sortingWithSingleValue(): void + { + $obj = new ExampleObject(); + $obj->property = 1.12; + $sortedFirstElement = $this->createCollection([$obj]) + ->stream() + ->sortBy(static function (ExampleObject $object) { + return $object->property; + }) + ->findFirst() + ; + self::assertNotNull($sortedFirstElement); + } + /** * @dataProvider sortCases * @test @@ -547,7 +561,7 @@ public function limitedWalkCheck(): void */ public function suspendedWalkCheck(): void { - CollectionFactory::numbers(10) + $collection = CollectionFactory::numbers(10) ->stream() ->walk(function ($i) { if ($i === 2) { @@ -557,9 +571,12 @@ public function suspendedWalkCheck(): void $this->fail('El this index > 2 should not be here'); } return null; - }); + }) + ->getCollection() + ; $this->assertTrue(true); + $this->assertEquals(10, $collection->size()); } /** diff --git a/tests/WS/Utils/Collections/UnitConstraints/CollectionComparingConstraint.php b/tests/WS/Utils/Collections/UnitConstraints/CollectionComparingConstraint.php index 4843256..45badba 100644 --- a/tests/WS/Utils/Collections/UnitConstraints/CollectionComparingConstraint.php +++ b/tests/WS/Utils/Collections/UnitConstraints/CollectionComparingConstraint.php @@ -16,7 +16,6 @@ abstract class CollectionComparingConstraint extends Constraint implements Stati public function __construct($expectedCollection) { - parent::__construct(); $this->expectedCollection = $this->normalize($expectedCollection); } @@ -43,7 +42,7 @@ public function toString(): string { return sprintf( 'is accepted by %s', - $this->exporter->export($this->expectedCollection) + $this->exporter()->export($this->expectedCollection) ); }