Tobias Gritschacher has submitted this change and it was merged. Change subject: Introduced ValueComparer interface ......................................................................
Introduced ValueComparer interface Change-Id: I671a8dc821e2f02f451723d36fa0674528723f70 --- M Diff.classes.php M Diff.mw.php M RELEASE-NOTES A includes/Comparer/CallbackComparer.php A includes/Comparer/StrictComparer.php A includes/Comparer/ValueComparer.php M includes/patcher/MapPatcher.php A tests/phpunit/Comparer/CallbackComparerTest.php A tests/phpunit/Comparer/StrictComparerTest.php M tests/phpunit/patcher/MapPatcherTest.php 10 files changed, 393 insertions(+), 2 deletions(-) Approvals: Tobias Gritschacher: Verified; Looks good to me, approved diff --git a/Diff.classes.php b/Diff.classes.php index fb1ff9e..fb806a0 100644 --- a/Diff.classes.php +++ b/Diff.classes.php @@ -15,6 +15,10 @@ 'Diff\Appendable' => 'includes/Appendable.php', 'Diff\DiffOpFactory' => 'includes/DiffOpFactory.php', + 'Diff\Comparer\CallbackComparer' => 'includes/Comparer/CallbackComparer.php', + 'Diff\Comparer\StrictComparer' => 'includes/Comparer/StrictComparer.php', + 'Diff\Comparer\ValueComparer' => 'includes/Comparer/ValueComparer.php', + 'Diff\CallbackListDiffer' => 'includes/differ/CallbackListDiffer.php', 'Diff\Differ' => 'includes/differ/Differ.php', 'Diff\ListDiffer' => 'includes/differ/ListDiffer.php', diff --git a/Diff.mw.php b/Diff.mw.php index daae74c..dfadc9e 100644 --- a/Diff.mw.php +++ b/Diff.mw.php @@ -58,6 +58,9 @@ $wgHooks['UnitTestsList'][] = function( array &$files ) { // @codeCoverageIgnoreStart $testFiles = array( + 'Comparer/CallbackComparer', + 'Comparer/StrictComparer', + 'differ/CallbackListDiffer', 'differ/ListDiffer', 'differ/MapDiffer', diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 0f0a207..3d412e2 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -15,6 +15,8 @@ ; Additions * Added phpunit.php runner in the tests directory +* Added Diff\Comparer\ValueComparer interface with CallbackComparer and StrictComparer implementations +* Added MapPatcher::setValueComparer to facilitate patching maps containing objects ; Removals diff --git a/includes/Comparer/CallbackComparer.php b/includes/Comparer/CallbackComparer.php new file mode 100644 index 0000000..749719c --- /dev/null +++ b/includes/Comparer/CallbackComparer.php @@ -0,0 +1,49 @@ +<?php + +namespace Diff\Comparer; + +/** + * Adapter around a comparision callback that implements the ValueComparer + * interface. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @since 0.6 + * + * @file + * @ingroup Diff + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < jeroended...@gmail.com > + */ +class CallbackComparer implements ValueComparer { + + private $callback; + + /** + * @since 0.6 + * + * @param callable $callback + */ + public function __construct( $callback ) { + $this->callback = $callback; + } + + public function valuesAreEqual( $firstValue, $secondValue ) { + return call_user_func_array( $this->callback, array( $firstValue, $secondValue ) ); + } + +} diff --git a/includes/Comparer/StrictComparer.php b/includes/Comparer/StrictComparer.php new file mode 100644 index 0000000..4734858 --- /dev/null +++ b/includes/Comparer/StrictComparer.php @@ -0,0 +1,37 @@ +<?php + +namespace Diff\Comparer; + +/** + * Value comparer that uses PHPs native strict equality check (ie ===). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @since 0.6 + * + * @file + * @ingroup Diff + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < jeroended...@gmail.com > + */ +class StrictComparer implements ValueComparer { + + public function valuesAreEqual( $firstValue, $secondValue ) { + return $firstValue === $secondValue; + } + +} diff --git a/includes/Comparer/ValueComparer.php b/includes/Comparer/ValueComparer.php new file mode 100644 index 0000000..97dfb42 --- /dev/null +++ b/includes/Comparer/ValueComparer.php @@ -0,0 +1,43 @@ +<?php + +namespace Diff\Comparer; + +/** + * Interface for objects that can determine if two values are equal. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @since 0.6 + * + * @file + * @ingroup Diff + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < jeroended...@gmail.com > + */ +interface ValueComparer { + + /** + * @since 0.6 + * + * @param mixed $firstValue + * @param mixed $secondValue + * + * @return boolean + */ + public function valuesAreEqual( $firstValue, $secondValue ); + +} diff --git a/includes/patcher/MapPatcher.php b/includes/patcher/MapPatcher.php index 5c3f920..2ebd70f 100644 --- a/includes/patcher/MapPatcher.php +++ b/includes/patcher/MapPatcher.php @@ -2,6 +2,8 @@ namespace Diff; +use Diff\Comparer\StrictComparer; +use Diff\Comparer\ValueComparer; use RuntimeException; /** @@ -40,10 +42,17 @@ protected $listPatcher; /** + * @since 0.6 + * + * @var ValueComparer|null + */ + protected $comparer = null; + + /** * @since 0.4 * * @param bool $throwErrors - * @param Patcher|null $listPatcher + * @param Patcher|null $listPatcher The patcher that will be used for lists in the value */ public function __construct( $throwErrors = false, Patcher $listPatcher = null ) { parent::__construct( $throwErrors ); @@ -53,6 +62,17 @@ } $this->listPatcher = $listPatcher; + } + + /** + * Sets the value comparer that should be used to determine if values are equal. + * + * @since 0.6 + * + * @param ValueComparer $comparer + */ + public function setValueComparer( ValueComparer $comparer ) { + $this->comparer = $comparer; } /** @@ -132,7 +152,7 @@ continue; } - if ( $base[$key] !== $diffOp->getOldValue() ) { + if ( !$this->valuesAreEqual( $base[$key], $diffOp->getOldValue() ) ) { $this->handleError( 'Tried changing a map value from an invalid source value' ); continue; } @@ -147,4 +167,12 @@ return $base; } + protected function valuesAreEqual( $firstValue, $secondValue ) { + if ( $this->comparer === null ) { + $this->comparer = new StrictComparer(); + } + + return $this->comparer->valuesAreEqual( $firstValue, $secondValue ); + } + } diff --git a/tests/phpunit/Comparer/CallbackComparerTest.php b/tests/phpunit/Comparer/CallbackComparerTest.php new file mode 100644 index 0000000..ef70534 --- /dev/null +++ b/tests/phpunit/Comparer/CallbackComparerTest.php @@ -0,0 +1,78 @@ +<?php + +namespace Diff\Tests\Comparer; + +use Diff\Comparer\CallbackComparer; +use Diff\Tests\DiffTestCase; + +/** + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + * @since 0.6 + * + * @ingroup DiffTest + * + * @group Diff + * @group Comparer + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < jeroended...@gmail.com > + */ +class CallbackComparerTest extends DiffTestCase { + + protected function newComparerInstance() { + return new CallbackComparer( function( $firstValue, $secondValue ) { + return $firstValue === 1 || $firstValue === $secondValue; + } ); + } + + /** + * @dataProvider equalProvider + */ + public function testEqualValuesAreEqual( $firstValue, $secondValue ) { + $comparer = $this->newComparerInstance(); + + $this->assertTrue( $comparer->valuesAreEqual( $firstValue, $secondValue ) ); + } + + public function equalProvider() { + return array( + array( 1, 0 ), + array( 1, 1 ), + array( 1, 2 ), + array( 2, 2 ), + ); + } + + /** + * @dataProvider unequalProvider + */ + public function testDifferentValuesAreNotEqual( $firstValue, $secondValue ) { + $comparer = $this->newComparerInstance(); + + $this->assertFalse( $comparer->valuesAreEqual( $firstValue, $secondValue ) ); + } + + public function unequalProvider() { + return array( + array( 0, 1 ), + array( 0, 2 ), + array( 0, '0' ), + ); + } + +} diff --git a/tests/phpunit/Comparer/StrictComparerTest.php b/tests/phpunit/Comparer/StrictComparerTest.php new file mode 100644 index 0000000..a6d8472 --- /dev/null +++ b/tests/phpunit/Comparer/StrictComparerTest.php @@ -0,0 +1,96 @@ +<?php + +namespace Diff\Tests\Comparer; + +use Diff\Comparer\StrictComparer; +use Diff\Tests\DiffTestCase; + +/** + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * + * @file + * @since 0.6 + * + * @ingroup DiffTest + * + * @group Diff + * @group Comparer + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < jeroended...@gmail.com > + */ +class StrictComparerTest extends DiffTestCase { + + /** + * @dataProvider equalProvider + */ + public function testEqualValuesAreEqual( $firstValue, $secondValue ) { + $comparer = new StrictComparer(); + + $this->assertTrue( $comparer->valuesAreEqual( $firstValue, $secondValue ) ); + } + + public function equalProvider() { + return array( + array( 1, 1 ), + array( '', '' ), + array( '1', '1' ), + array( 'foo bar ', 'foo bar ' ), + array( 4.2, 4.2 ), + array( null, null ), + array( false, false ), + array( true, true ), + array( array(), array() ), + array( array( 1 ), array( 1 ) ), + array( array( 1, 2, 'a' ), array( 1, 2, 'a' ) ), + array( array( 'a' => 1, 'b' => 2, null ), array( 'a' => 1, 'b' => 2, null ) ), + ); + } + + /** + * @dataProvider unequalProvider + */ + public function testDifferentValuesAreNotEqual( $firstValue, $secondValue ) { + $comparer = new StrictComparer(); + + $this->assertFalse( $comparer->valuesAreEqual( $firstValue, $secondValue ) ); + } + + public function unequalProvider() { + return array( + array( 1, 2 ), + array( '', '0' ), + array( '', ' ' ), + array( '', 0 ), + array( '', false ), + array( null, false ), + array( null, 0 ), + array( '1', '01' ), + array( 'foo bar', 'foo bar ' ), + array( 4, 4.0 ), + array( 4.2, 4.3 ), + array( false, true ), + array( true, '1' ), + array( array(), array( 1 ) ), + array( array( 1 ), array( 2 ) ), + array( array( 1, 2, 'b' ), array( 1, 2, 'c' ) ), + array( array( 'a' => 1, 'b' => 2 ), array( 'a' => 1, 'b' => 2, null ) ), + array( new \stdClass(), new \stdClass() ), + array( (object)array( 'a' => 1, 'b' => 2, null ), (object)array( 'a' => 1, 'b' => 3, null ) ), + ); + } + +} diff --git a/tests/phpunit/patcher/MapPatcherTest.php b/tests/phpunit/patcher/MapPatcherTest.php index a4f90bb..8b582c0 100644 --- a/tests/phpunit/patcher/MapPatcherTest.php +++ b/tests/phpunit/patcher/MapPatcherTest.php @@ -2,6 +2,8 @@ namespace Diff\Tests; +use Diff\Comparer\CallbackComparer; +use Diff\Comparer\StrictComparer; use Diff\Diff; use Diff\DiffOpAdd; use Diff\DiffOpChange; @@ -215,4 +217,53 @@ $this->assertEquals( $expected->getOperations(), $actual->getOperations(), $message ); } + public function testSetValueComparerToAlwaysFalse() { + $patcher = new MapPatcher(); + + $patcher->setValueComparer( new CallbackComparer( function( $firstValue, $secondValue ) { + return false; + } ) ); + + $baseMap = array( + 'foo' => 42, + 'bar' => 9001, + ); + + $patch = new Diff( array( + 'foo' => new DiffOpChange( 42, 1337 ), + 'bar' => new DiffOpChange( 9001, 1337 ), + ) ); + + $patchedMap = $patcher->patch( $baseMap, $patch ); + + $this->assertEquals( $baseMap, $patchedMap ); + } + + public function testSetValueComparerToAlwaysTrue() { + $patcher = new MapPatcher(); + + $patcher->setValueComparer( new CallbackComparer( function( $firstValue, $secondValue ) { + return true; + } ) ); + + $baseMap = array( + 'foo' => 42, + 'bar' => 9001, + ); + + $patch = new Diff( array( + 'foo' => new DiffOpChange( 3, 1337 ), + 'bar' => new DiffOpChange( 3, 1337 ), + ) ); + + $expectedMap = array( + 'foo' => 1337, + 'bar' => 1337, + ); + + $patchedMap = $patcher->patch( $baseMap, $patch ); + + $this->assertEquals( $expectedMap, $patchedMap ); + } + } -- To view, visit https://gerrit.wikimedia.org/r/61017 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I671a8dc821e2f02f451723d36fa0674528723f70 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Diff Gerrit-Branch: mw1.22-wmf3 Gerrit-Owner: Tobias Gritschacher <tobias.gritschac...@wikimedia.de> Gerrit-Reviewer: Jeroen De Dauw <jeroended...@gmail.com> Gerrit-Reviewer: Tobias Gritschacher <tobias.gritschac...@wikimedia.de> Gerrit-Reviewer: jenkins-bot _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits