From: jenkins-bot Date: Mon, 24 Sep 2018 13:48:21 +0000 (+0000) Subject: Merge "RevisionStoreDbTestBase, remove redundant needsDB override" X-Git-Tag: 1.34.0-rc.0~4012 X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=commitdiff_plain;h=74d04edec385aa86ee01943b9a27475d79f74e78;hp=-c Merge "RevisionStoreDbTestBase, remove redundant needsDB override" --- 74d04edec385aa86ee01943b9a27475d79f74e78 diff --combined tests/phpunit/includes/Storage/RevisionStoreDbTestBase.php index 910cdc401a,979350232a..5497d98cdc --- a/tests/phpunit/includes/Storage/RevisionStoreDbTestBase.php +++ b/tests/phpunit/includes/Storage/RevisionStoreDbTestBase.php @@@ -17,7 -17,6 +17,7 @@@ use MediaWiki\Storage\RevisionRecord use MediaWiki\Storage\RevisionStore; use MediaWiki\Storage\SlotRecord; use MediaWiki\Storage\SqlBlobStore; +use MediaWiki\User\UserIdentityValue; use MediaWikiTestCase; use PHPUnit_Framework_MockObject_MockObject; use Revision; @@@ -65,10 -64,6 +65,6 @@@ abstract class RevisionStoreDbTestBase */ abstract protected function getMcrTablesToReset(); - public function needsDB() { - return true; - } - public function setUp() { parent::setUp(); $this->tablesUsed[] = 'archive'; @@@ -78,12 -73,15 +74,12 @@@ $this->tablesUsed += $this->getMcrTablesToReset(); - $this->setMwGlobals( - 'wgMultiContentRevisionSchemaMigrationStage', - $this->getMcrMigrationStage() - ); - - $this->setMwGlobals( - 'wgContentHandlerUseDB', - $this->getContentHandlerUseDB() - ); + $this->setMwGlobals( [ + 'wgMultiContentRevisionSchemaMigrationStage' => $this->getMcrMigrationStage(), + 'wgContentHandlerUseDB' => $this->getContentHandlerUseDB(), + 'wgCommentTableSchemaMigrationStage' => MIGRATION_OLD, + 'wgActorTableSchemaMigrationStage' => MIGRATION_OLD, + ] ); $this->overrideMwServices(); } @@@ -242,14 -240,14 +238,14 @@@ $this->assertSame( 0, $count ); } - private function assertLinkTargetsEqual( LinkTarget $l1, LinkTarget $l2 ) { + protected function assertLinkTargetsEqual( LinkTarget $l1, LinkTarget $l2 ) { $this->assertEquals( $l1->getDBkey(), $l2->getDBkey() ); $this->assertEquals( $l1->getNamespace(), $l2->getNamespace() ); $this->assertEquals( $l1->getFragment(), $l2->getFragment() ); $this->assertEquals( $l1->getInterwiki(), $l2->getInterwiki() ); } - private function assertRevisionRecordsEqual( RevisionRecord $r1, RevisionRecord $r2 ) { + protected function assertRevisionRecordsEqual( RevisionRecord $r1, RevisionRecord $r2 ) { $this->assertEquals( $r1->getPageAsLinkTarget()->getNamespace(), $r2->getPageAsLinkTarget()->getNamespace() @@@ -272,7 -270,7 +268,7 @@@ $this->assertEquals( $r1->getSha1(), $r2->getSha1() ); $this->assertEquals( $r1->getSize(), $r2->getSize() ); $this->assertEquals( $r1->getPageId(), $r2->getPageId() ); - $this->assertArrayEqualsIgnoringIntKeyOrder( $r1->getSlotRoles(), $r2->getSlotRoles() ); + $this->assertArrayEquals( $r1->getSlotRoles(), $r2->getSlotRoles() ); $this->assertEquals( $r1->getWikiId(), $r2->getWikiId() ); $this->assertEquals( $r1->isMinor(), $r2->isMinor() ); foreach ( $r1->getSlotRoles() as $role ) { @@@ -289,7 -287,7 +285,7 @@@ } } - private function assertSlotRecordsEqual( SlotRecord $s1, SlotRecord $s2 ) { + protected function assertSlotRecordsEqual( SlotRecord $s1, SlotRecord $s2 ) { $this->assertSame( $s1->getRole(), $s2->getRole() ); $this->assertSame( $s1->getModel(), $s2->getModel() ); $this->assertSame( $s1->getFormat(), $s2->getFormat() ); @@@ -301,7 -299,7 +297,7 @@@ $s1->hasAddress() ? $this->assertSame( $s1->hasAddress(), $s2->hasAddress() ) : null; } - private function assertRevisionCompleteness( RevisionRecord $r ) { + protected function assertRevisionCompleteness( RevisionRecord $r ) { $this->assertTrue( $r->hasSlot( 'main' ) ); $this->assertInstanceOf( SlotRecord::class, $r->getSlot( 'main' ) ); $this->assertInstanceOf( Content::class, $r->getContent( 'main' ) ); @@@ -311,7 -309,7 +307,7 @@@ } } - private function assertSlotCompleteness( RevisionRecord $r, SlotRecord $slot ) { + protected function assertSlotCompleteness( RevisionRecord $r, SlotRecord $slot ) { $this->assertTrue( $slot->hasAddress() ); $this->assertSame( $r->getId(), $slot->getRevision() ); @@@ -395,6 -393,9 +391,6 @@@ public function testInsertRevisionOn_successes( array $revDetails = [] ) { - // FIXME: fails under postgres - $this->markTestSkippedIfDbType( 'postgres' ); - $title = $this->getTestPageTitle(); $rev = $this->getRevisionRecordFromDetailsArray( $revDetails ); @@@ -615,7 -616,7 +611,7 @@@ $this->assertEquals( $user->getName(), $record->getUser()->getName() ); $this->assertEquals( $baseRev->getId(), $record->getParentId() ); - $this->assertArrayEqualsIgnoringIntKeyOrder( + $this->assertArrayEquals( $baseRev->getSlotRoles(), $record->getSlotRoles() ); @@@ -837,7 -838,7 +833,7 @@@ return (object)$fields; } - private function assertRevisionRecordMatchesRevision( + protected function assertRevisionRecordMatchesRevision( Revision $rev, RevisionRecord $record ) { @@@ -885,38 -886,6 +881,38 @@@ } } + /** + * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow + * @covers \MediaWiki\Storage\RevisionStore::getQueryInfo + */ + public function testNewRevisionFromRow_getQueryInfo() { + $page = $this->getTestPage(); + $text = __METHOD__ . 'a-ä'; + /** @var Revision $rev */ + $rev = $page->doEditContent( + new WikitextContent( $text ), + __METHOD__ . 'a' + )->value['revision']; + + $store = MediaWikiServices::getInstance()->getRevisionStore(); + $info = $store->getQueryInfo(); + $row = $this->db->selectRow( + $info['tables'], + $info['fields'], + [ 'rev_id' => $rev->getId() ], + __METHOD__, + [], + $info['joins'] + ); + $record = $store->newRevisionFromRow( + $row, + [], + $page->getTitle() + ); + $this->assertRevisionRecordMatchesRevision( $rev, $record ); + $this->assertSame( $text, $rev->getContent()->serialize() ); + } + /** * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow */ @@@ -950,7 -919,7 +946,7 @@@ /** @var Revision $rev */ $rev = $page->doEditContent( new WikitextContent( $text ), - __METHOD__. 'a' + __METHOD__ . 'a' )->value['revision']; $store = MediaWikiServices::getInstance()->getRevisionStore(); @@@ -990,9 -959,8 +986,9 @@@ /** * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromArchiveRow + * @covers \MediaWiki\Storage\RevisionStore::getArchiveQueryInfo */ - public function testNewRevisionFromArchiveRow() { + public function testNewRevisionFromArchiveRow_getArchiveQueryInfo() { $store = MediaWikiServices::getInstance()->getRevisionStore(); $title = Title::newFromText( __METHOD__ ); $text = __METHOD__ . '-bä'; @@@ -1049,89 -1017,10 +1045,89 @@@ $this->assertSame( $text, $record->getContent( 'main' )->serialize() ); } + /** + * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromArchiveRow + */ + public function testNewRevisionFromArchiveRow_no_user() { + $store = MediaWikiServices::getInstance()->getRevisionStore(); + + $row = (object)[ + 'ar_id' => '1', + 'ar_page_id' => '2', + 'ar_namespace' => '0', + 'ar_title' => 'Something', + 'ar_rev_id' => '2', + 'ar_text_id' => '47', + 'ar_timestamp' => '20180528192356', + 'ar_minor_edit' => '0', + 'ar_deleted' => '0', + 'ar_len' => '78', + 'ar_parent_id' => '0', + 'ar_sha1' => 'deadbeef', + 'ar_comment_text' => 'whatever', + 'ar_comment_data' => null, + 'ar_comment_cid' => null, + 'ar_user' => '0', + 'ar_user_text' => '', // this is the important bit + 'ar_actor' => null, + 'ar_content_format' => null, + 'ar_content_model' => null, + ]; + + \Wikimedia\suppressWarnings(); + $record = $store->newRevisionFromArchiveRow( $row ); + \Wikimedia\suppressWarnings( true ); + + $this->assertInstanceOf( RevisionRecord::class, $record ); + $this->assertInstanceOf( UserIdentityValue::class, $record->getUser() ); + $this->assertSame( 'Unknown user', $record->getUser()->getName() ); + } + + /** + * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow + */ + public function testNewRevisionFromRow_no_user() { + $store = MediaWikiServices::getInstance()->getRevisionStore(); + $title = Title::newFromText( __METHOD__ ); + + $row = (object)[ + 'rev_id' => '2', + 'rev_page' => '2', + 'page_namespace' => '0', + 'page_title' => $title->getText(), + 'rev_text_id' => '47', + 'rev_timestamp' => '20180528192356', + 'rev_minor_edit' => '0', + 'rev_deleted' => '0', + 'rev_len' => '78', + 'rev_parent_id' => '0', + 'rev_sha1' => 'deadbeef', + 'rev_comment_text' => 'whatever', + 'rev_comment_data' => null, + 'rev_comment_cid' => null, + 'rev_user' => '0', + 'rev_user_text' => '', // this is the important bit + 'rev_actor' => null, + 'rev_content_format' => null, + 'rev_content_model' => null, + ]; + + \Wikimedia\suppressWarnings(); + $record = $store->newRevisionFromRow( $row, 0, $title ); + \Wikimedia\suppressWarnings( true ); + + $this->assertNotNull( $record ); + $this->assertNotNull( $record->getUser() ); + $this->assertNotEmpty( $record->getUser()->getName() ); + } + /** * @covers \MediaWiki\Storage\RevisionStore::insertRevisionOn */ public function testInsertRevisionOn_archive() { + // This is a round trip test for deletion and undeletion of a + // revision row via the archive table. + $store = MediaWikiServices::getInstance()->getRevisionStore(); $title = Title::newFromText( __METHOD__ ); @@@ -1143,9 -1032,6 +1139,9 @@@ $orig = $origRev->getRevisionRecord(); $page->doDeleteArticle( __METHOD__ ); + // re-create page, so we can later load revisions for it + $page->doEditContent( new WikitextContent( 'Two' ), __METHOD__ ); + $db = wfGetDB( DB_MASTER ); $arQuery = $store->getArchiveQueryInfo(); $row = $db->selectRow( @@@ -1153,37 -1039,34 +1149,37 @@@ __METHOD__, [], $arQuery['joins'] ); - $record = $store->newRevisionFromArchiveRow( $row ); + $this->assertNotFalse( $row, 'query failed' ); + + $record = $store->newRevisionFromArchiveRow( + $row, + 0, + $title, + [ 'page_id' => $title->getArticleID() ] + ); $restored = $store->insertRevisionOn( $record, $db ); - $this->assertSame( $orig->getPageId(), $restored->getPageId() ); - $this->assertSame( $orig->getId(), $restored->getId() ); - $this->assertSame( $orig->getComment()->text, $restored->getComment()->text ); - $origMain = $orig->getSlot( 'main' ); - $restoredMain = $restored->getSlot( 'main' ); - $this->assertSame( - $origMain->getOrigin(), - $restoredMain->getOrigin() - ); + // is the new revision correct? + $this->assertRevisionCompleteness( $restored ); + $this->assertRevisionRecordsEqual( $record, $restored ); - if ( $origMain->hasContentId() ) { - $this->assertSame( - $origMain->getContentId(), - $restoredMain->getContentId() - ); - } + // does the new revision use the original slot? + $recMain = $record->getSlot( 'main' ); + $restMain = $restored->getSlot( 'main' ); + $this->assertSame( $recMain->getAddress(), $restMain->getAddress() ); + $this->assertSame( $recMain->getContentId(), $restMain->getContentId() ); + $this->assertSame( $recMain->getOrigin(), $restMain->getOrigin() ); + $this->assertSame( 'Foo', $restMain->getContent()->serialize() ); - // NOTE: we didn't restore the page row, so we can't use RevisionStore::getRevisionById - $this->assertSelect( - 'revision', - [ 'rev_id' ], - [ 'rev_id' => $orig->getId() ], - [ [ $orig->getId() ] ] - ); + // can we load it from the store? + $loaded = $store->getRevisionById( $restored->getId() ); + $this->assertNotNull( $loaded ); + $this->assertRevisionCompleteness( $loaded ); + $this->assertRevisionRecordsEqual( $restored, $loaded ); + + // can we find it directly in the database? + $this->assertRevisionExistsInDatabase( $restored ); } /** @@@ -1661,4 -1544,182 +1657,4 @@@ $this->testNewMutableRevisionFromArray( $array ); } - protected function getDefaultQueryFields( $returnTextIdField = true ) { - $fields = [ - 'rev_id', - 'rev_page', - 'rev_timestamp', - 'rev_minor_edit', - 'rev_deleted', - 'rev_len', - 'rev_parent_id', - 'rev_sha1', - ]; - if ( $returnTextIdField ) { - $fields[] = 'rev_text_id'; - } - return $fields; - } - - protected function getCommentQueryFields() { - return [ - 'rev_comment_text' => 'rev_comment', - 'rev_comment_data' => 'NULL', - 'rev_comment_cid' => 'NULL', - ]; - } - - protected function getActorQueryFields() { - return [ - 'rev_user' => 'rev_user', - 'rev_user_text' => 'rev_user_text', - 'rev_actor' => 'NULL', - ]; - } - - protected function getContentHandlerQueryFields() { - return [ - 'rev_content_format', - 'rev_content_model', - ]; - } - - abstract public function provideGetQueryInfo(); - - /** - * @dataProvider provideGetQueryInfo - * @covers \MediaWiki\Storage\RevisionStore::getQueryInfo - */ - public function testGetQueryInfo( $options, $expected ) { - $store = MediaWikiServices::getInstance()->getRevisionStore(); - - $queryInfo = $store->getQueryInfo( $options ); - - $this->assertArrayEqualsIgnoringIntKeyOrder( - $expected['tables'], - $queryInfo['tables'] - ); - $this->assertArrayEqualsIgnoringIntKeyOrder( - $expected['fields'], - $queryInfo['fields'] - ); - $this->assertArrayEqualsIgnoringIntKeyOrder( - $expected['joins'], - $queryInfo['joins'] - ); - } - - protected function getDefaultArchiveFields( $returnTextFields = true ) { - $fields = [ - 'ar_id', - 'ar_page_id', - 'ar_namespace', - 'ar_title', - 'ar_rev_id', - 'ar_timestamp', - 'ar_minor_edit', - 'ar_deleted', - 'ar_len', - 'ar_parent_id', - 'ar_sha1', - ]; - if ( $returnTextFields ) { - $fields[] = 'ar_text_id'; - } - return $fields; - } - - abstract public function provideGetArchiveQueryInfo(); - - /** - * @dataProvider provideGetArchiveQueryInfo - * @covers \MediaWiki\Storage\RevisionStore::getArchiveQueryInfo - */ - public function testGetArchiveQueryInfo( $expected ) { - $store = MediaWikiServices::getInstance()->getRevisionStore(); - - $archiveQueryInfo = $store->getArchiveQueryInfo(); - - $this->assertArrayEqualsIgnoringIntKeyOrder( - $expected['tables'], - $archiveQueryInfo['tables'] - ); - - $this->assertArrayEqualsIgnoringIntKeyOrder( - $expected['fields'], - $archiveQueryInfo['fields'] - ); - - $this->assertArrayEqualsIgnoringIntKeyOrder( - $expected['joins'], - $archiveQueryInfo['joins'] - ); - } - - abstract public function provideGetSlotsQueryInfo(); - - /** - * @dataProvider provideGetSlotsQueryInfo - * @covers \MediaWiki\Storage\RevisionStore::getSlotsQueryInfo - */ - public function testGetSlotsQueryInfo( $options, $expected ) { - $store = MediaWikiServices::getInstance()->getRevisionStore(); - - $archiveQueryInfo = $store->getSlotsQueryInfo( $options ); - - $this->assertArrayEqualsIgnoringIntKeyOrder( - $expected['tables'], - $archiveQueryInfo['tables'] - ); - - $this->assertArrayEqualsIgnoringIntKeyOrder( - $expected['fields'], - $archiveQueryInfo['fields'] - ); - - $this->assertArrayEqualsIgnoringIntKeyOrder( - $expected['joins'], - $archiveQueryInfo['joins'] - ); - } - - /** - * Assert that the two arrays passed are equal, ignoring the order of the values that integer - * keys. - * - * Note: Failures of this assertion can be slightly confusing as the arrays are actually - * split into a string key array and an int key array before assertions occur. - * - * @param array $expected - * @param array $actual - */ - private function assertArrayEqualsIgnoringIntKeyOrder( array $expected, array $actual ) { - $this->objectAssociativeSort( $expected ); - $this->objectAssociativeSort( $actual ); - - // Separate the int key values from the string key values so that assertion failures are - // easier to understand. - $expectedIntKeyValues = []; - $actualIntKeyValues = []; - - // Remove all int keys and re add them at the end after sorting by value - // This will result in all int keys being in the same order with same ints at the end of - // the array - foreach ( $expected as $key => $value ) { - if ( is_int( $key ) ) { - unset( $expected[$key] ); - $expectedIntKeyValues[] = $value; - } - } - foreach ( $actual as $key => $value ) { - if ( is_int( $key ) ) { - unset( $actual[$key] ); - $actualIntKeyValues[] = $value; - } - } - - $this->assertArrayEquals( $expected, $actual, false, true ); - $this->assertArrayEquals( $expectedIntKeyValues, $actualIntKeyValues, false, true ); - } - }