X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=tests%2Fphpunit%2Fincludes%2FRevisionTest.php;h=ca8ed2bcc13748ec5b56bc5252c4d26828d6f454;hb=3cfa071542f56eabcf7ea143f70a2376f6e9a47e;hp=ef4d127d853cd8672cda5c7ad0bda605eb3a4004;hpb=e994e89e76c286c80dd9ad1bd3b73bcebfe9017b;p=lhc%2Fweb%2Fwiklou.git diff --git a/tests/phpunit/includes/RevisionTest.php b/tests/phpunit/includes/RevisionTest.php index ef4d127d85..ca8ed2bcc1 100644 --- a/tests/phpunit/includes/RevisionTest.php +++ b/tests/phpunit/includes/RevisionTest.php @@ -1,62 +1,13 @@ setMwGlobals( [ - 'wgContLang' => Language::factory( 'en' ), - 'wgLanguageCode' => 'en', - 'wgLegacyEncoding' => false, - 'wgCompressRevisions' => false, - - 'wgContentHandlerTextFallback' => 'ignore', - ] ); - - $this->mergeMwGlobalArrayValue( - 'wgExtraNamespaces', - [ - 12312 => 'Dummy', - 12313 => 'Dummy_talk', - ] - ); - - $this->mergeMwGlobalArrayValue( - 'wgNamespaceContentModels', - [ - 12312 => 'testing', - ] - ); - - $this->mergeMwGlobalArrayValue( - 'wgContentHandlers', - [ - 'testing' => 'DummyContentHandlerForTesting', - 'RevisionTestModifyableContent' => 'RevisionTestModifyableContentHandler', - ] - ); - - MWNamespace::clearCaches(); - // Reset namespace cache - $wgContLang->resetNamespaces(); - } - - protected function tearDown() { - global $wgContLang; - - MWNamespace::clearCaches(); - // Reset namespace cache - $wgContLang->resetNamespaces(); - - parent::tearDown(); - } - public function provideConstructFromArray() { yield 'with text' => [ [ @@ -73,8 +24,10 @@ class RevisionTest extends MediaWikiTestCase { /** * @dataProvider provideConstructFromArray + * @covers Revision::__construct + * @covers Revision::constructFromRowArray */ - public function testConstructFromArray( $rowArray ) { + public function testConstructFromArray( array $rowArray ) { $rev = new Revision( $rowArray ); $this->assertNotNull( $rev->getContent(), 'no content object available' ); $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContent()->getModel() ); @@ -106,6 +59,8 @@ class RevisionTest extends MediaWikiTestCase { /** * @dataProvider provideConstructFromArrayThrowsExceptions + * @covers Revision::__construct + * @covers Revision::constructFromRowArray */ public function testConstructFromArrayThrowsExceptions( $rowArray, Exception $expectedException ) { $this->setExpectedException( @@ -116,6 +71,78 @@ class RevisionTest extends MediaWikiTestCase { new Revision( $rowArray ); } + public function provideConstructFromRow() { + yield 'Full construction' => [ + [ + 'rev_id' => '2', + 'rev_page' => '1', + 'rev_text_id' => '2', + 'rev_timestamp' => '20171017114835', + 'rev_user_text' => '127.0.0.1', + 'rev_user' => '0', + 'rev_minor_edit' => '0', + 'rev_deleted' => '0', + 'rev_len' => '46', + 'rev_parent_id' => '1', + 'rev_sha1' => 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z', + 'rev_comment_text' => 'Goat Comment!', + 'rev_comment_data' => null, + 'rev_comment_cid' => null, + 'rev_content_format' => 'GOATFORMAT', + 'rev_content_model' => 'GOATMODEL', + ], + function ( RevisionTest $testCase, Revision $rev ) { + $testCase->assertSame( 2, $rev->getId() ); + $testCase->assertSame( 1, $rev->getPage() ); + $testCase->assertSame( 2, $rev->getTextId() ); + $testCase->assertSame( '20171017114835', $rev->getTimestamp() ); + $testCase->assertSame( '127.0.0.1', $rev->getUserText() ); + $testCase->assertSame( 0, $rev->getUser() ); + $testCase->assertSame( false, $rev->isMinor() ); + $testCase->assertSame( false, $rev->isDeleted( Revision::DELETED_TEXT ) ); + $testCase->assertSame( 46, $rev->getSize() ); + $testCase->assertSame( 1, $rev->getParentId() ); + $testCase->assertSame( 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z', $rev->getSha1() ); + $testCase->assertSame( 'Goat Comment!', $rev->getComment() ); + $testCase->assertSame( 'GOATFORMAT', $rev->getContentFormat() ); + $testCase->assertSame( 'GOATMODEL', $rev->getContentModel() ); + } + ]; + yield 'null fields' => [ + [ + 'rev_id' => '2', + 'rev_page' => '1', + 'rev_text_id' => '2', + 'rev_timestamp' => '20171017114835', + 'rev_user_text' => '127.0.0.1', + 'rev_user' => '0', + 'rev_minor_edit' => '0', + 'rev_deleted' => '0', + 'rev_comment_text' => 'Goat Comment!', + 'rev_comment_data' => null, + 'rev_comment_cid' => null, + ], + function ( RevisionTest $testCase, Revision $rev ) { + $testCase->assertNull( $rev->getSize() ); + $testCase->assertNull( $rev->getParentId() ); + $testCase->assertNull( $rev->getSha1() ); + $testCase->assertSame( 'text/x-wiki', $rev->getContentFormat() ); + $testCase->assertSame( 'wikitext', $rev->getContentModel() ); + } + ]; + } + + /** + * @dataProvider provideConstructFromRow + * @covers Revision::__construct + * @covers Revision::constructFromDbRowObject + */ + public function testConstructFromRow( array $arrayData, $assertions ) { + $row = (object)$arrayData; + $rev = new Revision( $row ); + $assertions( $this, $rev ); + } + public function provideGetRevisionText() { yield 'Generic test' => [ 'This is a goat of revision text.', @@ -126,6 +153,87 @@ class RevisionTest extends MediaWikiTestCase { ]; } + public function provideGetId() { + yield [ + [], + null + ]; + yield [ + [ 'id' => 998 ], + 998 + ]; + } + + /** + * @dataProvider provideGetId + * @covers Revision::getId + */ + public function testGetId( $rowArray, $expectedId ) { + $rev = new Revision( $rowArray ); + $this->assertEquals( $expectedId, $rev->getId() ); + } + + public function provideSetId() { + yield [ '123', 123 ]; + yield [ 456, 456 ]; + } + + /** + * @dataProvider provideSetId + * @covers Revision::setId + */ + public function testSetId( $input, $expected ) { + $rev = new Revision( [] ); + $rev->setId( $input ); + $this->assertSame( $expected, $rev->getId() ); + } + + public function provideSetUserIdAndName() { + yield [ '123', 123, 'GOaT' ]; + yield [ 456, 456, 'GOaT' ]; + } + + /** + * @dataProvider provideSetUserIdAndName + * @covers Revision::setUserIdAndName + */ + public function testSetUserIdAndName( $inputId, $expectedId, $name ) { + $rev = new Revision( [] ); + $rev->setUserIdAndName( $inputId, $name ); + $this->assertSame( $expectedId, $rev->getUser( Revision::RAW ) ); + $this->assertEquals( $name, $rev->getUserText( Revision::RAW ) ); + } + + public function provideGetTextId() { + yield [ [], null ]; + yield [ [ 'text_id' => '123' ], 123 ]; + yield [ [ 'text_id' => 456 ], 456 ]; + } + + /** + * @dataProvider provideGetTextId + * @covers Revision::getTextId() + */ + public function testGetTextId( $rowArray, $expected ) { + $rev = new Revision( $rowArray ); + $this->assertSame( $expected, $rev->getTextId() ); + } + + public function provideGetParentId() { + yield [ [], null ]; + yield [ [ 'parent_id' => '123' ], 123 ]; + yield [ [ 'parent_id' => 456 ], 456 ]; + } + + /** + * @dataProvider provideGetParentId + * @covers Revision::getParentId() + */ + public function testGetParentId( $rowArray, $expected ) { + $rev = new Revision( $rowArray ); + $this->assertSame( $expected, $rev->getParentId() ); + } + /** * @covers Revision::getRevisionText * @dataProvider provideGetRevisionText @@ -179,11 +287,16 @@ class RevisionTest extends MediaWikiTestCase { * @dataProvider provideGetRevisionTextWithLegacyEncoding */ public function testGetRevisionWithLegacyEncoding( $expected, $encoding, $rowData ) { - $GLOBALS['wgLegacyEncoding'] = $encoding; + $this->setMwGlobals( 'wgLegacyEncoding', $encoding ); $this->testGetRevisionText( $expected, $rowData ); } public function provideGetRevisionTextWithGzipAndLegacyEncoding() { + /** + * WARNING! + * Do not set the external flag! + * Otherwise, getRevisionText will hit the live database (if ExternalStore is enabled)! + */ yield 'Utf8NativeGzip' => [ "Wiki est l'\xc3\xa9cole superieur !", 'iso-8859-1', @@ -208,7 +321,7 @@ class RevisionTest extends MediaWikiTestCase { */ public function testGetRevisionWithGzipAndLegacyEncoding( $expected, $encoding, $rowData ) { $this->checkPHPExtension( 'zlib' ); - $GLOBALS['wgLegacyEncoding'] = $encoding; + $this->setMwGlobals( 'wgLegacyEncoding', $encoding ); $this->testGetRevisionText( $expected, $rowData ); } @@ -249,230 +362,174 @@ class RevisionTest extends MediaWikiTestCase { Revision::getRevisionText( $row ), "getRevisionText" ); } - /** - * @param string $text - * @param string $title - * @param string $model - * @param string $format - * - * @return Revision - */ - private function newTestRevision( $text, $title = "Test", - $model = CONTENT_MODEL_WIKITEXT, $format = null - ) { - if ( is_string( $title ) ) { - $title = Title::newFromText( $title ); - } - - $content = ContentHandler::makeContent( $text, $title, $model, $format ); - - $rev = new Revision( - [ - 'id' => 42, - 'page' => 23, - 'title' => $title, - - 'content' => $content, - 'length' => $content->getSize(), - 'comment' => "testing", - 'minor_edit' => false, - - 'content_format' => $format, - ] - ); - - return $rev; - } - - public function provideGetContentModel() { - // NOTE: we expect the help namespace to always contain wikitext - return [ - [ 'hello world', 'Help:Hello', null, null, CONTENT_MODEL_WIKITEXT ], - [ 'hello world', 'User:hello/there.css', null, null, CONTENT_MODEL_CSS ], - [ serialize( 'hello world' ), 'Dummy:Hello', null, null, "testing" ], - ]; + public function provideFetchFromConds() { + yield [ 0, [] ]; + yield [ Revision::READ_LOCKING, [ 'FOR UPDATE' ] ]; } /** - * @group Database - * @dataProvider provideGetContentModel - * @covers Revision::getContentModel + * @dataProvider provideFetchFromConds + * @covers Revision::fetchFromConds */ - public function testGetContentModel( $text, $title, $model, $format, $expectedModel ) { - $rev = $this->newTestRevision( $text, $title, $model, $format ); - - $this->assertEquals( $expectedModel, $rev->getContentModel() ); + public function testFetchFromConds( $flags, array $options ) { + $conditions = [ 'conditionsArray' ]; + + $db = $this->getMock( IDatabase::class ); + $db->expects( $this->once() ) + ->method( 'selectRow' ) + ->with( + $this->equalTo( [ 'revision', 'page', 'user' ] ), + // We don't really care about the fields are they come from the selectField methods + $this->isType( 'array' ), + $this->equalTo( $conditions ), + // Method name + $this->equalTo( 'Revision::fetchFromConds' ), + $this->equalTo( $options ), + // We don't really care about the join conds are they come from the joinCond methods + $this->isType( 'array' ) + ) + ->willReturn( 'RETURNVALUE' ); + + $wrapper = TestingAccessWrapper::newFromClass( Revision::class ); + $result = $wrapper->fetchFromConds( $db, $conditions, $flags ); + + $this->assertEquals( 'RETURNVALUE', $result ); } - public function provideGetContentFormat() { - // NOTE: we expect the help namespace to always contain wikitext - return [ - [ 'hello world', 'Help:Hello', null, null, CONTENT_FORMAT_WIKITEXT ], - [ 'hello world', 'Help:Hello', CONTENT_MODEL_CSS, null, CONTENT_FORMAT_CSS ], - [ 'hello world', 'User:hello/there.css', null, null, CONTENT_FORMAT_CSS ], - [ serialize( 'hello world' ), 'Dummy:Hello', null, null, "testing" ], + public function provideDecompressRevisionText() { + yield '(no legacy encoding), false in false out' => [ false, false, [], false ]; + yield '(no legacy encoding), empty in empty out' => [ false, '', [], '' ]; + yield '(no legacy encoding), empty in empty out' => [ false, 'A', [], 'A' ]; + yield '(no legacy encoding), string in with gzip flag returns string' => [ + // gzip string below generated with gzdeflate( 'AAAABBAAA' ) + false, "sttttr\002\022\000", [ 'gzip' ], 'AAAABBAAA', + ]; + yield '(no legacy encoding), string in with object flag returns false' => [ + // gzip string below generated with serialize( 'JOJO' ) + false, "s:4:\"JOJO\";", [ 'object' ], false, + ]; + yield '(no legacy encoding), serialized object in with object flag returns string' => [ + false, + // Using a TitleValue object as it has a getText method (which is needed) + serialize( new TitleValue( 0, 'HHJJDDFF' ) ), + [ 'object' ], + 'HHJJDDFF', + ]; + yield '(no legacy encoding), serialized object in with object & gzip flag returns string' => [ + false, + // Using a TitleValue object as it has a getText method (which is needed) + gzdeflate( serialize( new TitleValue( 0, '8219JJJ840' ) ) ), + [ 'object', 'gzip' ], + '8219JJJ840', + ]; + yield '(ISO-8859-1 encoding), string in string out' => [ + 'ISO-8859-1', + iconv( 'utf8', 'ISO-8859-1', "1®Àþ1" ), + [], + '1®Àþ1', + ]; + yield '(ISO-8859-1 encoding), serialized object in with gzip flags returns string' => [ + 'ISO-8859-1', + gzdeflate( iconv( 'utf8', 'ISO-8859-1', "4®Àþ4" ) ), + [ 'gzip' ], + '4®Àþ4', + ]; + yield '(ISO-8859-1 encoding), serialized object in with object flags returns string' => [ + 'ISO-8859-1', + serialize( new TitleValue( 0, iconv( 'utf8', 'ISO-8859-1', "3®Àþ3" ) ) ), + [ 'object' ], + '3®Àþ3', + ]; + yield '(ISO-8859-1 encoding), serialized object in with object & gzip flags returns string' => [ + 'ISO-8859-1', + gzdeflate( serialize( new TitleValue( 0, iconv( 'utf8', 'ISO-8859-1', "2®Àþ2" ) ) ) ), + [ 'gzip', 'object' ], + '2®Àþ2', ]; } /** - * @group Database - * @dataProvider provideGetContentFormat - * @covers Revision::getContentFormat + * @dataProvider provideDecompressRevisionText + * @covers Revision::decompressRevisionText + * + * @param bool $legacyEncoding + * @param mixed $text + * @param array $flags + * @param mixed $expected */ - public function testGetContentFormat( $text, $title, $model, $format, $expectedFormat ) { - $rev = $this->newTestRevision( $text, $title, $model, $format ); - - $this->assertEquals( $expectedFormat, $rev->getContentFormat() ); - } - - public function provideGetContentHandler() { - // NOTE: we expect the help namespace to always contain wikitext - return [ - [ 'hello world', 'Help:Hello', null, null, 'WikitextContentHandler' ], - [ 'hello world', 'User:hello/there.css', null, null, 'CssContentHandler' ], - [ serialize( 'hello world' ), 'Dummy:Hello', null, null, 'DummyContentHandlerForTesting' ], - ]; + public function testDecompressRevisionText( $legacyEncoding, $text, $flags, $expected ) { + $this->setMwGlobals( 'wgLegacyEncoding', $legacyEncoding ); + $this->setMwGlobals( 'wgLanguageCode', 'en' ); + $this->assertSame( + $expected, + Revision::decompressRevisionText( $text, $flags ) + ); } /** - * @group Database - * @dataProvider provideGetContentHandler - * @covers Revision::getContentHandler + * @covers Revision::getRevisionText */ - public function testGetContentHandler( $text, $title, $model, $format, $expectedClass ) { - $rev = $this->newTestRevision( $text, $title, $model, $format ); - - $this->assertEquals( $expectedClass, get_class( $rev->getContentHandler() ) ); + public function testGetRevisionText_returnsFalseWhenNoTextField() { + $this->assertFalse( Revision::getRevisionText( new stdClass() ) ); } - public function provideGetContent() { - // NOTE: we expect the help namespace to always contain wikitext - return [ - [ 'hello world', 'Help:Hello', null, null, Revision::FOR_PUBLIC, 'hello world' ], - [ - serialize( 'hello world' ), - 'Hello', - "testing", - null, - Revision::FOR_PUBLIC, - serialize( 'hello world' ) + public function provideTestGetRevisionText_returnsDecompressedTextFieldWhenNotExternal() { + yield 'Just text' => [ + (object)[ 'old_text' => 'SomeText' ], + 'old_', + 'SomeText' + ]; + // gzip string below generated with gzdeflate( 'AAAABBAAA' ) + yield 'gzip text' => [ + (object)[ + 'old_text' => "sttttr\002\022\000", + 'old_flags' => 'gzip' ], - [ - serialize( 'hello world' ), - 'Dummy:Hello', - null, - null, - Revision::FOR_PUBLIC, - serialize( 'hello world' ) + 'old_', + 'AAAABBAAA' + ]; + yield 'gzip text and different prefix' => [ + (object)[ + 'jojo_text' => "sttttr\002\022\000", + 'jojo_flags' => 'gzip' ], + 'jojo_', + 'AAAABBAAA' ]; } /** - * @group Database - * @dataProvider provideGetContent - * @covers Revision::getContent + * @dataProvider provideTestGetRevisionText_returnsDecompressedTextFieldWhenNotExternal + * @covers Revision::getRevisionText */ - public function testGetContent( $text, $title, $model, $format, - $audience, $expectedSerialization + public function testGetRevisionText_returnsDecompressedTextFieldWhenNotExternal( + $row, + $prefix, + $expected ) { - $rev = $this->newTestRevision( $text, $title, $model, $format ); - $content = $rev->getContent( $audience ); - - $this->assertEquals( - $expectedSerialization, - is_null( $content ) ? null : $content->serialize( $format ) - ); - } - - public function provideGetSize() { - return [ - [ "hello world.", CONTENT_MODEL_WIKITEXT, 12 ], - [ serialize( "hello world." ), "testing", 12 ], - ]; - } - - /** - * @covers Revision::getSize - * @group Database - * @dataProvider provideGetSize - */ - public function testGetSize( $text, $model, $expected_size ) { - $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSize', $model ); - $this->assertEquals( $expected_size, $rev->getSize() ); - } - - public function provideGetSha1() { - return [ - [ "hello world.", CONTENT_MODEL_WIKITEXT, Revision::base36Sha1( "hello world." ) ], - [ - serialize( "hello world." ), - "testing", - Revision::base36Sha1( serialize( "hello world." ) ) - ], - ]; + $this->assertSame( $expected, Revision::getRevisionText( $row, $prefix ) ); } - /** - * @covers Revision::getSha1 - * @group Database - * @dataProvider provideGetSha1 - */ - public function testGetSha1( $text, $model, $expected_hash ) { - $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSha1', $model ); - $this->assertEquals( $expected_hash, $rev->getSha1() ); + public function provideTestGetRevisionText_external_returnsFalseWhenNotEnoughUrlParts() { + yield 'Just some text' => [ 'someNonUrlText' ]; + yield 'No second URL part' => [ 'someProtocol://' ]; } /** - * Tests whether $rev->getContent() returns a clone when needed. - * - * @group Database - * @covers Revision::getContent + * @dataProvider provideTestGetRevisionText_external_returnsFalseWhenNotEnoughUrlParts + * @covers Revision::getRevisionText */ - public function testGetContentClone() { - $content = new RevisionTestModifyableContent( "foo" ); - - $rev = new Revision( - [ - 'id' => 42, - 'page' => 23, - 'title' => Title::newFromText( "testGetContentClone_dummy" ), - - 'content' => $content, - 'length' => $content->getSize(), - 'comment' => "testing", - 'minor_edit' => false, - ] + public function testGetRevisionText_external_returnsFalseWhenNotEnoughUrlParts( + $text + ) { + $this->assertFalse( + Revision::getRevisionText( + (object)[ + 'old_text' => $text, + 'old_flags' => 'external', + ] + ) ); - - /** @var RevisionTestModifyableContent $content */ - $content = $rev->getContent( Revision::RAW ); - $content->setText( "bar" ); - - /** @var RevisionTestModifyableContent $content2 */ - $content2 = $rev->getContent( Revision::RAW ); - // content is mutable, expect clone - $this->assertNotSame( $content, $content2, "expected a clone" ); - // clone should contain the original text - $this->assertEquals( "foo", $content2->getText() ); - - $content2->setText( "bla bla" ); - // clones should be independent - $this->assertEquals( "bar", $content->getText() ); } - /** - * Tests whether $rev->getContent() returns the same object repeatedly if appropriate. - * - * @group Database - * @covers Revision::getContent - */ - public function testGetContentUncloned() { - $rev = $this->newTestRevision( "hello", "testGetContentUncloned_dummy", CONTENT_MODEL_WIKITEXT ); - $content = $rev->getContent( Revision::RAW ); - $content2 = $rev->getContent( Revision::RAW ); - - // for immutable content like wikitext, this should be the same object - $this->assertSame( $content, $content2 ); - } }