Merge "RevisionStoreDbTestBase, remove redundant needsDB override"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 24 Sep 2018 13:48:21 +0000 (13:48 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 24 Sep 2018 13:48:21 +0000 (13:48 +0000)
1  2 
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';
  
                $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();
        }
                $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->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 ) {
                }
        }
  
 -      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() );
                $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' ) );
                }
        }
  
 -      private function assertSlotCompleteness( RevisionRecord $r, SlotRecord $slot ) {
 +      protected function assertSlotCompleteness( RevisionRecord $r, SlotRecord $slot ) {
                $this->assertTrue( $slot->hasAddress() );
                $this->assertSame( $r->getId(), $slot->getRevision() );
  
        public function testInsertRevisionOn_successes(
                array $revDetails = []
        ) {
 -              // FIXME: fails under postgres
 -              $this->markTestSkippedIfDbType( 'postgres' );
 -
                $title = $this->getTestPageTitle();
                $rev = $this->getRevisionRecordFromDetailsArray( $revDetails );
  
                $this->assertEquals( $user->getName(), $record->getUser()->getName() );
                $this->assertEquals( $baseRev->getId(), $record->getParentId() );
  
 -              $this->assertArrayEqualsIgnoringIntKeyOrder(
 +              $this->assertArrayEquals(
                        $baseRev->getSlotRoles(),
                        $record->getSlotRoles()
                );
                return (object)$fields;
        }
  
 -      private function assertRevisionRecordMatchesRevision(
 +      protected function assertRevisionRecordMatchesRevision(
                Revision $rev,
                RevisionRecord $record
        ) {
                }
        }
  
 +      /**
 +       * @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
         */
                /** @var Revision $rev */
                $rev = $page->doEditContent(
                        new WikitextContent( $text ),
 -                      __METHOD__. 'a'
 +                      __METHOD__ . 'a'
                )->value['revision'];
  
                $store = MediaWikiServices::getInstance()->getRevisionStore();
  
        /**
         * @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ä';
                $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__ );
  
                $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(
                        __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 );
        }
  
        /**
                $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 );
 -      }
 -
  }