wiki.techinc.nl/tests/phpunit/includes/Revision/RevisionArchiveRecordTest.php
Petr Pchelko 816e02ae51 Convert RevisionRecord to Authority and PageIdentity
As we convert the RevisionRecord to using Authority,
we no longer need Title instances, so we can convert
that to PageIdentity.

Ideally, we'd part away from using Title at all, but:
1. For foreign wikis PageIdentity has stronger validation,
so calling PageIdentity getId() on Title will break things.
There's still a lot of code depending on lax Title guarantees,
so we keep it.
2. A lot of code still depends on Title, so we try to pass it
through even if we don't nesessarily need to, to save cost
on recreating it later on.

Bug: T271458
Depends-On: I287400b967b467ea18bebbb579e881a785a19158
Change-Id: I63d9807264d7e2295afef51fc9d982447f92fcbd
2021-01-21 13:37:01 -06:00

346 lines
8.5 KiB
PHP

<?php
namespace MediaWiki\Tests\Revision;
use CommentStoreComment;
use InvalidArgumentException;
use MediaWiki\Page\PageIdentity;
use MediaWiki\Page\PageIdentityValue;
use MediaWiki\Revision\RevisionArchiveRecord;
use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Revision\RevisionSlots;
use MediaWiki\Revision\SlotRecord;
use MediaWiki\User\UserIdentity;
use MediaWiki\User\UserIdentityValue;
use MediaWikiIntegrationTestCase;
use stdClass;
use TextContent;
use Title;
use TitleValue;
use Wikimedia\Assert\PreconditionException;
/**
* @covers \MediaWiki\Revision\RevisionArchiveRecord
* @covers \MediaWiki\Revision\RevisionRecord
*/
class RevisionArchiveRecordTest extends MediaWikiIntegrationTestCase {
use RevisionRecordTests;
/**
* @param array $rowOverrides
*
* @return RevisionArchiveRecord
*/
protected function newRevision( array $rowOverrides = [] ) {
$title = Title::newFromText( 'Dummy' );
$title->resetArticleID( 17 );
$user = new UserIdentityValue( 11, 'Tester', 0 );
$comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
$main = SlotRecord::newUnsaved( SlotRecord::MAIN, new TextContent( 'Lorem Ipsum' ) );
$aux = SlotRecord::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
$slots = new RevisionSlots( [ $main, $aux ] );
$row = [
'ar_id' => '5',
'ar_rev_id' => '7',
'ar_page_id' => strval( $title->getArticleID() ),
'ar_timestamp' => '20200101000000',
'ar_deleted' => 0,
'ar_minor_edit' => 0,
'ar_parent_id' => '5',
'ar_len' => $slots->computeSize(),
'ar_sha1' => $slots->computeSha1(),
];
foreach ( $rowOverrides as $field => $value ) {
$field = preg_replace( '/^rev_/', 'ar_', $field );
$row[$field] = $value;
}
return new RevisionArchiveRecord( $title, $user, $comment, (object)$row, $slots );
}
public function provideConstructor() {
$user = new UserIdentityValue( 11, 'Tester', 0 );
$comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
$main = SlotRecord::newUnsaved( SlotRecord::MAIN, new TextContent( 'Lorem Ipsum' ) );
$aux = SlotRecord::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
$slots = new RevisionSlots( [ $main, $aux ] );
$protoRow = [
'ar_id' => '5',
'ar_rev_id' => '7',
'ar_page_id' => '17',
'ar_timestamp' => '20200101000000',
'ar_deleted' => 0,
'ar_minor_edit' => 0,
'ar_parent_id' => '5',
'ar_len' => $slots->computeSize(),
'ar_sha1' => $slots->computeSha1(),
];
$row = $protoRow;
yield 'all info' => [
new PageIdentityValue( 17, NS_MAIN, 'Dummy', 'acmewiki' ),
$user,
$comment,
(object)$row,
$slots,
'acmewiki',
PreconditionException::class
];
yield 'all info, local' => [
new PageIdentityValue( 17, NS_MAIN, 'Dummy', PageIdentity::LOCAL ),
$user,
$comment,
(object)$row,
$slots,
];
$title = Title::newFromText( 'Dummy' );
$title->resetArticleID( 17 );
yield 'all info, local, with Title' => [
$title,
$user,
$comment,
(object)$row,
$slots,
];
// this case exists for b/c and should be deprecated
yield 'all info, foreign, with Title' => [
$title,
$user,
$comment,
(object)$row,
$slots,
'acmewiki',
];
$row = $protoRow;
$row['ar_minor_edit'] = '1';
$row['ar_deleted'] = strval( RevisionRecord::DELETED_USER );
yield 'minor deleted' => [
$title,
$user,
$comment,
(object)$row,
$slots
];
$row = $protoRow;
unset( $row['ar_parent'] );
yield 'no parent' => [
$title,
$user,
$comment,
(object)$row,
$slots
];
$row = $protoRow;
$row['ar_len'] = null;
$row['ar_sha1'] = '';
yield 'ar_len is null, ar_sha1 is ""' => [
$title,
$user,
$comment,
(object)$row,
$slots
];
$row = $protoRow;
yield 'no length, no hash' => [
Title::newFromText( 'DummyDoesNotExist' ),
$user,
$comment,
(object)$row,
$slots
];
}
/**
* @dataProvider provideConstructor
*
* @param Title $page
* @param UserIdentity $user
* @param CommentStoreComment $comment
* @param stdClass $row
* @param RevisionSlots $slots
* @param bool $wikiId
* @param string|null $expectedException
*/
public function testConstructorAndGetters(
PageIdentity $page,
UserIdentity $user,
CommentStoreComment $comment,
$row,
RevisionSlots $slots,
$wikiId = PageIdentity::LOCAL,
string $expectedException = null
) {
$rec = new RevisionArchiveRecord( $page, $user, $comment, $row, $slots, $wikiId );
$this->assertTrue( $page->isSamePageAs( $rec->getPage() ), 'getPage' );
$this->assertSame( $user, $rec->getUser( RevisionRecord::RAW ), 'getUser' );
$this->assertSame( $comment, $rec->getComment(), 'getComment' );
$this->assertSame( $slots->getSlotRoles(), $rec->getSlotRoles(), 'getSlotRoles' );
$this->assertSame( $wikiId, $rec->getWikiId(), 'getWikiId' );
$this->assertSame( (int)$row->ar_id, $rec->getArchiveId(), 'getArchiveId' );
$this->assertSame( (int)$row->ar_rev_id, $rec->getId(), 'getId' );
$this->assertSame( (int)$row->ar_page_id, $rec->getPageId(), 'getId' );
$this->assertSame( $row->ar_timestamp, $rec->getTimestamp(), 'getTimestamp' );
$this->assertSame( (int)$row->ar_deleted, $rec->getVisibility(), 'getVisibility' );
$this->assertSame( (bool)$row->ar_minor_edit, $rec->isMinor(), 'getIsMinor' );
if ( isset( $row->ar_parent_id ) ) {
$this->assertSame( (int)$row->ar_parent_id, $rec->getParentId(), 'getParentId' );
} else {
$this->assertSame( 0, $rec->getParentId(), 'getParentId' );
}
if ( isset( $row->ar_len ) ) {
$this->assertSame( (int)$row->ar_len, $rec->getSize(), 'getSize' );
} else {
$this->assertSame( $slots->computeSize(), $rec->getSize(), 'getSize' );
}
if ( !empty( $row->ar_sha1 ) ) {
$this->assertSame( $row->ar_sha1, $rec->getSha1(), 'getSha1' );
} else {
$this->assertSame( $slots->computeSha1(), $rec->getSha1(), 'getSha1' );
}
if ( $expectedException ) {
$this->expectException( $expectedException );
$rec->getPageAsLinkTarget();
} else {
$this->assertTrue(
TitleValue::newFromPage( $page )->isSameLinkAs( $rec->getPageAsLinkTarget() ),
'getPageAsLinkTarget'
);
}
}
public function provideConstructorFailure() {
$title = Title::newFromText( 'Dummy' );
$title->resetArticleID( 17 );
$user = new UserIdentityValue( 11, 'Tester', 0 );
$comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
$main = SlotRecord::newUnsaved( SlotRecord::MAIN, new TextContent( 'Lorem Ipsum' ) );
$aux = SlotRecord::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
$slots = new RevisionSlots( [ $main, $aux ] );
$protoRow = [
'ar_id' => '5',
'ar_rev_id' => '7',
'ar_page_id' => strval( $title->getArticleID() ),
'ar_timestamp' => '20200101000000',
'ar_deleted' => 0,
'ar_minor_edit' => 0,
'ar_parent_id' => '5',
'ar_len' => $slots->computeSize(),
'ar_sha1' => $slots->computeSha1(),
];
yield 'mismatching wiki ID' => [
new PageIdentityValue(
$title->getArticleID(),
$title->getNamespace(),
$title->getDBkey(),
PageIdentity::LOCAL
),
$user,
$comment,
'not a row',
$slots,
'acmewiki',
PreconditionException::class
];
yield 'not a row' => [
new PageIdentityValue(
$title->getArticleID(),
$title->getNamespace(),
$title->getDBkey(),
'acmewiki'
),
$user,
$comment,
'not a row',
$slots,
'acmewiki'
];
$row = $protoRow;
$row['ar_timestamp'] = 'kittens';
yield 'bad timestamp' => [
$title,
$user,
$comment,
(object)$row,
$slots
];
$row = $protoRow;
yield 'bad wiki' => [
$title,
$user,
$comment,
(object)$row,
$slots,
12345
];
// NOTE: $title->getArticleID does *not* have to match ar_page_id in all cases!
}
/**
* @dataProvider provideConstructorFailure
*
* @param PageIdentity $page
* @param UserIdentity $user
* @param CommentStoreComment $comment
* @param stdClass $row
* @param RevisionSlots $slots
* @param bool $wikiId,
* @param string|null $expectedException
*/
public function testConstructorFailure(
PageIdentity $page,
UserIdentity $user,
CommentStoreComment $comment,
$row,
RevisionSlots $slots,
$wikiId = false,
string $expectedException = InvalidArgumentException::class
) {
$this->expectException( $expectedException );
new RevisionArchiveRecord( $page, $user, $comment, $row, $slots, $wikiId );
}
/**
* @covers \MediaWiki\Revision\RevisionRecord::isCurrent
*/
public function testIsCurrent() {
$rev = $this->newRevision();
$this->assertFalse( $rev->isCurrent(),
RevisionArchiveRecord::class . ' cannot be stored current revision' );
}
}