X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=tests%2Fphpunit%2Fincludes%2FStorage%2FRevisionStoreDbTestBase.php;h=ad1e013fca61ec24467f76295bc41558b8b066bd;hb=2f5d88819799f077f4d3a3288dad104141692f20;hp=7ea0627e7b04efeba39ca0ed8186686f89e471b8;hpb=94879e96c8f203c9f2132bc2860738a88305ee47;p=lhc%2Fweb%2Fwiklou.git diff --git a/tests/phpunit/includes/Storage/RevisionStoreDbTestBase.php b/tests/phpunit/includes/Storage/RevisionStoreDbTestBase.php index 7ea0627e7b..910cdc401a 100644 --- a/tests/phpunit/includes/Storage/RevisionStoreDbTestBase.php +++ b/tests/phpunit/includes/Storage/RevisionStoreDbTestBase.php @@ -3,6 +3,7 @@ namespace MediaWiki\Tests\Storage; use CommentStoreComment; +use Content; use Exception; use HashBagOStuff; use InvalidArgumentException; @@ -16,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; @@ -36,6 +38,16 @@ use WikitextContent; */ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { + /** + * @var Title + */ + private $testPageTitle; + + /** + * @var WikiPage + */ + private $testPage; + /** * @return int */ @@ -66,15 +78,12 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $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(); } @@ -83,6 +92,46 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { // Blank out. This would fail with a modified schema, and we don't need it. } + /** + * @return Title + */ + protected function getTestPageTitle() { + if ( $this->testPageTitle ) { + return $this->testPageTitle; + } + + $this->testPageTitle = Title::newFromText( 'UTPage-' . __CLASS__ ); + return $this->testPageTitle; + } + /** + * @return WikiPage + */ + protected function getTestPage() { + if ( $this->testPage ) { + return $this->testPage; + } + + $title = $this->getTestPageTitle(); + $this->testPage = WikiPage::factory( $title ); + + if ( !$this->testPage->exists() ) { + // Make sure we don't write to the live db. + $this->ensureMockDatabaseConnection( wfGetDB( DB_MASTER ) ); + + $user = static::getTestSysop()->getUser(); + + $this->testPage->doEditContent( + new WikitextContent( 'UTContent-' . __CLASS__ ), + 'UTPageSummary-' . __CLASS__, + EDIT_NEW | EDIT_SUPPRESS_RC, + false, + $user + ); + } + + return $this->testPage; + } + /** * @return LoadBalancer|PHPUnit_Framework_MockObject_MockObject */ @@ -193,25 +242,37 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $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() + ); + + $this->assertEquals( + $r1->getPageAsLinkTarget()->getText(), + $r2->getPageAsLinkTarget()->getText() + ); + + if ( $r1->getParentId() ) { + $this->assertEquals( $r1->getParentId(), $r2->getParentId() ); + } + $this->assertEquals( $r1->getUser()->getName(), $r2->getUser()->getName() ); $this->assertEquals( $r1->getUser()->getId(), $r2->getUser()->getId() ); $this->assertEquals( $r1->getComment(), $r2->getComment() ); - $this->assertEquals( $r1->getPageAsLinkTarget(), $r2->getPageAsLinkTarget() ); $this->assertEquals( $r1->getTimestamp(), $r2->getTimestamp() ); $this->assertEquals( $r1->getVisibility(), $r2->getVisibility() ); $this->assertEquals( $r1->getSha1(), $r2->getSha1() ); - $this->assertEquals( $r1->getParentId(), $r2->getParentId() ); $this->assertEquals( $r1->getSize(), $r2->getSize() ); $this->assertEquals( $r1->getPageId(), $r2->getPageId() ); - $this->assertEquals( $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 ) { @@ -228,7 +289,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { } } - 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() ); @@ -240,15 +301,21 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $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' ) ); + foreach ( $r->getSlotRoles() as $role ) { $this->assertSlotCompleteness( $r, $r->getSlot( $role ) ); } } - private function assertSlotCompleteness( RevisionRecord $r, SlotRecord $slot ) { + protected function assertSlotCompleteness( RevisionRecord $r, SlotRecord $slot ) { $this->assertTrue( $slot->hasAddress() ); $this->assertSame( $r->getId(), $slot->getRevision() ); + + $this->assertInstanceOf( Content::class, $slot->getContent() ); } /** @@ -256,21 +323,20 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * * @return RevisionRecord */ - private function getRevisionRecordFromDetailsArray( $title, $details = [] ) { + private function getRevisionRecordFromDetailsArray( $details = [] ) { // Convert some values that can't be provided by dataProviders - $page = WikiPage::factory( $title ); if ( isset( $details['user'] ) && $details['user'] === true ) { $details['user'] = $this->getTestUser()->getUser(); } if ( isset( $details['page'] ) && $details['page'] === true ) { - $details['page'] = $page->getId(); + $details['page'] = $this->getTestPage()->getId(); } if ( isset( $details['parent'] ) && $details['parent'] === true ) { - $details['parent'] = $page->getLatest(); + $details['parent'] = $this->getTestPage()->getLatest(); } // Create the RevisionRecord with any available data - $rev = new MutableRevisionRecord( $title ); + $rev = new MutableRevisionRecord( $this->getTestPageTitle() ); isset( $details['slot'] ) ? $rev->setSlot( $details['slot'] ) : null; isset( $details['parent'] ) ? $rev->setParentId( $details['parent'] ) : null; isset( $details['page'] ) ? $rev->setPageId( $details['page'] ) : null; @@ -283,22 +349,26 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { isset( $details['visibility'] ) ? $rev->setVisibility( $details['visibility'] ) : null; isset( $details['id'] ) ? $rev->setId( $details['id'] ) : null; + if ( isset( $details['content'] ) ) { + foreach ( $details['content'] as $role => $content ) { + $rev->setContent( $role, $content ); + } + } + return $rev; } public function provideInsertRevisionOn_successes() { yield 'Bare minimum revision insertion' => [ - Title::newFromText( 'UTPage' ), [ 'slot' => SlotRecord::newUnsaved( 'main', new WikitextContent( 'Chicken' ) ), - 'parent' => true, + 'page' => true, 'comment' => $this->getRandomCommentStoreComment(), 'timestamp' => '20171117010101', 'user' => true, ], ]; yield 'Detailed revision insertion' => [ - Title::newFromText( 'UTPage' ), [ 'slot' => SlotRecord::newUnsaved( 'main', new WikitextContent( 'Chicken' ) ), 'parent' => true, @@ -312,7 +382,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { ]; } - private function getRandomCommentStoreComment() { + protected function getRandomCommentStoreComment() { return CommentStoreComment::newUnsavedComment( __METHOD__ . '.' . rand( 0, 1000 ) ); } @@ -323,25 +393,53 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::insertContentRowOn */ public function testInsertRevisionOn_successes( - Title $title, array $revDetails = [] ) { - $this->getExistingTestPage( $title ); - $rev = $this->getRevisionRecordFromDetailsArray( $title, $revDetails ); + $title = $this->getTestPageTitle(); + $rev = $this->getRevisionRecordFromDetailsArray( $revDetails ); $this->overrideMwServices(); $store = MediaWikiServices::getInstance()->getRevisionStore(); $return = $store->insertRevisionOn( $rev, wfGetDB( DB_MASTER ) ); + // is the new revision correct? + $this->assertRevisionCompleteness( $return ); $this->assertLinkTargetsEqual( $title, $return->getPageAsLinkTarget() ); $this->assertRevisionRecordsEqual( $rev, $return ); - $this->assertRevisionCompleteness( $return ); + + // can we load it from the store? + $loaded = $store->getRevisionById( $return->getId() ); + $this->assertRevisionCompleteness( $loaded ); + $this->assertRevisionRecordsEqual( $return, $loaded ); + + // can we find it directly in the database? $this->assertRevisionExistsInDatabase( $return ); } protected function assertRevisionExistsInDatabase( RevisionRecord $rev ) { + $row = $this->revisionToRow( new Revision( $rev ), [] ); + + // unset nulled fields + unset( $row->rev_content_model ); + unset( $row->rev_content_format ); + + // unset fake fields + unset( $row->rev_comment_text ); + unset( $row->rev_comment_data ); + unset( $row->rev_comment_cid ); + unset( $row->rev_comment_id ); + + $store = MediaWikiServices::getInstance()->getRevisionStore(); + $queryInfo = $store->getQueryInfo( [ 'user' ] ); + + $row = get_object_vars( $row ); $this->assertSelect( - 'revision', [ 'count(*)' ], [ 'rev_id' => $rev->getId() ], [ [ '1' ] ] + $queryInfo['tables'], + array_keys( $row ), + [ 'rev_id' => $rev->getId() ], + [ array_values( $row ) ], + [], + $queryInfo['joins'] ); } @@ -358,8 +456,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::insertRevisionOn */ public function testInsertRevisionOn_blobAddressExists() { - $page = $this->getExistingTestPage(); - $title = $page->getTitle(); + $title = $this->getTestPageTitle(); $revDetails = [ 'slot' => SlotRecord::newUnsaved( 'main', new WikitextContent( 'Chicken' ) ), 'parent' => true, @@ -372,14 +469,14 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $store = MediaWikiServices::getInstance()->getRevisionStore(); // Insert the first revision - $revOne = $this->getRevisionRecordFromDetailsArray( $title, $revDetails ); + $revOne = $this->getRevisionRecordFromDetailsArray( $revDetails ); $firstReturn = $store->insertRevisionOn( $revOne, wfGetDB( DB_MASTER ) ); $this->assertLinkTargetsEqual( $title, $firstReturn->getPageAsLinkTarget() ); $this->assertRevisionRecordsEqual( $revOne, $firstReturn ); // Insert a second revision inheriting the same blob address $revDetails['slot'] = SlotRecord::newInherited( $firstReturn->getSlot( 'main' ) ); - $revTwo = $this->getRevisionRecordFromDetailsArray( $title, $revDetails ); + $revTwo = $this->getRevisionRecordFromDetailsArray( $revDetails ); $secondReturn = $store->insertRevisionOn( $revTwo, wfGetDB( DB_MASTER ) ); $this->assertLinkTargetsEqual( $title, $secondReturn->getPageAsLinkTarget() ); $this->assertRevisionRecordsEqual( $revTwo, $secondReturn ); @@ -399,26 +496,23 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { public function provideInsertRevisionOn_failures() { yield 'no slot' => [ - Title::newFromText( 'UTPage' ), [ 'comment' => $this->getRandomCommentStoreComment(), 'timestamp' => '20171117010101', 'user' => true, ], - new InvalidArgumentException( 'At least one slot needs to be defined!' ) + new InvalidArgumentException( 'main slot must be provided' ) ]; - yield 'slot that is not main slot' => [ - Title::newFromText( 'UTPage' ), + yield 'no main slot' => [ [ - 'slot' => SlotRecord::newUnsaved( 'lalala', new WikitextContent( 'Chicken' ) ), + 'slot' => SlotRecord::newUnsaved( 'aux', new WikitextContent( 'Turkey' ) ), 'comment' => $this->getRandomCommentStoreComment(), 'timestamp' => '20171117010101', 'user' => true, ], - new InvalidArgumentException( 'Only the main slot is supported for now!' ) + new InvalidArgumentException( 'main slot must be provided' ) ]; yield 'no timestamp' => [ - Title::newFromText( 'UTPage' ), [ 'slot' => SlotRecord::newUnsaved( 'main', new WikitextContent( 'Chicken' ) ), 'comment' => $this->getRandomCommentStoreComment(), @@ -427,7 +521,6 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { new IncompleteRevisionException( 'timestamp field must not be NULL!' ) ]; yield 'no comment' => [ - Title::newFromText( 'UTPage' ), [ 'slot' => SlotRecord::newUnsaved( 'main', new WikitextContent( 'Chicken' ) ), 'timestamp' => '20171117010101', @@ -436,7 +529,6 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { new IncompleteRevisionException( 'comment must not be NULL!' ) ]; yield 'no user' => [ - Title::newFromText( 'UTPage' ), [ 'slot' => SlotRecord::newUnsaved( 'main', new WikitextContent( 'Chicken' ) ), 'comment' => $this->getRandomCommentStoreComment(), @@ -451,13 +543,10 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::insertRevisionOn */ public function testInsertRevisionOn_failures( - Title $title, array $revDetails = [], Exception $exception ) { - $page = $this->getExistingTestPage( $title ); - - $rev = $this->getRevisionRecordFromDetailsArray( $title, $revDetails ); + $rev = $this->getRevisionRecordFromDetailsArray( $revDetails ); $store = MediaWikiServices::getInstance()->getRevisionStore(); @@ -471,12 +560,14 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { public function provideNewNullRevision() { yield [ - Title::newFromText( __METHOD__ ), + Title::newFromText( 'UTPage_notAutoCreated' ), + [ 'content' => [ 'main' => new WikitextContent( 'Flubber1' ) ] ], CommentStoreComment::newUnsavedComment( __METHOD__ . ' comment1' ), true, ]; yield [ - Title::newFromText( __METHOD__ ), + Title::newFromText( 'UTPage_notAutoCreated' ), + [ 'content' => [ 'main' => new WikitextContent( 'Flubber2' ) ] ], CommentStoreComment::newUnsavedComment( __METHOD__ . ' comment2', [ 'a' => 1 ] ), false, ]; @@ -487,16 +578,28 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::newNullRevision * @covers \MediaWiki\Storage\RevisionStore::findSlotContentId */ - public function testNewNullRevision( Title $title, $comment, $minor ) { + public function testNewNullRevision( Title $title, $revDetails, $comment, $minor = false ) { $this->overrideMwServices(); - $page = $this->getExistingTestPage( $title ); - $rev = $page->getRevision(); + $user = TestUserRegistry::getMutableTestUser( __METHOD__ )->getUser(); + $page = WikiPage::factory( $title ); + + if ( !$page->exists() ) { + $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__, EDIT_NEW ); + } + + $revDetails['page'] = $page->getId(); + $revDetails['timestamp'] = wfTimestampNow(); + $revDetails['comment'] = CommentStoreComment::newUnsavedComment( 'Base' ); + $revDetails['user'] = $user; + $baseRev = $this->getRevisionRecordFromDetailsArray( $revDetails ); $store = MediaWikiServices::getInstance()->getRevisionStore(); - $user = TestUserRegistry::getMutableTestUser( __METHOD__ )->getUser(); - $parent = $store->getRevisionById( $rev->getId() ); + $dbw = wfGetDB( DB_MASTER ); + $baseRev = $store->insertRevisionOn( $baseRev, $dbw ); + $page->updateRevisionOn( $dbw, new Revision( $baseRev ), $page->getLatest() ); + $record = $store->newNullRevision( wfGetDB( DB_MASTER ), $title, @@ -510,14 +613,21 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $this->assertEquals( $comment, $record->getComment() ); $this->assertEquals( $minor, $record->isMinor() ); $this->assertEquals( $user->getName(), $record->getUser()->getName() ); - $this->assertEquals( $parent->getId(), $record->getParentId() ); + $this->assertEquals( $baseRev->getId(), $record->getParentId() ); + + $this->assertArrayEquals( + $baseRev->getSlotRoles(), + $record->getSlotRoles() + ); - $parentSlot = $parent->getSlot( 'main' ); - $slot = $record->getSlot( 'main' ); + foreach ( $baseRev->getSlotRoles() as $role ) { + $parentSlot = $baseRev->getSlot( $role ); + $slot = $record->getSlot( $role ); - $this->assertTrue( $slot->isInherited(), 'isInherited' ); - $this->assertSame( $parentSlot->getOrigin(), $slot->getOrigin(), 'getOrigin' ); - $this->assertSameSlotContent( $parentSlot, $slot ); + $this->assertTrue( $slot->isInherited(), 'isInherited' ); + $this->assertSame( $parentSlot->getOrigin(), $slot->getOrigin(), 'getOrigin' ); + $this->assertSameSlotContent( $parentSlot, $slot ); + } } /** @@ -539,7 +649,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getRcIdIfUnpatrolled */ public function testGetRcIdIfUnpatrolled_returnsRecentChangesId() { - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); $status = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ ); /** @var Revision $rev */ $rev = $status->value['revision']; @@ -550,7 +660,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $this->assertGreaterThan( 0, $result ); $this->assertSame( - $page->getRevision()->getRecentChange()->getAttribute( 'rc_id' ), + $store->getRecentChange( $revisionRecord )->getAttribute( 'rc_id' ), $result ); } @@ -561,7 +671,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { public function testGetRcIdIfUnpatrolled_returnsZeroIfPatrolled() { // This assumes that sysops are auto patrolled $sysop = $this->getTestSysop()->getUser(); - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); $status = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__, @@ -583,7 +693,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getRecentChange */ public function testGetRecentChange() { - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); $content = new WikitextContent( __METHOD__ ); $status = $page->doEditContent( $content, __METHOD__ ); /** @var Revision $rev */ @@ -601,7 +711,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getRevisionById */ public function testGetRevisionById() { - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); $content = new WikitextContent( __METHOD__ ); $status = $page->doEditContent( $content, __METHOD__ ); /** @var Revision $rev */ @@ -619,7 +729,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getRevisionByTitle */ public function testGetRevisionByTitle() { - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); $content = new WikitextContent( __METHOD__ ); $status = $page->doEditContent( $content, __METHOD__ ); /** @var Revision $rev */ @@ -637,7 +747,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getRevisionByPageId */ public function testGetRevisionByPageId() { - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); $content = new WikitextContent( __METHOD__ ); $status = $page->doEditContent( $content, __METHOD__ ); /** @var Revision $rev */ @@ -658,7 +768,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { // Make sure there is 1 second between the last revision and the rev we create... // Otherwise we might not get the correct revision and the test may fail... // :( - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); sleep( 1 ); $content = new WikitextContent( __METHOD__ ); $status = $page->doEditContent( $content, __METHOD__ ); @@ -676,13 +786,13 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $this->assertSame( __METHOD__, $revRecord->getComment()->text ); } - protected function revisionToRow( Revision $rev ) { + protected function revisionToRow( Revision $rev, $options = [ 'page', 'user', 'comment' ] ) { + // XXX: the WikiPage object loads another RevisionRecord from the database. Not great. $page = WikiPage::factory( $rev->getTitle() ); - return (object)[ + $fields = [ 'rev_id' => (string)$rev->getId(), 'rev_page' => (string)$rev->getPage(), - 'rev_text_id' => (string)$rev->getTextId(), 'rev_timestamp' => $this->db->timestamp( $rev->getTimestamp() ), 'rev_user_text' => (string)$rev->getUserText(), 'rev_user' => (string)$rev->getUser(), @@ -691,22 +801,43 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { 'rev_len' => (string)$rev->getSize(), 'rev_parent_id' => (string)$rev->getParentId(), 'rev_sha1' => (string)$rev->getSha1(), - 'rev_comment_text' => $rev->getComment(), - 'rev_comment_data' => null, - 'rev_comment_cid' => null, - 'rev_content_format' => $rev->getContentFormat(), - 'rev_content_model' => $rev->getContentModel(), - 'page_namespace' => (string)$page->getTitle()->getNamespace(), - 'page_title' => $page->getTitle()->getDBkey(), - 'page_id' => (string)$page->getId(), - 'page_latest' => (string)$page->getLatest(), - 'page_is_redirect' => $page->isRedirect() ? '1' : '0', - 'page_len' => (string)$page->getContent()->getSize(), - 'user_name' => (string)$rev->getUserText(), ]; + + if ( in_array( 'page', $options ) ) { + $fields += [ + 'page_namespace' => (string)$page->getTitle()->getNamespace(), + 'page_title' => $page->getTitle()->getDBkey(), + 'page_id' => (string)$page->getId(), + 'page_latest' => (string)$page->getLatest(), + 'page_is_redirect' => $page->isRedirect() ? '1' : '0', + 'page_len' => (string)$page->getContent()->getSize(), + ]; + } + + if ( in_array( 'user', $options ) ) { + $fields += [ + 'user_name' => (string)$rev->getUserText(), + ]; + } + + if ( in_array( 'comment', $options ) ) { + $fields += [ + 'rev_comment_text' => $rev->getComment(), + 'rev_comment_data' => null, + 'rev_comment_cid' => null, + ]; + } + + if ( $rev->getId() ) { + $fields += [ + 'rev_id' => (string)$rev->getId(), + ]; + } + + return (object)$fields; } - private function assertRevisionRecordMatchesRevision( + protected function assertRevisionRecordMatchesRevision( Revision $rev, RevisionRecord $record ) { @@ -756,11 +887,41 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { /** * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow - * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow_1_29 + * @covers \MediaWiki\Storage\RevisionStore::getQueryInfo */ - public function testNewRevisionFromRow_anonEdit() { - $page = $this->getExistingTestPage(); + 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 + */ + public function testNewRevisionFromRow_anonEdit() { + $page = $this->getTestPage(); $text = __METHOD__ . 'a-ä'; /** @var Revision $rev */ $rev = $page->doEditContent( @@ -780,18 +941,16 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { /** * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow - * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow_1_29 */ public function testNewRevisionFromRow_anonEdit_legacyEncoding() { $this->setMwGlobals( 'wgLegacyEncoding', 'windows-1252' ); $this->overrideMwServices(); - $page = $this->getExistingTestPage(); - + $page = $this->getTestPage(); $text = __METHOD__ . 'a-ä'; /** @var Revision $rev */ $rev = $page->doEditContent( new WikitextContent( $text ), - __METHOD__. 'a' + __METHOD__ . 'a' )->value['revision']; $store = MediaWikiServices::getInstance()->getRevisionStore(); @@ -806,11 +965,9 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { /** * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow - * @covers \MediaWiki\Storage\RevisionStore::newRevisionFromRow_1_29 */ public function testNewRevisionFromRow_userEdit() { - $page = $this->getExistingTestPage(); - + $page = $this->getTestPage(); $text = __METHOD__ . 'b-ä'; /** @var Revision $rev */ $rev = $page->doEditContent( @@ -833,12 +990,13 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { /** * @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ä'; - $page = $this->getExistingTestPage( $title ); + $page = WikiPage::factory( $title ); /** @var Revision $orig */ $orig = $page->doEditContent( new WikitextContent( $text ), __METHOD__ ) ->value['revision']; @@ -869,7 +1027,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $store = MediaWikiServices::getInstance()->getRevisionStore(); $title = Title::newFromText( __METHOD__ ); $text = __METHOD__ . '-bä'; - $page = $this->getExistingTestPage( $title ); + $page = WikiPage::factory( $title ); /** @var Revision $orig */ $orig = $page->doEditContent( new WikitextContent( $text ), __METHOD__ ) ->value['revision']; @@ -891,10 +1049,89 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $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__ ); @@ -906,6 +1143,9 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $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( @@ -913,34 +1153,37 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { __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 ); } /** @@ -948,8 +1191,10 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { */ public function testLoadRevisionFromId() { $title = Title::newFromText( __METHOD__ ); - $page = $this->getExistingTestPage( $title ); - $rev = $page->getRevision(); + $page = WikiPage::factory( $title ); + /** @var Revision $rev */ + $rev = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ ) + ->value['revision']; $store = MediaWikiServices::getInstance()->getRevisionStore(); $result = $store->loadRevisionFromId( wfGetDB( DB_MASTER ), $rev->getId() ); @@ -961,8 +1206,10 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { */ public function testLoadRevisionFromPageId() { $title = Title::newFromText( __METHOD__ ); - $page = $this->getExistingTestPage( $title ); - $rev = $page->getRevision(); + $page = WikiPage::factory( $title ); + /** @var Revision $rev */ + $rev = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ ) + ->value['revision']; $store = MediaWikiServices::getInstance()->getRevisionStore(); $result = $store->loadRevisionFromPageId( wfGetDB( DB_MASTER ), $page->getId() ); @@ -974,8 +1221,10 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { */ public function testLoadRevisionFromTitle() { $title = Title::newFromText( __METHOD__ ); - $page = $this->getExistingTestPage( $title ); - $rev = $page->getRevision(); + $page = WikiPage::factory( $title ); + /** @var Revision $rev */ + $rev = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ ) + ->value['revision']; $store = MediaWikiServices::getInstance()->getRevisionStore(); $result = $store->loadRevisionFromTitle( wfGetDB( DB_MASTER ), $title ); @@ -986,8 +1235,8 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::loadRevisionFromTimestamp */ public function testLoadRevisionFromTimestamp() { - $page = $this->getNonexistingTestPage( __METHOD__ ); - $title = $page->getTitle(); + $title = Title::newFromText( __METHOD__ ); + $page = WikiPage::factory( $title ); /** @var Revision $revOne */ $revOne = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ ) ->value['revision']; @@ -1023,7 +1272,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::listRevisionSizes */ public function testGetParentLengths() { - $page = $this->getNonexistingTestPage( __METHOD__ ); + $page = WikiPage::factory( Title::newFromText( __METHOD__ ) ); /** @var Revision $revOne */ $revOne = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ @@ -1059,7 +1308,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getPreviousRevision */ public function testGetPreviousRevision() { - $page = $this->getNonexistingTestPage( __METHOD__ ); + $page = WikiPage::factory( Title::newFromText( __METHOD__ ) ); /** @var Revision $revOne */ $revOne = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ @@ -1083,7 +1332,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getNextRevision */ public function testGetNextRevision() { - $page = $this->getNonexistingTestPage( __METHOD__ ); + $page = WikiPage::factory( Title::newFromText( __METHOD__ ) ); /** @var Revision $revOne */ $revOne = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ @@ -1107,8 +1356,10 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getTimestampFromId */ public function testGetTimestampFromId_found() { - $page = $this->getExistingTestPage(); - $rev = $page->getRevision(); + $page = $this->getTestPage(); + /** @var Revision $rev */ + $rev = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ ) + ->value['revision']; $store = MediaWikiServices::getInstance()->getRevisionStore(); $result = $store->getTimestampFromId( @@ -1123,8 +1374,10 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getTimestampFromId */ public function testGetTimestampFromId_notFound() { - $page = $this->getExistingTestPage(); - $rev = $page->getRevision(); + $page = $this->getTestPage(); + /** @var Revision $rev */ + $rev = $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ ) + ->value['revision']; $store = MediaWikiServices::getInstance()->getRevisionStore(); $result = $store->getTimestampFromId( @@ -1140,7 +1393,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { */ public function testCountRevisionsByPageId() { $store = MediaWikiServices::getInstance()->getRevisionStore(); - $page = $this->getNonexistingTestPage( __METHOD__ ); + $page = WikiPage::factory( Title::newFromText( __METHOD__ ) ); $this->assertSame( 0, @@ -1163,7 +1416,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { */ public function testCountRevisionsByTitle() { $store = MediaWikiServices::getInstance()->getRevisionStore(); - $page = $this->getNonexistingTestPage( __METHOD__ ); + $page = WikiPage::factory( Title::newFromText( __METHOD__ ) ); $this->assertSame( 0, @@ -1186,7 +1439,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { */ public function testUserWasLastToEdit_false() { $sysop = $this->getTestSysop()->getUser(); - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ ); $store = MediaWikiServices::getInstance()->getRevisionStore(); @@ -1205,7 +1458,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { public function testUserWasLastToEdit_true() { $startTime = wfTimestampNow(); $sysop = $this->getTestSysop()->getUser(); - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); $page->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__, @@ -1228,7 +1481,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { * @covers \MediaWiki\Storage\RevisionStore::getKnownCurrentRevision */ public function testGetKnownCurrentRevision() { - $page = $this->getExistingTestPage(); + $page = $this->getTestPage(); /** @var Revision $rev */ $rev = $page->doEditContent( new WikitextContent( __METHOD__ . 'b' ), @@ -1248,24 +1501,6 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { } public function provideNewMutableRevisionFromArray() { - yield 'Basic array, with page & id' => [ - [ - 'id' => 2, - 'page' => 1, - 'text_id' => 2, - 'timestamp' => '20171017114835', - 'user_text' => '111.0.1.2', - 'user' => 0, - 'minor_edit' => false, - 'deleted' => 0, - 'len' => 46, - 'parent_id' => 1, - 'sha1' => 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z', - 'comment' => 'Goat Comment!', - 'content_format' => 'text/x-wiki', - 'content_model' => 'wikitext', - ] - ]; yield 'Basic array, content object' => [ [ 'id' => 2, @@ -1318,7 +1553,6 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { yield 'Basic array, with title' => [ [ 'title' => Title::newFromText( 'SomeText' ), - 'text_id' => 2, 'timestamp' => '20171017114835', 'user_text' => '111.0.1.2', 'user' => 0, @@ -1328,15 +1562,13 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { 'parent_id' => 1, 'sha1' => 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z', 'comment' => 'Goat Comment!', - 'content_format' => 'text/x-wiki', - 'content_model' => 'wikitext', + 'content' => new WikitextContent( 'Some Content' ), ] ]; yield 'Basic array, no user field' => [ [ 'id' => 2, 'page' => 1, - 'text_id' => 2, 'timestamp' => '20171017114835', 'user_text' => '111.0.1.3', 'minor_edit' => false, @@ -1345,8 +1577,7 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { 'parent_id' => 1, 'sha1' => 'rdqbbzs3pkhihgbs8qf2q9jsvheag5z', 'comment' => 'Goat Comment!', - 'content_format' => 'text/x-wiki', - 'content_model' => 'wikitext', + 'content' => new WikitextContent( 'Some Content' ), ] ]; } @@ -1388,12 +1619,14 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $this->assertSame( $array['sha1'], $result->getSha1() ); $this->assertSame( $array['comment'], $result->getComment()->text ); if ( isset( $array['content'] ) ) { - $this->assertTrue( - $result->getSlot( 'main' )->getContent()->equals( $array['content'] ) - ); + foreach ( $array['content'] as $role => $content ) { + $this->assertTrue( + $result->getContent( $role )->equals( $content ) + ); + } } elseif ( isset( $array['text'] ) ) { $this->assertSame( $array['text'], $result->getSlot( 'main' )->getContent()->serialize() ); - } else { + } elseif ( isset( $array['content_format'] ) ) { $this->assertSame( $array['content_format'], $result->getSlot( 'main' )->getContent()->getDefaultFormat() @@ -1428,155 +1661,4 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase { $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'] - ); - } - - /** - * 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 ); - } - }