3 namespace MediaWiki\Tests\Storage
;
5 use CommentStoreComment
;
6 use InvalidArgumentException
;
7 use MediaWiki\Storage\RevisionRecord
;
8 use MediaWiki\Storage\RevisionSlots
;
9 use MediaWiki\Storage\RevisionStoreRecord
;
10 use MediaWiki\Storage\SlotRecord
;
11 use MediaWiki\User\UserIdentity
;
12 use MediaWiki\User\UserIdentityValue
;
13 use MediaWikiTestCase
;
18 * @covers \MediaWiki\Storage\RevisionStoreRecord
19 * @covers \MediaWiki\Storage\RevisionRecord
21 class RevisionStoreRecordTest
extends MediaWikiTestCase
{
23 use RevisionRecordTests
;
26 * @param array $rowOverrides
28 * @return RevisionStoreRecord
30 protected function newRevision( array $rowOverrides = [] ) {
31 $title = Title
::newFromText( 'Dummy' );
32 $title->resetArticleID( 17 );
34 $user = new UserIdentityValue( 11, 'Tester', 0 );
35 $comment = CommentStoreComment
::newUnsavedComment( 'Hello World' );
37 $main = SlotRecord
::newUnsaved( 'main', new TextContent( 'Lorem Ipsum' ) );
38 $aux = SlotRecord
::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
39 $slots = new RevisionSlots( [ $main, $aux ] );
43 'rev_page' => strval( $title->getArticleID() ),
44 'rev_timestamp' => '20200101000000',
46 'rev_minor_edit' => 0,
47 'rev_parent_id' => '5',
48 'rev_len' => $slots->computeSize(),
49 'rev_sha1' => $slots->computeSha1(),
50 'page_latest' => '18',
53 $row = array_merge( $row, $rowOverrides );
55 return new RevisionStoreRecord( $title, $user, $comment, (object)$row, $slots );
58 public function provideConstructor() {
59 $title = Title
::newFromText( 'Dummy' );
60 $title->resetArticleID( 17 );
62 $user = new UserIdentityValue( 11, 'Tester', 0 );
63 $comment = CommentStoreComment
::newUnsavedComment( 'Hello World' );
65 $main = SlotRecord
::newUnsaved( 'main', new TextContent( 'Lorem Ipsum' ) );
66 $aux = SlotRecord
::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
67 $slots = new RevisionSlots( [ $main, $aux ] );
71 'rev_page' => strval( $title->getArticleID() ),
72 'rev_timestamp' => '20200101000000',
74 'rev_minor_edit' => 0,
75 'rev_parent_id' => '5',
76 'rev_len' => $slots->computeSize(),
77 'rev_sha1' => $slots->computeSha1(),
78 'page_latest' => '18',
92 $row['rev_minor_edit'] = '1';
93 $row['rev_deleted'] = strval( RevisionRecord
::DELETED_USER
);
95 yield
'minor deleted' => [
104 $row['page_latest'] = $row['rev_id'];
115 unset( $row['rev_parent'] );
117 yield
'no parent' => [
126 $row['rev_len'] = null;
127 $row['rev_sha1'] = '';
129 yield
'rev_len is null, rev_sha1 is ""' => [
138 yield
'no length, no hash' => [
139 Title
::newFromText( 'DummyDoesNotExist' ),
148 * @dataProvider provideConstructor
150 * @param Title $title
151 * @param UserIdentity $user
152 * @param CommentStoreComment $comment
154 * @param RevisionSlots $slots
155 * @param bool $wikiId
157 public function testConstructorAndGetters(
160 CommentStoreComment
$comment,
162 RevisionSlots
$slots,
165 $rec = new RevisionStoreRecord( $title, $user, $comment, $row, $slots, $wikiId );
167 $this->assertSame( $title, $rec->getPageAsLinkTarget(), 'getPageAsLinkTarget' );
168 $this->assertSame( $user, $rec->getUser( RevisionRecord
::RAW
), 'getUser' );
169 $this->assertSame( $comment, $rec->getComment(), 'getComment' );
171 $this->assertSame( $slots->getSlotRoles(), $rec->getSlotRoles(), 'getSlotRoles' );
172 $this->assertSame( $wikiId, $rec->getWikiId(), 'getWikiId' );
174 $this->assertSame( (int)$row->rev_id
, $rec->getId(), 'getId' );
175 $this->assertSame( (int)$row->rev_page
, $rec->getPageId(), 'getId' );
176 $this->assertSame( $row->rev_timestamp
, $rec->getTimestamp(), 'getTimestamp' );
177 $this->assertSame( (int)$row->rev_deleted
, $rec->getVisibility(), 'getVisibility' );
178 $this->assertSame( (bool)$row->rev_minor_edit
, $rec->isMinor(), 'getIsMinor' );
180 if ( isset( $row->rev_parent_id
) ) {
181 $this->assertSame( (int)$row->rev_parent_id
, $rec->getParentId(), 'getParentId' );
183 $this->assertSame( 0, $rec->getParentId(), 'getParentId' );
186 if ( isset( $row->rev_len
) ) {
187 $this->assertSame( (int)$row->rev_len
, $rec->getSize(), 'getSize' );
189 $this->assertSame( $slots->computeSize(), $rec->getSize(), 'getSize' );
192 if ( !empty( $row->rev_sha1
) ) {
193 $this->assertSame( $row->rev_sha1
, $rec->getSha1(), 'getSha1' );
195 $this->assertSame( $slots->computeSha1(), $rec->getSha1(), 'getSha1' );
198 if ( isset( $row->page_latest
) ) {
200 (int)$row->rev_id
=== (int)$row->page_latest
,
213 public function provideConstructorFailure() {
214 $title = Title
::newFromText( 'Dummy' );
215 $title->resetArticleID( 17 );
217 $user = new UserIdentityValue( 11, 'Tester', 0 );
219 $comment = CommentStoreComment
::newUnsavedComment( 'Hello World' );
221 $main = SlotRecord
::newUnsaved( 'main', new TextContent( 'Lorem Ipsum' ) );
222 $aux = SlotRecord
::newUnsaved( 'aux', new TextContent( 'Frumious Bandersnatch' ) );
223 $slots = new RevisionSlots( [ $main, $aux ] );
227 'rev_page' => strval( $title->getArticleID() ),
228 'rev_timestamp' => '20200101000000',
230 'rev_minor_edit' => 0,
231 'rev_parent_id' => '5',
232 'rev_len' => $slots->computeSize(),
233 'rev_sha1' => $slots->computeSha1(),
234 'page_latest' => '18',
237 yield
'not a row' => [
247 $row['rev_timestamp'] = 'kittens';
249 yield
'bad timestamp' => [
258 $row['rev_page'] = 99;
260 yield
'page ID mismatch' => [
270 yield
'bad wiki' => [
281 * @dataProvider provideConstructorFailure
283 * @param Title $title
284 * @param UserIdentity $user
285 * @param CommentStoreComment $comment
287 * @param RevisionSlots $slots
288 * @param bool $wikiId
290 public function testConstructorFailure(
293 CommentStoreComment
$comment,
295 RevisionSlots
$slots,
298 $this->setExpectedException( InvalidArgumentException
::class );
299 new RevisionStoreRecord( $title, $user, $comment, $row, $slots, $wikiId );
302 public function provideIsCurrent() {
320 * @dataProvider provideIsCurrent
322 public function testIsCurrent( $row, $current ) {
323 $rev = $this->newRevision( $row );
325 $this->assertSame( $current, $rev->isCurrent(), 'isCurrent()' );
328 public function provideGetSlot_audience_latest() {
329 return $this->provideAudienceCheckData( RevisionRecord
::DELETED_TEXT
);
333 * @dataProvider provideGetSlot_audience_latest
335 public function testGetSlot_audience_latest( $visibility, $groups, $userCan, $publicCan ) {
336 $this->forceStandardPermissions();
338 $user = $this->getTestUser( $groups )->getUser();
339 $rev = $this->newRevision(
341 'rev_deleted' => $visibility,
343 'page_latest' => 11, // revision is current
347 // NOTE: slot meta-data is never suppressed, just the content is!
348 $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord
::RAW
), 'raw can' );
349 $this->assertNotNull( $rev->getSlot( 'main', RevisionRecord
::FOR_PUBLIC
), 'public can' );
351 $this->assertNotNull(
352 $rev->getSlot( 'main', RevisionRecord
::FOR_THIS_USER
, $user ),
356 $rev->getSlot( 'main', RevisionRecord
::RAW
)->getContent();
357 // NOTE: the content of the current revision is never suppressed!
358 // Check that getContent() doesn't throw SuppressedDataException
359 $rev->getSlot( 'main', RevisionRecord
::FOR_PUBLIC
)->getContent();
360 $rev->getSlot( 'main', RevisionRecord
::FOR_THIS_USER
, $user )->getContent();