Merge "RevisionIntegrationTest more newFromArchiveRow tests"
[lhc/web/wiklou.git] / tests / phpunit / includes / RevisionIntegrationTest.php
1 <?php
2
3 /**
4 * @group ContentHandler
5 * @group Database
6 *
7 * @group medium
8 */
9 class RevisionIntegrationTest extends MediaWikiTestCase {
10
11 /**
12 * @var WikiPage $testPage
13 */
14 private $testPage;
15
16 public function __construct( $name = null, array $data = [], $dataName = '' ) {
17 parent::__construct( $name, $data, $dataName );
18
19 $this->tablesUsed = array_merge( $this->tablesUsed,
20 [
21 'page',
22 'revision',
23 'ip_changes',
24 'text',
25 'archive',
26
27 'recentchanges',
28 'logging',
29
30 'page_props',
31 'pagelinks',
32 'categorylinks',
33 'langlinks',
34 'externallinks',
35 'imagelinks',
36 'templatelinks',
37 'iwlinks'
38 ]
39 );
40 }
41
42 protected function setUp() {
43 global $wgContLang;
44
45 parent::setUp();
46
47 $this->mergeMwGlobalArrayValue(
48 'wgExtraNamespaces',
49 [
50 12312 => 'Dummy',
51 12313 => 'Dummy_talk',
52 ]
53 );
54
55 $this->mergeMwGlobalArrayValue(
56 'wgNamespaceContentModels',
57 [
58 12312 => DummyContentForTesting::MODEL_ID,
59 ]
60 );
61
62 $this->mergeMwGlobalArrayValue(
63 'wgContentHandlers',
64 [
65 DummyContentForTesting::MODEL_ID => 'DummyContentHandlerForTesting',
66 RevisionTestModifyableContent::MODEL_ID => 'RevisionTestModifyableContentHandler',
67 ]
68 );
69
70 MWNamespace::clearCaches();
71 // Reset namespace cache
72 $wgContLang->resetNamespaces();
73 if ( !$this->testPage ) {
74 $this->testPage = WikiPage::factory( Title::newFromText( 'UTPage' ) );
75 }
76 }
77
78 protected function tearDown() {
79 global $wgContLang;
80
81 parent::tearDown();
82
83 MWNamespace::clearCaches();
84 // Reset namespace cache
85 $wgContLang->resetNamespaces();
86 }
87
88 private function makeRevisionWithProps( $props = null ) {
89 if ( $props === null ) {
90 $props = [];
91 }
92
93 if ( !isset( $props['content'] ) && !isset( $props['text'] ) ) {
94 $props['text'] = 'Lorem Ipsum';
95 }
96
97 if ( !isset( $props['comment'] ) ) {
98 $props['comment'] = 'just a test';
99 }
100
101 if ( !isset( $props['page'] ) ) {
102 $props['page'] = $this->testPage->getId();
103 }
104
105 $rev = new Revision( $props );
106
107 $dbw = wfGetDB( DB_MASTER );
108 $rev->insertOn( $dbw );
109
110 return $rev;
111 }
112
113 /**
114 * @param string $titleString
115 * @param string $text
116 * @param string|null $model
117 *
118 * @return WikiPage
119 */
120 private function createPage( $titleString, $text, $model = null ) {
121 if ( !preg_match( '/:/', $titleString ) &&
122 ( $model === null || $model === CONTENT_MODEL_WIKITEXT )
123 ) {
124 $ns = $this->getDefaultWikitextNS();
125 $titleString = MWNamespace::getCanonicalName( $ns ) . ':' . $titleString;
126 }
127
128 $title = Title::newFromText( $titleString );
129 $wikipage = new WikiPage( $title );
130
131 // Delete the article if it already exists
132 if ( $wikipage->exists() ) {
133 $wikipage->doDeleteArticle( "done" );
134 }
135
136 $content = ContentHandler::makeContent( $text, $title, $model );
137 $wikipage->doEditContent( $content, __METHOD__, EDIT_NEW );
138
139 return $wikipage;
140 }
141
142 private function assertRevEquals( Revision $orig, Revision $rev = null ) {
143 $this->assertNotNull( $rev, 'missing revision' );
144
145 $this->assertEquals( $orig->getId(), $rev->getId() );
146 $this->assertEquals( $orig->getPage(), $rev->getPage() );
147 $this->assertEquals( $orig->getTimestamp(), $rev->getTimestamp() );
148 $this->assertEquals( $orig->getUser(), $rev->getUser() );
149 $this->assertEquals( $orig->getContentModel(), $rev->getContentModel() );
150 $this->assertEquals( $orig->getContentFormat(), $rev->getContentFormat() );
151 $this->assertEquals( $orig->getSha1(), $rev->getSha1() );
152 }
153
154 /**
155 * @covers Revision::__construct
156 */
157 public function testConstructFromRow() {
158 $latestRevisionId = $this->testPage->getLatest();
159 $latestRevision = $this->testPage->getRevision();
160
161 $dbr = wfGetDB( DB_REPLICA );
162 $res = $dbr->select(
163 'revision',
164 Revision::selectFields(),
165 [ 'rev_id' => $latestRevisionId ]
166 );
167 $this->assertTrue( is_object( $res ), 'query failed' );
168
169 $row = $res->fetchObject();
170 $res->free();
171
172 $this->assertRevEquals( $latestRevision, new Revision( $row ) );
173 }
174
175 /**
176 * @covers Revision::newFromTitle
177 */
178 public function testNewFromTitle_withoutId() {
179 $latestRevId = $this->testPage->getLatest();
180
181 $rev = Revision::newFromTitle( $this->testPage->getTitle() );
182
183 $this->assertTrue( $this->testPage->getTitle()->equals( $rev->getTitle() ) );
184 $this->assertEquals( $latestRevId, $rev->getId() );
185 }
186
187 /**
188 * @covers Revision::newFromTitle
189 */
190 public function testNewFromTitle_withId() {
191 $latestRevId = $this->testPage->getLatest();
192
193 $rev = Revision::newFromTitle( $this->testPage->getTitle(), $latestRevId );
194
195 $this->assertTrue( $this->testPage->getTitle()->equals( $rev->getTitle() ) );
196 $this->assertEquals( $latestRevId, $rev->getId() );
197 }
198
199 /**
200 * @covers Revision::newFromTitle
201 */
202 public function testNewFromTitle_withBadId() {
203 $latestRevId = $this->testPage->getLatest();
204
205 $rev = Revision::newFromTitle( $this->testPage->getTitle(), $latestRevId + 1 );
206
207 $this->assertNull( $rev );
208 }
209
210 /**
211 * @covers Revision::newFromRow
212 */
213 public function testNewFromRow() {
214 $orig = $this->makeRevisionWithProps();
215
216 $dbr = wfGetDB( DB_REPLICA );
217 $res = $dbr->select( 'revision', Revision::selectFields(), [ 'rev_id' => $orig->getId() ] );
218 $this->assertTrue( is_object( $res ), 'query failed' );
219
220 $row = $res->fetchObject();
221 $res->free();
222
223 $rev = Revision::newFromRow( $row );
224
225 $this->assertRevEquals( $orig, $rev );
226 }
227
228 public function provideNewFromArchiveRow() {
229 yield [
230 true,
231 function ( $f ) {
232 return $f;
233 },
234 ];
235 yield [
236 false,
237 function ( $f ) {
238 return $f;
239 },
240 ];
241 yield [
242 true,
243 function ( $f ) {
244 return $f + [ 'ar_namespace', 'ar_title' ];
245 },
246 ];
247 yield [
248 false,
249 function ( $f ) {
250 return $f + [ 'ar_namespace', 'ar_title' ];
251 },
252 ];
253 yield [
254 true,
255 function ( $f ) {
256 unset( $f['ar_text_id'] );
257 return $f;
258 },
259 ];
260 yield [
261 false,
262 function ( $f ) {
263 unset( $f['ar_text_id'] );
264 return $f;
265 },
266 ];
267 }
268
269 /**
270 * @dataProvider provideNewFromArchiveRow
271 * @covers Revision::newFromArchiveRow
272 */
273 public function testNewFromArchiveRow( $contentHandlerUseDB, $selectModifier ) {
274 $this->setMwGlobals( 'wgContentHandlerUseDB', $contentHandlerUseDB );
275
276 $page = $this->createPage(
277 'RevisionStorageTest_testNewFromArchiveRow',
278 'Lorem Ipsum',
279 CONTENT_MODEL_WIKITEXT
280 );
281 $orig = $page->getRevision();
282 $page->doDeleteArticle( 'test Revision::newFromArchiveRow' );
283
284 $dbr = wfGetDB( DB_REPLICA );
285 $selectFields = $selectModifier( Revision::selectArchiveFields() );
286 $res = $dbr->select(
287 'archive', $selectFields, [ 'ar_rev_id' => $orig->getId() ]
288 );
289 $this->assertTrue( is_object( $res ), 'query failed' );
290
291 $row = $res->fetchObject();
292 $res->free();
293
294 $rev = Revision::newFromArchiveRow( $row );
295
296 $this->assertRevEquals( $orig, $rev );
297 }
298
299 /**
300 * @covers Revision::newFromArchiveRow
301 */
302 public function testNewFromArchiveRowOverrides() {
303 $page = $this->createPage(
304 'RevisionStorageTest_testNewFromArchiveRow',
305 'Lorem Ipsum',
306 CONTENT_MODEL_WIKITEXT
307 );
308 $orig = $page->getRevision();
309 $page->doDeleteArticle( 'test Revision::newFromArchiveRow' );
310
311 $dbr = wfGetDB( DB_REPLICA );
312 $res = $dbr->select(
313 'archive', Revision::selectArchiveFields(), [ 'ar_rev_id' => $orig->getId() ]
314 );
315 $this->assertTrue( is_object( $res ), 'query failed' );
316
317 $row = $res->fetchObject();
318 $res->free();
319
320 $rev = Revision::newFromArchiveRow( $row, [ 'comment' => 'SOMEOVERRIDE' ] );
321
322 $this->assertNotEquals( $orig->getComment(), $rev->getComment() );
323 $this->assertEquals( 'SOMEOVERRIDE', $rev->getComment() );
324 }
325
326 /**
327 * @covers Revision::newFromId
328 */
329 public function testNewFromId() {
330 $orig = $this->testPage->getRevision();
331 $rev = Revision::newFromId( $orig->getId() );
332 $this->assertRevEquals( $orig, $rev );
333 }
334
335 /**
336 * @covers Revision::newFromPageId
337 */
338 public function testNewFromPageId() {
339 $rev = Revision::newFromPageId( $this->testPage->getId() );
340 $this->assertRevEquals(
341 $this->testPage->getRevision(),
342 $rev
343 );
344 }
345
346 /**
347 * @covers Revision::newFromPageId
348 */
349 public function testNewFromPageIdWithLatestId() {
350 $rev = Revision::newFromPageId(
351 $this->testPage->getId(),
352 $this->testPage->getLatest()
353 );
354 $this->assertRevEquals(
355 $this->testPage->getRevision(),
356 $rev
357 );
358 }
359
360 /**
361 * @covers Revision::newFromPageId
362 */
363 public function testNewFromPageIdWithNotLatestId() {
364 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
365 $rev = Revision::newFromPageId(
366 $this->testPage->getId(),
367 $this->testPage->getRevision()->getPrevious()->getId()
368 );
369 $this->assertRevEquals(
370 $this->testPage->getRevision()->getPrevious(),
371 $rev
372 );
373 }
374
375 /**
376 * @covers Revision::fetchRevision
377 */
378 public function testFetchRevision() {
379 // Hidden process cache assertion below
380 $this->testPage->getRevision()->getId();
381
382 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
383 $id = $this->testPage->getRevision()->getId();
384
385 $res = Revision::fetchRevision( $this->testPage->getTitle() );
386
387 # note: order is unspecified
388 $rows = [];
389 while ( ( $row = $res->fetchObject() ) ) {
390 $rows[$row->rev_id] = $row;
391 }
392
393 $this->assertEquals( 1, count( $rows ), 'expected exactly one revision' );
394 $this->assertArrayHasKey( $id, $rows, 'missing revision with id ' . $id );
395 }
396
397 /**
398 * @covers Revision::getPage
399 */
400 public function testGetPage() {
401 $page = $this->testPage;
402
403 $orig = $this->makeRevisionWithProps( [ 'page' => $page->getId() ] );
404 $rev = Revision::newFromId( $orig->getId() );
405
406 $this->assertEquals( $page->getId(), $rev->getPage() );
407 }
408
409 /**
410 * @covers Revision::isCurrent
411 */
412 public function testIsCurrent() {
413 $rev1 = $this->testPage->getRevision();
414
415 # @todo find out if this should be true
416 # $this->assertTrue( $rev1->isCurrent() );
417
418 $rev1x = Revision::newFromId( $rev1->getId() );
419 $this->assertTrue( $rev1x->isCurrent() );
420
421 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
422 $rev2 = $this->testPage->getRevision();
423
424 # @todo find out if this should be true
425 # $this->assertTrue( $rev2->isCurrent() );
426
427 $rev1x = Revision::newFromId( $rev1->getId() );
428 $this->assertFalse( $rev1x->isCurrent() );
429
430 $rev2x = Revision::newFromId( $rev2->getId() );
431 $this->assertTrue( $rev2x->isCurrent() );
432 }
433
434 /**
435 * @covers Revision::getPrevious
436 */
437 public function testGetPrevious() {
438 $oldestRevision = $this->testPage->getOldestRevision();
439 $latestRevision = $this->testPage->getLatest();
440
441 $this->assertNull( $oldestRevision->getPrevious() );
442
443 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
444 $newRevision = $this->testPage->getRevision();
445
446 $this->assertNotNull( $newRevision->getPrevious() );
447 $this->assertEquals( $latestRevision, $newRevision->getPrevious()->getId() );
448 }
449
450 /**
451 * @covers Revision::getNext
452 */
453 public function testGetNext() {
454 $rev1 = $this->testPage->getRevision();
455
456 $this->assertNull( $rev1->getNext() );
457
458 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
459 $rev2 = $this->testPage->getRevision();
460
461 $this->assertNotNull( $rev1->getNext() );
462 $this->assertEquals( $rev2->getId(), $rev1->getNext()->getId() );
463 }
464
465 /**
466 * @covers Revision::newNullRevision
467 */
468 public function testNewNullRevision() {
469 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
470 $orig = $this->testPage->getRevision();
471
472 $dbw = wfGetDB( DB_MASTER );
473 $rev = Revision::newNullRevision( $dbw, $this->testPage->getId(), 'a null revision', false );
474
475 $this->assertNotEquals( $orig->getId(), $rev->getId(),
476 'new null revision should have a different id from the original revision' );
477 $this->assertEquals( $orig->getTextId(), $rev->getTextId(),
478 'new null revision should have the same text id as the original revision' );
479 $this->assertEquals( __METHOD__, $rev->getContent()->getNativeData() );
480 }
481
482 /**
483 * @covers Revision::insertOn
484 */
485 public function testInsertOn() {
486 $ip = '2600:387:ed7:947e:8c16:a1ad:dd34:1dd7';
487
488 $orig = $this->makeRevisionWithProps( [
489 'user_text' => $ip
490 ] );
491
492 // Make sure the revision was copied to ip_changes
493 $dbr = wfGetDB( DB_REPLICA );
494 $res = $dbr->select( 'ip_changes', '*', [ 'ipc_rev_id' => $orig->getId() ] );
495 $row = $res->fetchObject();
496
497 $this->assertEquals( IP::toHex( $ip ), $row->ipc_hex );
498 $this->assertEquals( $orig->getTimestamp(), $row->ipc_rev_timestamp );
499 }
500
501 public static function provideUserWasLastToEdit() {
502 yield 'actually the last edit' => [ 3, true ];
503 yield 'not the current edit, but still by this user' => [ 2, true ];
504 yield 'edit by another user' => [ 1, false ];
505 yield 'first edit, by this user, but another user edited in the mean time' => [ 0, false ];
506 }
507
508 /**
509 * @dataProvider provideUserWasLastToEdit
510 */
511 public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) {
512 $userA = User::newFromName( "RevisionStorageTest_userA" );
513 $userB = User::newFromName( "RevisionStorageTest_userB" );
514
515 if ( $userA->getId() === 0 ) {
516 $userA = User::createNew( $userA->getName() );
517 }
518
519 if ( $userB->getId() === 0 ) {
520 $userB = User::createNew( $userB->getName() );
521 }
522
523 $ns = $this->getDefaultWikitextNS();
524
525 $dbw = wfGetDB( DB_MASTER );
526 $revisions = [];
527
528 // create revisions -----------------------------
529 $page = WikiPage::factory( Title::newFromText(
530 'RevisionStorageTest_testUserWasLastToEdit', $ns ) );
531 $page->insertOn( $dbw );
532
533 $revisions[0] = new Revision( [
534 'page' => $page->getId(),
535 // we need the title to determine the page's default content model
536 'title' => $page->getTitle(),
537 'timestamp' => '20120101000000',
538 'user' => $userA->getId(),
539 'text' => 'zero',
540 'content_model' => CONTENT_MODEL_WIKITEXT,
541 'summary' => 'edit zero'
542 ] );
543 $revisions[0]->insertOn( $dbw );
544
545 $revisions[1] = new Revision( [
546 'page' => $page->getId(),
547 // still need the title, because $page->getId() is 0 (there's no entry in the page table)
548 'title' => $page->getTitle(),
549 'timestamp' => '20120101000100',
550 'user' => $userA->getId(),
551 'text' => 'one',
552 'content_model' => CONTENT_MODEL_WIKITEXT,
553 'summary' => 'edit one'
554 ] );
555 $revisions[1]->insertOn( $dbw );
556
557 $revisions[2] = new Revision( [
558 'page' => $page->getId(),
559 'title' => $page->getTitle(),
560 'timestamp' => '20120101000200',
561 'user' => $userB->getId(),
562 'text' => 'two',
563 'content_model' => CONTENT_MODEL_WIKITEXT,
564 'summary' => 'edit two'
565 ] );
566 $revisions[2]->insertOn( $dbw );
567
568 $revisions[3] = new Revision( [
569 'page' => $page->getId(),
570 'title' => $page->getTitle(),
571 'timestamp' => '20120101000300',
572 'user' => $userA->getId(),
573 'text' => 'three',
574 'content_model' => CONTENT_MODEL_WIKITEXT,
575 'summary' => 'edit three'
576 ] );
577 $revisions[3]->insertOn( $dbw );
578
579 $revisions[4] = new Revision( [
580 'page' => $page->getId(),
581 'title' => $page->getTitle(),
582 'timestamp' => '20120101000200',
583 'user' => $userA->getId(),
584 'text' => 'zero',
585 'content_model' => CONTENT_MODEL_WIKITEXT,
586 'summary' => 'edit four'
587 ] );
588 $revisions[4]->insertOn( $dbw );
589
590 // test it ---------------------------------
591 $since = $revisions[$sinceIdx]->getTimestamp();
592
593 $wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
594
595 $this->assertEquals( $expectedLast, $wasLast );
596 }
597
598 /**
599 * @param string $text
600 * @param string $title
601 * @param string $model
602 * @param string $format
603 *
604 * @return Revision
605 */
606 private function newTestRevision( $text, $title = "Test",
607 $model = CONTENT_MODEL_WIKITEXT, $format = null
608 ) {
609 if ( is_string( $title ) ) {
610 $title = Title::newFromText( $title );
611 }
612
613 $content = ContentHandler::makeContent( $text, $title, $model, $format );
614
615 $rev = new Revision(
616 [
617 'id' => 42,
618 'page' => 23,
619 'title' => $title,
620
621 'content' => $content,
622 'length' => $content->getSize(),
623 'comment' => "testing",
624 'minor_edit' => false,
625
626 'content_format' => $format,
627 ]
628 );
629
630 return $rev;
631 }
632
633 public function provideGetContentModel() {
634 // NOTE: we expect the help namespace to always contain wikitext
635 return [
636 [ 'hello world', 'Help:Hello', null, null, CONTENT_MODEL_WIKITEXT ],
637 [ 'hello world', 'User:hello/there.css', null, null, CONTENT_MODEL_CSS ],
638 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentForTesting::MODEL_ID ],
639 ];
640 }
641
642 /**
643 * @dataProvider provideGetContentModel
644 * @covers Revision::getContentModel
645 */
646 public function testGetContentModel( $text, $title, $model, $format, $expectedModel ) {
647 $rev = $this->newTestRevision( $text, $title, $model, $format );
648
649 $this->assertEquals( $expectedModel, $rev->getContentModel() );
650 }
651
652 public function provideGetContentFormat() {
653 // NOTE: we expect the help namespace to always contain wikitext
654 return [
655 [ 'hello world', 'Help:Hello', null, null, CONTENT_FORMAT_WIKITEXT ],
656 [ 'hello world', 'Help:Hello', CONTENT_MODEL_CSS, null, CONTENT_FORMAT_CSS ],
657 [ 'hello world', 'User:hello/there.css', null, null, CONTENT_FORMAT_CSS ],
658 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentForTesting::MODEL_ID ],
659 ];
660 }
661
662 /**
663 * @dataProvider provideGetContentFormat
664 * @covers Revision::getContentFormat
665 */
666 public function testGetContentFormat( $text, $title, $model, $format, $expectedFormat ) {
667 $rev = $this->newTestRevision( $text, $title, $model, $format );
668
669 $this->assertEquals( $expectedFormat, $rev->getContentFormat() );
670 }
671
672 public function provideGetContentHandler() {
673 // NOTE: we expect the help namespace to always contain wikitext
674 return [
675 [ 'hello world', 'Help:Hello', null, null, 'WikitextContentHandler' ],
676 [ 'hello world', 'User:hello/there.css', null, null, 'CssContentHandler' ],
677 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, 'DummyContentHandlerForTesting' ],
678 ];
679 }
680
681 /**
682 * @dataProvider provideGetContentHandler
683 * @covers Revision::getContentHandler
684 */
685 public function testGetContentHandler( $text, $title, $model, $format, $expectedClass ) {
686 $rev = $this->newTestRevision( $text, $title, $model, $format );
687
688 $this->assertEquals( $expectedClass, get_class( $rev->getContentHandler() ) );
689 }
690
691 public function provideGetContent() {
692 // NOTE: we expect the help namespace to always contain wikitext
693 return [
694 [ 'hello world', 'Help:Hello', null, null, Revision::FOR_PUBLIC, 'hello world' ],
695 [
696 serialize( 'hello world' ),
697 'Hello',
698 DummyContentForTesting::MODEL_ID,
699 null,
700 Revision::FOR_PUBLIC,
701 serialize( 'hello world' )
702 ],
703 [
704 serialize( 'hello world' ),
705 'Dummy:Hello',
706 null,
707 null,
708 Revision::FOR_PUBLIC,
709 serialize( 'hello world' )
710 ],
711 ];
712 }
713
714 /**
715 * @dataProvider provideGetContent
716 * @covers Revision::getContent
717 */
718 public function testGetContent( $text, $title, $model, $format,
719 $audience, $expectedSerialization
720 ) {
721 $rev = $this->newTestRevision( $text, $title, $model, $format );
722 $content = $rev->getContent( $audience );
723
724 $this->assertEquals(
725 $expectedSerialization,
726 is_null( $content ) ? null : $content->serialize( $format )
727 );
728 }
729
730 /**
731 * @covers Revision::getContent
732 */
733 public function testGetContent_failure() {
734 $rev = new Revision( [
735 'page' => $this->testPage->getId(),
736 'content_model' => $this->testPage->getContentModel(),
737 'text_id' => 123456789, // not in the test DB
738 ] );
739
740 $this->assertNull( $rev->getContent(),
741 "getContent() should return null if the revision's text blob could not be loaded." );
742
743 // NOTE: check this twice, once for lazy initialization, and once with the cached value.
744 $this->assertNull( $rev->getContent(),
745 "getContent() should return null if the revision's text blob could not be loaded." );
746 }
747
748 public function provideGetSize() {
749 return [
750 [ "hello world.", CONTENT_MODEL_WIKITEXT, 12 ],
751 [ serialize( "hello world." ), DummyContentForTesting::MODEL_ID, 12 ],
752 ];
753 }
754
755 /**
756 * @covers Revision::getSize
757 * @dataProvider provideGetSize
758 */
759 public function testGetSize( $text, $model, $expected_size ) {
760 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSize', $model );
761 $this->assertEquals( $expected_size, $rev->getSize() );
762 }
763
764 public function provideGetSha1() {
765 return [
766 [ "hello world.", CONTENT_MODEL_WIKITEXT, Revision::base36Sha1( "hello world." ) ],
767 [
768 serialize( "hello world." ),
769 DummyContentForTesting::MODEL_ID,
770 Revision::base36Sha1( serialize( "hello world." ) )
771 ],
772 ];
773 }
774
775 /**
776 * @covers Revision::getSha1
777 * @dataProvider provideGetSha1
778 */
779 public function testGetSha1( $text, $model, $expected_hash ) {
780 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSha1', $model );
781 $this->assertEquals( $expected_hash, $rev->getSha1() );
782 }
783
784 /**
785 * Tests whether $rev->getContent() returns a clone when needed.
786 *
787 * @covers Revision::getContent
788 */
789 public function testGetContentClone() {
790 $content = new RevisionTestModifyableContent( "foo" );
791
792 $rev = new Revision(
793 [
794 'id' => 42,
795 'page' => 23,
796 'title' => Title::newFromText( "testGetContentClone_dummy" ),
797
798 'content' => $content,
799 'length' => $content->getSize(),
800 'comment' => "testing",
801 'minor_edit' => false,
802 ]
803 );
804
805 /** @var RevisionTestModifyableContent $content */
806 $content = $rev->getContent( Revision::RAW );
807 $content->setText( "bar" );
808
809 /** @var RevisionTestModifyableContent $content2 */
810 $content2 = $rev->getContent( Revision::RAW );
811 // content is mutable, expect clone
812 $this->assertNotSame( $content, $content2, "expected a clone" );
813 // clone should contain the original text
814 $this->assertEquals( "foo", $content2->getText() );
815
816 $content2->setText( "bla bla" );
817 // clones should be independent
818 $this->assertEquals( "bar", $content->getText() );
819 }
820
821 /**
822 * Tests whether $rev->getContent() returns the same object repeatedly if appropriate.
823 * @covers Revision::getContent
824 */
825 public function testGetContentUncloned() {
826 $rev = $this->newTestRevision( "hello", "testGetContentUncloned_dummy", CONTENT_MODEL_WIKITEXT );
827 $content = $rev->getContent( Revision::RAW );
828 $content2 = $rev->getContent( Revision::RAW );
829
830 // for immutable content like wikitext, this should be the same object
831 $this->assertSame( $content, $content2 );
832 }
833
834 /**
835 * @covers Revision::loadFromId
836 */
837 public function testLoadFromId() {
838 $rev = $this->testPage->getRevision();
839 $this->assertRevEquals(
840 $rev,
841 Revision::loadFromId( wfGetDB( DB_MASTER ), $rev->getId() )
842 );
843 }
844
845 /**
846 * @covers Revision::loadFromPageId
847 */
848 public function testLoadFromPageId() {
849 $this->assertRevEquals(
850 $this->testPage->getRevision(),
851 Revision::loadFromPageId( wfGetDB( DB_MASTER ), $this->testPage->getId() )
852 );
853 }
854
855 /**
856 * @covers Revision::loadFromPageId
857 */
858 public function testLoadFromPageIdWithLatestRevId() {
859 $this->assertRevEquals(
860 $this->testPage->getRevision(),
861 Revision::loadFromPageId(
862 wfGetDB( DB_MASTER ),
863 $this->testPage->getId(),
864 $this->testPage->getLatest()
865 )
866 );
867 }
868
869 /**
870 * @covers Revision::loadFromPageId
871 */
872 public function testLoadFromPageIdWithNotLatestRevId() {
873 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
874 $this->assertRevEquals(
875 $this->testPage->getRevision()->getPrevious(),
876 Revision::loadFromPageId(
877 wfGetDB( DB_MASTER ),
878 $this->testPage->getId(),
879 $this->testPage->getRevision()->getPrevious()->getId()
880 )
881 );
882 }
883
884 /**
885 * @covers Revision::loadFromTitle
886 */
887 public function testLoadFromTitle() {
888 $this->assertRevEquals(
889 $this->testPage->getRevision(),
890 Revision::loadFromTitle( wfGetDB( DB_MASTER ), $this->testPage->getTitle() )
891 );
892 }
893
894 /**
895 * @covers Revision::loadFromTitle
896 */
897 public function testLoadFromTitleWithLatestRevId() {
898 $this->assertRevEquals(
899 $this->testPage->getRevision(),
900 Revision::loadFromTitle(
901 wfGetDB( DB_MASTER ),
902 $this->testPage->getTitle(),
903 $this->testPage->getLatest()
904 )
905 );
906 }
907
908 /**
909 * @covers Revision::loadFromTitle
910 */
911 public function testLoadFromTitleWithNotLatestRevId() {
912 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
913 $this->assertRevEquals(
914 $this->testPage->getRevision()->getPrevious(),
915 Revision::loadFromTitle(
916 wfGetDB( DB_MASTER ),
917 $this->testPage->getTitle(),
918 $this->testPage->getRevision()->getPrevious()->getId()
919 )
920 );
921 }
922
923 /**
924 * @covers Revision::loadFromTimestamp()
925 */
926 public function testLoadFromTimestamp() {
927 $this->assertRevEquals(
928 $this->testPage->getRevision(),
929 Revision::loadFromTimestamp(
930 wfGetDB( DB_MASTER ),
931 $this->testPage->getTitle(),
932 $this->testPage->getRevision()->getTimestamp()
933 )
934 );
935 }
936
937 }