2019-12-24 01:52:07 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace Psl\Tests\Collection;
|
|
|
|
|
|
|
|
use PHPUnit\Framework\TestCase;
|
2019-12-25 22:45:52 +01:00
|
|
|
use Psl\Arr;
|
|
|
|
use Psl\Collection;
|
|
|
|
use Psl\Exception;
|
|
|
|
use Psl\Iter;
|
|
|
|
use Psl\Str;
|
2019-12-24 01:52:07 +01:00
|
|
|
|
|
|
|
class VectorTest extends TestCase
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
public function testAdd(): void
|
|
|
|
{
|
|
|
|
$vector = new Collection\Vector(['foo', 'bar']);
|
|
|
|
self::assertCount(2, $vector);
|
|
|
|
|
|
|
|
$vector->add('baz');
|
|
|
|
self::assertCount(3, $vector);
|
|
|
|
self::assertSame('baz', $vector->at(2));
|
|
|
|
|
|
|
|
$vector->add('qux');
|
|
|
|
self::assertCount(4, $vector);
|
|
|
|
self::assertSame('qux', $vector->at(3));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testAddAll(): void
|
|
|
|
{
|
|
|
|
$vector = new Collection\Vector(['foo', 'bar']);
|
|
|
|
self::assertCount(2, $vector);
|
|
|
|
|
|
|
|
$vector->addAll(['baz', 'qux']);
|
|
|
|
|
|
|
|
self::assertCount(4, $vector);
|
|
|
|
self::assertSame('baz', $vector->at(2));
|
|
|
|
self::assertSame('qux', $vector->at(3));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testClear(): void
|
|
|
|
{
|
|
|
|
$vector = new Collection\Vector(['foo', 'bar']);
|
|
|
|
$vector->clear();
|
|
|
|
|
|
|
|
self::assertCount(0, $vector);
|
|
|
|
|
|
|
|
$vector = new Collection\Vector([]);
|
|
|
|
$vector->clear();
|
|
|
|
self::assertCount(0, $vector);
|
|
|
|
}
|
|
|
|
|
2019-12-24 01:52:07 +01:00
|
|
|
public function testItems(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar']);
|
|
|
|
|
|
|
|
$items = $vector->items();
|
|
|
|
|
|
|
|
self::assertCount(2, $items);
|
|
|
|
|
|
|
|
self::assertSame('foo', $items[0]);
|
|
|
|
self::assertSame('bar', $items[1]);
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testIsEmpty(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar']);
|
|
|
|
|
|
|
|
self::assertFalse($vector->isEmpty());
|
|
|
|
$vector->clear();
|
|
|
|
|
|
|
|
self::assertTrue($vector->isEmpty());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testCount(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar']);
|
|
|
|
self::assertCount(2, $vector);
|
|
|
|
|
|
|
|
$vector = $vector->filter(fn ($v) => 'foo' === $v);
|
|
|
|
self::assertCount(1, $vector);
|
|
|
|
|
|
|
|
$vector = $vector->filter(fn ($v) => false);
|
|
|
|
self::assertCount(0, $vector);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testToArray(): void
|
|
|
|
{
|
|
|
|
$vector = new Collection\Vector(['foo', 'bar']);
|
|
|
|
$array = $vector->toArray();
|
|
|
|
|
|
|
|
self::assertTrue(Arr\contains($array, 'foo'));
|
|
|
|
self::assertTrue(Arr\contains($array, 'bar'));
|
|
|
|
|
|
|
|
$vector = $vector->filter(fn ($v) => false);
|
|
|
|
$array = $vector->toArray();
|
|
|
|
|
|
|
|
self::assertEmpty($array);
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testAt(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar']);
|
|
|
|
|
|
|
|
self::assertSame('foo', $vector->at(0));
|
|
|
|
self::assertSame('bar', $vector->at(1));
|
|
|
|
|
|
|
|
$this->expectException(Exception\InvariantViolationException::class);
|
|
|
|
$this->expectExceptionMessage('Key (2) is out-of-bound.');
|
|
|
|
|
|
|
|
$vector->at(2);
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testContainsKey(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', null]);
|
|
|
|
|
|
|
|
self::assertTrue($vector->containsKey(0));
|
|
|
|
self::assertTrue($vector->containsKey(1));
|
|
|
|
self::assertTrue($vector->containsKey(2));
|
|
|
|
self::assertFalse($vector->containsKey(3));
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testGet(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar']);
|
|
|
|
|
|
|
|
self::assertSame('foo', $vector->get(0));
|
|
|
|
self::assertSame('bar', $vector->get(1));
|
|
|
|
self::assertNull($vector->get(3));
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
public function testValues(): void
|
2019-12-24 01:52:07 +01:00
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', null]);
|
|
|
|
$values = $vector->values();
|
|
|
|
|
|
|
|
self::assertCount(3, $values);
|
|
|
|
self::assertSame('foo', $values->at(0));
|
|
|
|
self::assertSame('bar', $values->at(1));
|
|
|
|
self::assertNull($values->at(2));
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
public function testKeys(): void
|
2019-12-24 01:52:07 +01:00
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', 'baz']);
|
|
|
|
$keys = $vector->keys();
|
|
|
|
|
|
|
|
self::assertCount(3, $keys);
|
|
|
|
self::assertSame(0, $keys->at(0));
|
|
|
|
self::assertSame(1, $keys->at(1));
|
|
|
|
self::assertSame(2, $keys->at(2));
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
public function testMap(): void
|
2019-12-24 01:52:07 +01:00
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', 'baz']);
|
|
|
|
|
|
|
|
$vector = $vector->map(fn ($value) => Str\uppercase($value));
|
|
|
|
self::assertSame('FOO', $vector->at(0));
|
|
|
|
self::assertSame('BAR', $vector->at(1));
|
|
|
|
self::assertSame('BAZ', $vector->at(2));
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
public function testMapWithKey(): void
|
2019-12-24 01:52:07 +01:00
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', 'baz']);
|
|
|
|
|
|
|
|
$vector = $vector->mapWithKey(fn ($key, $value) => Str\format('%s (%d)', $value, $key));
|
|
|
|
self::assertSame('foo (0)', $vector->at(0));
|
|
|
|
self::assertSame('bar (1)', $vector->at(1));
|
|
|
|
self::assertSame('baz (2)', $vector->at(2));
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
public function testFilter(): void
|
2019-12-24 01:52:07 +01:00
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 3));
|
|
|
|
|
|
|
|
$vector = $vector->filter(fn ($value) => $value >= 2);
|
|
|
|
self::assertCount(2, $vector);
|
|
|
|
$array = $vector->toArray();
|
|
|
|
|
|
|
|
self::assertFalse(Arr\contains($array, 1));
|
|
|
|
self::assertTrue(Arr\contains($array, 2));
|
|
|
|
self::assertTrue(Arr\contains($array, 3));
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
public function testFilterWithKey(): void
|
2019-12-24 01:52:07 +01:00
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', 'baz']);
|
|
|
|
|
|
|
|
$vector = $vector->filterWithKey(fn ($key, $value) => 0 === $key || 'baz' === $value);
|
|
|
|
self::assertCount(2, $vector);
|
|
|
|
|
|
|
|
$array = $vector->toArray();
|
|
|
|
|
|
|
|
self::assertTrue(Arr\contains($array, 'foo'));
|
|
|
|
self::assertFalse(Arr\contains($array, 'bar'));
|
|
|
|
self::assertTrue(Arr\contains($array, 'baz'));
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testZip(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 3));
|
|
|
|
|
|
|
|
$vector = $vector->zip(Iter\range(4, 8));
|
|
|
|
|
|
|
|
self::assertCount(3, $vector);
|
|
|
|
|
|
|
|
/** @var Collection\Pair $first */
|
|
|
|
$first = $vector->at(0);
|
|
|
|
self::assertInstanceOf(Collection\Pair::class, $first);
|
|
|
|
self::assertSame(1, $first->first());
|
|
|
|
self::assertSame(4, $first->last());
|
|
|
|
|
|
|
|
/** @var Collection\Pair $second */
|
|
|
|
$second = $vector->at(1);
|
|
|
|
self::assertInstanceOf(Collection\Pair::class, $second);
|
|
|
|
self::assertSame(2, $second->first());
|
|
|
|
self::assertSame(5, $second->last());
|
|
|
|
|
|
|
|
/** @var Collection\Pair $third */
|
|
|
|
$third = $vector->at(2);
|
|
|
|
self::assertInstanceOf(Collection\Pair::class, $third);
|
|
|
|
self::assertSame(3, $third->first());
|
|
|
|
self::assertSame(6, $third->last());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testTake(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', 'baz', 'qux']);
|
|
|
|
|
|
|
|
$vector = $vector->take(2);
|
|
|
|
|
|
|
|
self::assertCount(2, $vector);
|
|
|
|
self::assertSame(['foo', 'bar'], $vector->toArray());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testTakeWhile(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', 'baz', 'qux']);
|
|
|
|
|
|
|
|
$vector = $vector->takeWhile(fn ($value) => 'baz' !== $value);
|
|
|
|
|
|
|
|
self::assertCount(2, $vector);
|
|
|
|
self::assertSame(['foo', 'bar'], $vector->toArray());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testDrop(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', 'baz', 'qux']);
|
|
|
|
|
|
|
|
$vector = $vector->drop(2);
|
|
|
|
|
|
|
|
self::assertCount(2, $vector);
|
|
|
|
self::assertSame(['baz', 'qux'], $vector->toArray());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testDropWhile(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', 'baz', 'qux']);
|
|
|
|
|
|
|
|
$vector = $vector->dropWhile(fn ($value) => 'baz' !== $value);
|
|
|
|
|
|
|
|
self::assertCount(2, $vector);
|
|
|
|
self::assertSame(['baz', 'qux'], $vector->toArray());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testSlice(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo', 'bar', 'baz', 'qux']);
|
|
|
|
|
|
|
|
$vector = $vector->slice(2, 1);
|
|
|
|
|
|
|
|
self::assertCount(1, $vector);
|
|
|
|
self::assertSame(['baz'], $vector->toArray());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testConcat(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 5));
|
|
|
|
$vector = $vector->concat(Iter\range(6, 10));
|
|
|
|
|
|
|
|
self::assertCount(10, $vector);
|
|
|
|
self::assertSame([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], $vector->toArray());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testFirst(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 5));
|
|
|
|
|
|
|
|
self::assertSame(1, $vector->first());
|
|
|
|
|
|
|
|
$vector = new Collection\Vector([]);
|
|
|
|
|
|
|
|
self::assertNull($vector->first());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testFirstKey(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 5));
|
|
|
|
|
|
|
|
self::assertSame(0, $vector->firstKey());
|
|
|
|
|
|
|
|
$vector = new Collection\Vector([]);
|
|
|
|
|
|
|
|
self::assertNull($vector->firstKey());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testLast(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 5));
|
|
|
|
|
|
|
|
self::assertSame(5, $vector->last());
|
|
|
|
|
|
|
|
$vector = new Collection\Vector([]);
|
|
|
|
|
|
|
|
self::assertNull($vector->last());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testLastKey(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 5));
|
2019-12-24 01:52:07 +01:00
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
self::assertSame(4, $vector->lastKey());
|
2019-12-24 01:52:07 +01:00
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector([]);
|
2019-12-24 01:52:07 +01:00
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
self::assertNull($vector->lastKey());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
public function testImmutable(): void
|
2019-12-24 01:52:07 +01:00
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(['foo' => 1, 'bar' => 2, 'baz' => 3, 'qux' => 4]);
|
|
|
|
$immutable = $vector->immutable();
|
2019-12-24 01:52:07 +01:00
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
self::assertSame($vector->toArray(), $immutable->toArray());
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
2019-12-25 22:45:52 +01:00
|
|
|
public function testGetIterator(): void
|
2019-12-24 01:52:07 +01:00
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 10));
|
|
|
|
|
|
|
|
$iterator = $vector->getIterator();
|
|
|
|
self::assertInstanceOf(Iter\Iterator::class, $iterator);
|
|
|
|
|
|
|
|
$array = \iterator_to_array($iterator);
|
|
|
|
self::assertSame([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], $array);
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testSet(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 10));
|
|
|
|
|
|
|
|
$vector->set(0, 5);
|
|
|
|
|
|
|
|
self::assertSame(5, $vector->get(0));
|
|
|
|
|
|
|
|
$this->expectException(Exception\InvariantViolationException::class);
|
|
|
|
$this->expectExceptionMessage('Key (20) is out-of-bound. If you want to add a value even if a key is not present, use `add()`.');
|
|
|
|
|
|
|
|
$vector->set(20, 5);
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testSetAll(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(1, 10));
|
|
|
|
|
|
|
|
$vector->setAll(Iter\range(10, 12));
|
|
|
|
|
|
|
|
self::assertSame(10, $vector->get(0));
|
|
|
|
self::assertSame(11, $vector->get(1));
|
|
|
|
self::assertSame(12, $vector->get(2));
|
|
|
|
|
|
|
|
$this->expectException(Exception\InvariantViolationException::class);
|
|
|
|
$this->expectExceptionMessage('Key (15) is out-of-bound. If you want to add a value even if a key is not present, use `addAll()`.');
|
|
|
|
|
|
|
|
$vector->setAll([15 => 5]);
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testRemoveKey(): void
|
|
|
|
{
|
2019-12-25 22:45:52 +01:00
|
|
|
$vector = new Collection\Vector(Iter\range(0, 4));
|
|
|
|
|
|
|
|
self::assertCount(5, $vector);
|
|
|
|
|
|
|
|
$vector->removeKey(2);
|
|
|
|
|
|
|
|
self::assertCount(4, $vector);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testLinearSearch(): void
|
|
|
|
{
|
|
|
|
$vector = new Collection\Vector(Iter\range(1, 4));
|
|
|
|
|
|
|
|
self::assertSame(0, $vector->linearSearch(1));
|
|
|
|
self::assertSame(1, $vector->linearSearch(2));
|
|
|
|
self::assertSame(2, $vector->linearSearch(3));
|
|
|
|
self::assertSame(3, $vector->linearSearch(4));
|
|
|
|
|
|
|
|
self::assertNull($vector->linearSearch(5));
|
2019-12-24 01:52:07 +01:00
|
|
|
}
|
|
|
|
}
|