diff --git a/composer.json b/composer.json index 44be9ef..30ec199 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,9 @@ "autoload": { "psr-0": { "Malarzm\\Collections\\": "lib/" } }, + "autoload-dev": { + "psr-4": { "Malarzm\\Collections\\Tests\\": "tests/" } + }, "extra": { "branch-alias": { "dev-master": "1.0.x-dev" diff --git a/lib/Malarzm/Collections/Mixin/ReadOnly.php b/lib/Malarzm/Collections/Mixin/ReadOnly.php new file mode 100644 index 0000000..50b96c4 --- /dev/null +++ b/lib/Malarzm/Collections/Mixin/ReadOnly.php @@ -0,0 +1,46 @@ + - ./tests/Malarzm/ + ./tests// \ No newline at end of file diff --git a/tests/BaseReadOnlyTest.php b/tests/BaseReadOnlyTest.php new file mode 100644 index 0000000..c7570ea --- /dev/null +++ b/tests/BaseReadOnlyTest.php @@ -0,0 +1,72 @@ +setExpectedException('\LogicException', 'You can not modify a read only collection.'); + parent::testClearAndIsEmpty($coll); + } + + + /** + * @dataProvider provideCollection + */ + public function testAddIsProhibited(Collection $coll, array $elements) + { + $this->setExpectedException('\LogicException', 'You can not modify a read only collection.'); + $coll->add(reset($elements)); + } + + /** + * @dataProvider provideCollection + */ + public function testRemoveIsProhibited(Collection $coll, array $elements) + { + $this->setExpectedException('\LogicException', 'You can not modify a read only collection.'); + $coll->remove(array_keys($elements)[0]); + } + + /** + * @dataProvider provideCollection + */ + public function testRemoveElementIsProhibited(Collection $coll, array $elements) + { + $this->setExpectedException('\LogicException', 'You can not modify a read only collection.'); + $coll->remove(reset($elements)); + } + + /** + * @dataProvider provideCollection + */ + public function testSetIsProhibited(Collection $coll, array $elements) + { + $this->setExpectedException('\LogicException', 'You can not modify a read only collection.'); + $coll->set(array_keys($elements)[0], reset($elements)); + } + + /** + * @dataProvider provideCollection + */ + public function testOffsetSetIsProhibited(Collection $coll, array $elements) + { + $this->setExpectedException('\LogicException', 'You can not modify a read only collection.'); + $coll[array_keys($elements)[0]] = reset($elements); + } + + /** + * @dataProvider provideCollection + */ + public function testOffsetRemoveIsProhibited(Collection $coll, array $elements) + { + $this->setExpectedException('\LogicException', 'You can not modify a read only collection.'); + unset($coll[array_keys($elements)[0]]); + } +} diff --git a/tests/Malarzm/Tests/BaseTest.php b/tests/BaseTest.php similarity index 100% rename from tests/Malarzm/Tests/BaseTest.php rename to tests/BaseTest.php diff --git a/tests/Malarzm/Tests/Collections/ArrayCollectionTest.php b/tests/Collections/ArrayCollectionTest.php similarity index 94% rename from tests/Malarzm/Tests/Collections/ArrayCollectionTest.php rename to tests/Collections/ArrayCollectionTest.php index dee9b0e..afb8dca 100644 --- a/tests/Malarzm/Tests/Collections/ArrayCollectionTest.php +++ b/tests/Collections/ArrayCollectionTest.php @@ -1,8 +1,9 @@ 1, 'bar' => 2, 7 ]; + return [ + [ new ReadOnlyArrayCollection([ 5, 7, 9 ]), [ 5, 7, 9] ], + [ new ReadOnlyArrayCollection($associative), $associative ], + ]; + } +} diff --git a/tests/Collections/ReadOnly/ReadOnlyListArrayTest.php b/tests/Collections/ReadOnly/ReadOnlyListArrayTest.php new file mode 100644 index 0000000..51367e9 --- /dev/null +++ b/tests/Collections/ReadOnly/ReadOnlyListArrayTest.php @@ -0,0 +1,22 @@ + 1]); + $this->assertSame([ 1 ], $coll->toArray()); + } +} diff --git a/tests/Collections/ReadOnly/ReadOnlyObjectSetTest.php b/tests/Collections/ReadOnly/ReadOnlyObjectSetTest.php new file mode 100644 index 0000000..6e308e4 --- /dev/null +++ b/tests/Collections/ReadOnly/ReadOnlyObjectSetTest.php @@ -0,0 +1,27 @@ +assertTrue($coll->contains($coll->first())); + $this->assertFalse($coll->contains(new \stdClass())); + } +} diff --git a/tests/Collections/ReadOnly/ReadOnlySetTest.php b/tests/Collections/ReadOnly/ReadOnlySetTest.php new file mode 100644 index 0000000..fb59a6b --- /dev/null +++ b/tests/Collections/ReadOnly/ReadOnlySetTest.php @@ -0,0 +1,32 @@ + 1, 'bar' => 2, 7 ]; + return [ + [ new ReadOnlyIntSet([ 5, 7, 9 ]), [ 5, 7, 9] ], + [ new ReadOnlyIntSet($associative), $associative ], + ]; + } +} + +class ReadOnlyIntSet extends ReadOnlySet +{ + public function compare($a, $b) + { + if ($a > $b) { + return 1; + } elseif ($a === $b) { + return 0; + } else { + return -1; + } + } +} diff --git a/tests/Collections/ReadOnly/ReadOnlySortedCollectionTest.php b/tests/Collections/ReadOnly/ReadOnlySortedCollectionTest.php new file mode 100644 index 0000000..2e4fa1f --- /dev/null +++ b/tests/Collections/ReadOnly/ReadOnlySortedCollectionTest.php @@ -0,0 +1,91 @@ + 1, 'bar' => 2, 5 ]; + return [ + [ new SortedIntCollection([ 5, 7, 9 ], 'usort'), [ 5, 7, 9] ], + [ new SortedIntCollection($associative, 'uasort'), $associative ], + ]; + } + + public function testSortIsCalled() + { + $i = 0; $spy = new SortSpy(); + ++$i; $c = new SortedIntCollection([2, 1], $spy); + $this->assertEquals($i, $spy->cnt); + } + + public function testMapKeepsSortOrder() + { + $collection = new SortedObjectCollection([ + (object) ['sortOrder' => 1], + (object) ['sortOrder' => 2], + (object) ['sortOrder' => 3], + ]); + + $newCollection = $collection->map(function ($object) { return (array) $object; }); + + $expected = [ + ['sortOrder' => 1], + ['sortOrder' => 2], + ['sortOrder' => 3], + ]; + + $this->assertSame($expected, $newCollection->toArray()); + } +} + +class SortedIntCollection extends ReadOnlySortedCollection +{ + public function compare($a, $b) + { + if ($a > $b) { + return 1; + } elseif ($a === $b) { + return 0; + } else { + return -1; + } + } +} + +class SortedObjectCollection extends ReadOnlySortedCollection +{ + public function compare($a, $b) + { + if (! $a instanceof \stdClass || ! $b instanceof \stdClass) { + return 0; + } + + if (! isset($a->sortOrder, $b->sortOrder)) { + return 0; + } + + if ($a->sortOrder > $b->sortOrder) { + return 1; + } elseif ($a->sortOrder === $b->sortOrder) { + return 0; + } else { + return -1; + } + } +} + +class SortSpy +{ + public $cnt = 0; + + public function __invoke(& $elements, $comp) + { + $this->cnt++; + usort($elements, $comp); + } +} diff --git a/tests/Collections/ReadOnly/ReadOnlySortedListTest.php b/tests/Collections/ReadOnly/ReadOnlySortedListTest.php new file mode 100644 index 0000000..dd660a8 --- /dev/null +++ b/tests/Collections/ReadOnly/ReadOnlySortedListTest.php @@ -0,0 +1,103 @@ + 8, 3 => 4, 8 => 9 ]); + $this->assertSame([4, 8, 9], $c->toArray()); + } + + public function testContainsThoroughly() + { + $c = new SortedIntList([ 5, 9, 7, 1, 3 ]); + $this->assertFalse($c->contains(0)); + $this->assertTrue($c->contains(1)); + $this->assertFalse($c->contains(2)); + $this->assertTrue($c->contains(3)); + $this->assertFalse($c->contains(4)); + $this->assertTrue($c->contains(5)); + $this->assertFalse($c->contains(6)); + $this->assertTrue($c->contains(7)); + $this->assertFalse($c->contains(8)); + $this->assertTrue($c->contains(9)); + $this->assertFalse($c->contains(10)); + } + + public function testIndexOfThoroughly() + { + $c = new SortedIntList([ 5, 9, 7, 1, 3 ]); + $this->assertSame(0, $c->indexOf(1)); + $this->assertSame(1, $c->indexOf(3)); + $this->assertSame(2, $c->indexOf(5)); + $this->assertSame(3, $c->indexOf(7)); + $this->assertSame(4, $c->indexOf(9)); + $this->assertSame(false, $c->indexOf(666)); + } + + public function testMapKeepsSortOrder() + { + $collection = new SortedObjectList([ + (object) ['sortOrder' => 1], + (object) ['sortOrder' => 2], + (object) ['sortOrder' => 3], + ]); + + $newCollection = $collection->map(function ($object) { return (array) $object; }); + + $expected = [ + ['sortOrder' => 1], + ['sortOrder' => 2], + ['sortOrder' => 3], + ]; + + $this->assertSame($expected, $newCollection->toArray()); + } +} + +class SortedIntList extends ReadOnlySortedList +{ + public function compare($a, $b) + { + if ($a > $b) { + return 1; + } elseif ($a === $b) { + return 0; + } else { + return -1; + } + } +} + +class SortedObjectList extends ReadOnlySortedList +{ + public function compare($a, $b) + { + if (! $a instanceof \stdClass || ! $b instanceof \stdClass) { + return 0; + } + + if (! isset($a->sortOrder, $b->sortOrder)) { + return 0; + } + + if ($a->sortOrder > $b->sortOrder) { + return 1; + } elseif ($a->sortOrder === $b->sortOrder) { + return 0; + } else { + return -1; + } + } +} diff --git a/tests/Malarzm/Tests/Collections/SetTest.php b/tests/Collections/SetTest.php similarity index 94% rename from tests/Malarzm/Tests/Collections/SetTest.php rename to tests/Collections/SetTest.php index 0e20da7..17bdde3 100644 --- a/tests/Malarzm/Tests/Collections/SetTest.php +++ b/tests/Collections/SetTest.php @@ -1,8 +1,9 @@ add('Malarzm\Collections\Tests', __DIR__);