From 5fd96867db89931fb13d511ff57882ad55da8714 Mon Sep 17 00:00:00 2001 From: Maciej Malarz Date: Sun, 22 Oct 2017 22:20:13 +0200 Subject: [PATCH 1/2] Add read only implementations of provided collections --- lib/Malarzm/Collections/Mixin/ReadOnly.php | 46 ++++++++ .../ReadOnly/ReadOnlyArrayCollection.php | 11 ++ .../ReadOnly/ReadOnlyListArray.php | 11 ++ .../ReadOnly/ReadOnlyObjectSet.php | 11 ++ .../Collections/ReadOnly/ReadOnlySet.php | 11 ++ .../ReadOnly/ReadOnlySortedCollection.php | 11 ++ .../ReadOnly/ReadOnlySortedList.php | 11 ++ tests/Malarzm/Tests/BaseReadOnlyTest.php | 72 ++++++++++++ .../ReadOnly/ReadOnlyArrayCollectionTest.php | 19 ++++ .../ReadOnly/ReadOnlyListArrayTest.php | 22 ++++ .../ReadOnly/ReadOnlyObjectSetTest.php | 27 +++++ .../Collections/ReadOnly/ReadOnlySetTest.php | 32 ++++++ .../ReadOnly/ReadOnlySortedCollectionTest.php | 91 ++++++++++++++++ .../ReadOnly/ReadOnlySortedListTest.php | 103 ++++++++++++++++++ 14 files changed, 478 insertions(+) create mode 100644 lib/Malarzm/Collections/Mixin/ReadOnly.php create mode 100644 lib/Malarzm/Collections/ReadOnly/ReadOnlyArrayCollection.php create mode 100644 lib/Malarzm/Collections/ReadOnly/ReadOnlyListArray.php create mode 100644 lib/Malarzm/Collections/ReadOnly/ReadOnlyObjectSet.php create mode 100644 lib/Malarzm/Collections/ReadOnly/ReadOnlySet.php create mode 100644 lib/Malarzm/Collections/ReadOnly/ReadOnlySortedCollection.php create mode 100644 lib/Malarzm/Collections/ReadOnly/ReadOnlySortedList.php create mode 100644 tests/Malarzm/Tests/BaseReadOnlyTest.php create mode 100644 tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyArrayCollectionTest.php create mode 100644 tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyListArrayTest.php create mode 100644 tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyObjectSetTest.php create mode 100644 tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlySetTest.php create mode 100644 tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlySortedCollectionTest.php create mode 100644 tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlySortedListTest.php 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 @@ +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/Collections/ReadOnly/ReadOnlyArrayCollectionTest.php b/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyArrayCollectionTest.php new file mode 100644 index 0000000..912a794 --- /dev/null +++ b/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyArrayCollectionTest.php @@ -0,0 +1,19 @@ + 1, 'bar' => 2, 7 ]; + return [ + [ new ReadOnlyArrayCollection([ 5, 7, 9 ]), [ 5, 7, 9] ], + [ new ReadOnlyArrayCollection($associative), $associative ], + ]; + } +} diff --git a/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyListArrayTest.php b/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyListArrayTest.php new file mode 100644 index 0000000..51367e9 --- /dev/null +++ b/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyListArrayTest.php @@ -0,0 +1,22 @@ + 1]); + $this->assertSame([ 1 ], $coll->toArray()); + } +} diff --git a/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyObjectSetTest.php b/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyObjectSetTest.php new file mode 100644 index 0000000..6e308e4 --- /dev/null +++ b/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlyObjectSetTest.php @@ -0,0 +1,27 @@ +assertTrue($coll->contains($coll->first())); + $this->assertFalse($coll->contains(new \stdClass())); + } +} diff --git a/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlySetTest.php b/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlySetTest.php new file mode 100644 index 0000000..9aeb669 --- /dev/null +++ b/tests/Malarzm/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/Malarzm/Tests/Collections/ReadOnly/ReadOnlySortedCollectionTest.php b/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlySortedCollectionTest.php new file mode 100644 index 0000000..2e4fa1f --- /dev/null +++ b/tests/Malarzm/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/Malarzm/Tests/Collections/ReadOnly/ReadOnlySortedListTest.php b/tests/Malarzm/Tests/Collections/ReadOnly/ReadOnlySortedListTest.php new file mode 100644 index 0000000..dd660a8 --- /dev/null +++ b/tests/Malarzm/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; + } + } +} From 8cef96034461b43580fdaad39158bb3ff852aa4d Mon Sep 17 00:00:00 2001 From: Maciej Malarz Date: Wed, 20 Dec 2017 16:04:11 +0100 Subject: [PATCH 2/2] Unscrew test structure --- composer.json | 3 +++ phpunit.xml.dist | 2 +- tests/{Malarzm/Tests => }/BaseReadOnlyTest.php | 0 tests/{Malarzm/Tests => }/BaseTest.php | 0 tests/{Malarzm/Tests => }/Collections/ArrayCollectionTest.php | 3 ++- tests/{Malarzm/Tests => }/Collections/DiffableTest.php | 3 ++- tests/{Malarzm/Tests => }/Collections/ListArrayTest.php | 3 ++- tests/{Malarzm/Tests => }/Collections/ObjectSetTest.php | 3 ++- .../Collections/ReadOnly/ReadOnlyArrayCollectionTest.php | 0 .../Tests => }/Collections/ReadOnly/ReadOnlyListArrayTest.php | 0 .../Tests => }/Collections/ReadOnly/ReadOnlyObjectSetTest.php | 0 .../Tests => }/Collections/ReadOnly/ReadOnlySetTest.php | 2 +- .../Collections/ReadOnly/ReadOnlySortedCollectionTest.php | 0 .../Tests => }/Collections/ReadOnly/ReadOnlySortedListTest.php | 0 tests/{Malarzm/Tests => }/Collections/SetTest.php | 3 ++- tests/{Malarzm/Tests => }/Collections/SortedCollectionTest.php | 3 ++- tests/{Malarzm/Tests => }/Collections/SortedListTest.php | 3 ++- tests/bootstrap.php | 2 -- 18 files changed, 19 insertions(+), 11 deletions(-) rename tests/{Malarzm/Tests => }/BaseReadOnlyTest.php (100%) rename tests/{Malarzm/Tests => }/BaseTest.php (100%) rename tests/{Malarzm/Tests => }/Collections/ArrayCollectionTest.php (94%) rename tests/{Malarzm/Tests => }/Collections/DiffableTest.php (95%) rename tests/{Malarzm/Tests => }/Collections/ListArrayTest.php (93%) rename tests/{Malarzm/Tests => }/Collections/ObjectSetTest.php (96%) rename tests/{Malarzm/Tests => }/Collections/ReadOnly/ReadOnlyArrayCollectionTest.php (100%) rename tests/{Malarzm/Tests => }/Collections/ReadOnly/ReadOnlyListArrayTest.php (100%) rename tests/{Malarzm/Tests => }/Collections/ReadOnly/ReadOnlyObjectSetTest.php (100%) rename tests/{Malarzm/Tests => }/Collections/ReadOnly/ReadOnlySetTest.php (90%) rename tests/{Malarzm/Tests => }/Collections/ReadOnly/ReadOnlySortedCollectionTest.php (100%) rename tests/{Malarzm/Tests => }/Collections/ReadOnly/ReadOnlySortedListTest.php (100%) rename tests/{Malarzm/Tests => }/Collections/SetTest.php (94%) rename tests/{Malarzm/Tests => }/Collections/SortedCollectionTest.php (96%) rename tests/{Malarzm/Tests => }/Collections/SortedListTest.php (97%) 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/phpunit.xml.dist b/phpunit.xml.dist index 30f9d81..09fb130 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -12,7 +12,7 @@ > - ./tests/Malarzm/ + ./tests// \ No newline at end of file diff --git a/tests/Malarzm/Tests/BaseReadOnlyTest.php b/tests/BaseReadOnlyTest.php similarity index 100% rename from tests/Malarzm/Tests/BaseReadOnlyTest.php rename to tests/BaseReadOnlyTest.php 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 @@ add('Malarzm\Collections\Tests', __DIR__);