jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/378414 )
Change subject: Add TermList (lemmaList) shrinking ...................................................................... Add TermList (lemmaList) shrinking Change-Id: I5a3e09b2393fb2e4f4239efee90be3de6c79cfbb --- A tests/phpunit/composer/ErisGenerators/CartesianProduct.php A tests/phpunit/composer/ErisGenerators/CartesianProductTest.php M tests/phpunit/composer/ErisGenerators/LexemeGenerator.php M tests/phpunit/composer/ErisGenerators/TermListGenerator.php 4 files changed, 317 insertions(+), 5 deletions(-) Approvals: WMDE-leszek: Looks good to me, approved jenkins-bot: Verified diff --git a/tests/phpunit/composer/ErisGenerators/CartesianProduct.php b/tests/phpunit/composer/ErisGenerators/CartesianProduct.php new file mode 100644 index 0000000..aa6930d --- /dev/null +++ b/tests/phpunit/composer/ErisGenerators/CartesianProduct.php @@ -0,0 +1,116 @@ +<?php + +namespace Wikibase\Lexeme\Tests\ErisGenerators; + +use Eris\Generator\GeneratedValueOptions; +use Eris\Generator\GeneratedValueSingle; + +class CartesianProduct { + + /** + * @var GeneratedValueOptions[] + */ + private $generatedValues; + + /** + * @param GeneratedValueOptions|GeneratedValueSingle $generatedValue + * @param GeneratedValueOptions|GeneratedValueSingle $_generatedValue + * + * @return CartesianProduct + */ + public static function create( $generatedValue /*, ...$_generatedValue*/ ) { + $args = func_get_args(); + + $resultingValues = array_map( + function ( $generatedValue ) { + if ( $generatedValue instanceof GeneratedValueSingle ) { + return new GeneratedValueOptions( [ $generatedValue ] ); + } elseif ( $generatedValue instanceof GeneratedValueOptions ) { + return $generatedValue; + } else { + throw new \InvalidArgumentException( + '$generatedValue can only be GeneratedValueOptions or GeneratedValueSingle' + ); + } + }, + $args + ); + + return new self( $resultingValues ); + } + + private function __construct( array $generatedValues ) { + $this->generatedValues = $generatedValues; + } + + public function map( callable $fn, $generatorName = 'CartesianProduct' ) { + $result = $this->combine( $generatorName ); + + return $result->map( + function ( array $args ) use ( $fn ) { + return call_user_func_array( $fn, $args ); + }, + $generatorName + ); + } + + /** + * @param $generatorName + * + * @return GeneratedValueOptions + */ + private function combine( $generatorName ) { + if ( count( $this->generatedValues ) === 1 ) { + return $this->generatedValues[0]->map( + function ( $v ) { + return [ $v ]; + }, + $generatorName + ); + } + + $result = $this->cartesianProduct( + $this->generatedValues[0], + $this->generatedValues[1], + $generatorName, + function ( $v1, $v2 ) { + return [ $v1, $v2 ]; + } + ); + + $valuesCount = count( $this->generatedValues ); + for ( $i = 2; $i < $valuesCount; $i++ ) { + $result = $this->cartesianProduct( + $result, + $this->generatedValues[$i], + $generatorName, + function ( array $args, $value ) { + $args[] = $value; + return $args; + } + ); + } + + return $result; + } + + private function cartesianProduct( + GeneratedValueOptions $v1, + GeneratedValueOptions $v2, + $generatorName, + callable $merge + ) { + $options = []; + foreach ( $v1 as $firstPart ) { + foreach ( $v2 as $secondPart ) { + $options[] = GeneratedValueSingle::fromValueAndInput( + $merge( $firstPart->unbox(), $secondPart->unbox() ), + $merge( $firstPart->input(), $secondPart->input() ), + $generatorName + ); + } + } + return new GeneratedValueOptions( $options ); + } + +} diff --git a/tests/phpunit/composer/ErisGenerators/CartesianProductTest.php b/tests/phpunit/composer/ErisGenerators/CartesianProductTest.php new file mode 100644 index 0000000..3bde892 --- /dev/null +++ b/tests/phpunit/composer/ErisGenerators/CartesianProductTest.php @@ -0,0 +1,161 @@ +<?php + +namespace Wikibase\Lexeme\Tests\ErisGenerators; + +use Eris\Facade; +use Eris\Generator\GeneratedValueOptions; +use Eris\Generator\GeneratedValueSingle; + +class CartesianProductTest extends \PHPUnit_Framework_TestCase { + + public function testCanHandleOneGeneratedValueOptions() { + $this->skipTestIfErisIsNotInstalled(); + + $opt1 = $this->createOptionsWithSingleValue( 1 ); + + /** @var GeneratedValueOptions $result */ + $result = CartesianProduct::create( $opt1 ) + ->map( + function ( $n1 ) { + return $n1; + } + ); + + $this->assertEquals( 1, $result->count() ); + $this->assertEquals( 1, $result->first()->unbox() ); + } + + public function testCanHandleTwoGeneratedValueOptions() { + $this->skipTestIfErisIsNotInstalled(); + + $opt1 = $this->createOptionsWithSingleValue( 1 ); + $opt2 = $this->createOptionsWithSingleValue( 2 ); + + /** @var GeneratedValueOptions $result */ + $result = CartesianProduct::create( $opt1, $opt2 ) + ->map( + function ( $n1, $n2 ) { + return [ $n1, $n2 ]; + } + ); + + $this->assertInstanceOf( GeneratedValueOptions::class, $result ); + $this->assertEquals( 1, $result->count() ); + $this->assertEquals( [ 1, 2 ], $result->first()->unbox() ); + } + + public function testCanHandleThreeGeneratedValueOptions() { + $this->skipTestIfErisIsNotInstalled(); + + $opt1 = $this->createOptionsWithSingleValue( 1 ); + $opt2 = $this->createOptionsWithSingleValue( 2 ); + $opt3 = $this->createOptionsWithSingleValue( 3 ); + + /** @var GeneratedValueOptions $result */ + $result = CartesianProduct::create( $opt1, $opt2, $opt3 ) + ->map( + function ( $n1, $n2, $n3 ) { + return [ $n1, $n2, $n3 ]; + } + ); + + $this->assertEquals( 1, $result->count() ); + $this->assertEquals( [ 1, 2, 3 ], $result->first()->unbox() ); + } + + public function testCanHandleGeneratedValueSingle() { + $this->skipTestIfErisIsNotInstalled(); + + $opt1 = GeneratedValueSingle::fromJustValue( 1 ); + $opt2 = GeneratedValueSingle::fromJustValue( 2 ); + + /** @var GeneratedValueOptions $result */ + $result = CartesianProduct::create( $opt1, $opt2 ) + ->map( + function ( $n1, $n2 ) { + return [ $n1, $n2 ]; + } + ); + + $this->assertInstanceOf( GeneratedValueOptions::class, $result ); + $this->assertEquals( 1, $result->count() ); + $this->assertEquals( [ 1, 2 ], $result->first()->unbox() ); + } + + public function testCanCombineValuesFromDifferentGenerators() { + $this->skipTestIfErisIsNotInstalled(); + + $opt1 = GeneratedValueSingle::fromJustValue( 1, 'generator a' ); + $opt2 = GeneratedValueSingle::fromJustValue( 2, 'generator b' ); + + /** @var GeneratedValueOptions $result */ + $result = CartesianProduct::create( $opt1, $opt2 ) + ->map( + function ( $n1, $n2 ) { + return [ $n1, $n2 ]; + } + ); + + $this->assertEquals( 1, $result->count() ); + $this->assertEquals( [ 1, 2 ], $result->first()->unbox() ); + } + + public function testProducesAllTheCombinations() { + $this->skipTestIfErisIsNotInstalled(); + + $opt1 = new GeneratedValueOptions( [ + GeneratedValueSingle::fromJustValue( 1 ), + GeneratedValueSingle::fromJustValue( 2 ), + GeneratedValueSingle::fromJustValue( 3 ), + ] ); + $opt2 = new GeneratedValueOptions( [ + GeneratedValueSingle::fromJustValue( 4 ), + GeneratedValueSingle::fromJustValue( 5 ), + GeneratedValueSingle::fromJustValue( 6 ), + ] ); + + /** @var GeneratedValueOptions $result */ + $resultingCalls = []; + $result = CartesianProduct::create( $opt1, $opt2 ) + ->map( + function ( $n1, $n2 ) use ( &$resultingCalls ) { + $resultingCalls[] = [ $n1, $n2 ]; + return [ $n1, $n2 ]; + } + ); + + $this->assertEquals( 9, $result->count() ); + $this->assertContains( [ 1,4 ], $resultingCalls ); + $this->assertContains( [ 1,5 ], $resultingCalls ); + $this->assertContains( [ 1,6 ], $resultingCalls ); + $this->assertContains( [ 2,4 ], $resultingCalls ); + $this->assertContains( [ 2,5 ], $resultingCalls ); + $this->assertContains( [ 2,6 ], $resultingCalls ); + $this->assertContains( [ 3,4 ], $resultingCalls ); + $this->assertContains( [ 3,5 ], $resultingCalls ); + $this->assertContains( [ 3,6 ], $resultingCalls ); + } + + /** + * @return GeneratedValueOptions + */ + private function createOptionsWithSingleValue( $value ) { + return new GeneratedValueOptions( [ + GeneratedValueSingle::fromJustValue( $value ) + ] ); + } + + protected function skipTestIfErisIsNotInstalled() { + if ( !self::erisIsInstalled() ) { + $this->markTestSkipped( 'Package `giorgiosironi/eris` is not installed. Skipping' ); + } + } + + /** + * @return bool + */ + private static function erisIsInstalled() { + return class_exists( Facade::class ); + } + +} diff --git a/tests/phpunit/composer/ErisGenerators/LexemeGenerator.php b/tests/phpunit/composer/ErisGenerators/LexemeGenerator.php index b58b2fa..0808a39 100644 --- a/tests/phpunit/composer/ErisGenerators/LexemeGenerator.php +++ b/tests/phpunit/composer/ErisGenerators/LexemeGenerator.php @@ -101,12 +101,17 @@ $shrunkFormSet = $this->formSetGenerator->shrink( GeneratedValueSingle::fromJustValue( new FormSet( $lexeme->getForms() ) ) ); + $shrunkLemmas = $this->lemmaListGenerator->shrink( + GeneratedValueSingle::fromJustValue( $lexeme->getLemmas() ) + ); - $result = $shrunkFormSet - ->map( function ( FormSet $formSet ) { + $result = CartesianProduct::create( + $shrunkLemmas, + $shrunkFormSet + )->map( function ( TermList $lemmas, FormSet $formSet ) { return new Lexeme( new LexemeId( 'L1' ), - null, + $lemmas, new ItemId( 'Q1' ), new ItemId( 'Q2' ), null, @@ -114,7 +119,7 @@ $formSet->toArray(), [] ); - }, + }, 'lexeme' ); diff --git a/tests/phpunit/composer/ErisGenerators/TermListGenerator.php b/tests/phpunit/composer/ErisGenerators/TermListGenerator.php index 5bde51e..c8aff9b 100644 --- a/tests/phpunit/composer/ErisGenerators/TermListGenerator.php +++ b/tests/phpunit/composer/ErisGenerators/TermListGenerator.php @@ -67,7 +67,37 @@ * @return GeneratedValueSingle<T>|GeneratedValueOptions<T> */ public function shrink( GeneratedValueSingle $element ) { - return $element; + /** @var TermList $termList */ + $termList = $element->unbox(); + + if ( $termList->count() === 0 ) { + return $element; + } elseif ( $termList->count() === 1 ) { + return GeneratedValueSingle::fromValueAndInput( + new TermList( [] ), + $element, + 'TermList' + ); + } else { + + $terms = iterator_to_array( $termList ); + + $splitIndex = (int)( count( $terms ) / 2 ); + $terms1 = array_slice( $terms, 0, $splitIndex ); + $terms2 = array_slice( $terms, $splitIndex ); + + $shrunk1 = new TermList( $terms1 ); + $shrunk2 = new TermList( $terms2 ); + + array_pop( $terms ); + $shrunkOneLess = new TermList( $terms ); + + return new Generator\GeneratedValueOptions( [ + GeneratedValueSingle::fromValueAndInput( $shrunk1, $element, 'TermList' ), + GeneratedValueSingle::fromValueAndInput( $shrunk2, $element, 'TermList' ), + GeneratedValueSingle::fromValueAndInput( $shrunkOneLess, $element, 'TermList' ), + ] ); + } } /** -- To view, visit https://gerrit.wikimedia.org/r/378414 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I5a3e09b2393fb2e4f4239efee90be3de6c79cfbb Gerrit-PatchSet: 5 Gerrit-Project: mediawiki/extensions/WikibaseLexeme Gerrit-Branch: master Gerrit-Owner: Aleksey Bekh-Ivanov (WMDE) <aleksey.bekh-iva...@wikimedia.de> Gerrit-Reviewer: Aleksey Bekh-Ivanov (WMDE) <aleksey.bekh-iva...@wikimedia.de> Gerrit-Reviewer: WMDE-leszek <leszek.mani...@wikimedia.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits