Merge "Cleanup page creation in RevisionIntegrationTest"
[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 /**
229 * @covers Revision::newFromArchiveRow
230 */
231 public function testNewFromArchiveRow() {
232 $page = $this->createPage(
233 'RevisionStorageTest_testNewFromArchiveRow',
234 'Lorem Ipsum',
235 CONTENT_MODEL_WIKITEXT
236 );
237 $orig = $page->getRevision();
238 $page->doDeleteArticle( 'test Revision::newFromArchiveRow' );
239
240 $dbr = wfGetDB( DB_REPLICA );
241 $res = $dbr->select(
242 'archive', Revision::selectArchiveFields(), [ 'ar_rev_id' => $orig->getId() ]
243 );
244 $this->assertTrue( is_object( $res ), 'query failed' );
245
246 $row = $res->fetchObject();
247 $res->free();
248
249 $rev = Revision::newFromArchiveRow( $row );
250
251 $this->assertRevEquals( $orig, $rev );
252 }
253
254 /**
255 * @covers Revision::newFromId
256 */
257 public function testNewFromId() {
258 $orig = $this->testPage->getRevision();
259 $rev = Revision::newFromId( $orig->getId() );
260 $this->assertRevEquals( $orig, $rev );
261 }
262
263 /**
264 * @covers Revision::fetchRevision
265 */
266 public function testFetchRevision() {
267 // Hidden process cache assertion below
268 $this->testPage->getRevision()->getId();
269
270 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
271 $id = $this->testPage->getRevision()->getId();
272
273 $res = Revision::fetchRevision( $this->testPage->getTitle() );
274
275 # note: order is unspecified
276 $rows = [];
277 while ( ( $row = $res->fetchObject() ) ) {
278 $rows[$row->rev_id] = $row;
279 }
280
281 $this->assertEquals( 1, count( $rows ), 'expected exactly one revision' );
282 $this->assertArrayHasKey( $id, $rows, 'missing revision with id ' . $id );
283 }
284
285 /**
286 * @covers Revision::selectFields
287 */
288 public function testSelectFields() {
289 global $wgContentHandlerUseDB;
290
291 $fields = Revision::selectFields();
292
293 $this->assertTrue( in_array( 'rev_id', $fields ), 'missing rev_id in list of fields' );
294 $this->assertTrue( in_array( 'rev_page', $fields ), 'missing rev_page in list of fields' );
295 $this->assertTrue(
296 in_array( 'rev_timestamp', $fields ),
297 'missing rev_timestamp in list of fields'
298 );
299 $this->assertTrue( in_array( 'rev_user', $fields ), 'missing rev_user in list of fields' );
300
301 if ( $wgContentHandlerUseDB ) {
302 $this->assertTrue( in_array( 'rev_content_model', $fields ),
303 'missing rev_content_model in list of fields' );
304 $this->assertTrue( in_array( 'rev_content_format', $fields ),
305 'missing rev_content_format in list of fields' );
306 }
307 }
308
309 /**
310 * @covers Revision::getPage
311 */
312 public function testGetPage() {
313 $page = $this->testPage;
314
315 $orig = $this->makeRevisionWithProps( [ 'page' => $page->getId() ] );
316 $rev = Revision::newFromId( $orig->getId() );
317
318 $this->assertEquals( $page->getId(), $rev->getPage() );
319 }
320
321 /**
322 * @covers Revision::isCurrent
323 */
324 public function testIsCurrent() {
325 $rev1 = $this->testPage->getRevision();
326
327 # @todo find out if this should be true
328 # $this->assertTrue( $rev1->isCurrent() );
329
330 $rev1x = Revision::newFromId( $rev1->getId() );
331 $this->assertTrue( $rev1x->isCurrent() );
332
333 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
334 $rev2 = $this->testPage->getRevision();
335
336 # @todo find out if this should be true
337 # $this->assertTrue( $rev2->isCurrent() );
338
339 $rev1x = Revision::newFromId( $rev1->getId() );
340 $this->assertFalse( $rev1x->isCurrent() );
341
342 $rev2x = Revision::newFromId( $rev2->getId() );
343 $this->assertTrue( $rev2x->isCurrent() );
344 }
345
346 /**
347 * @covers Revision::getPrevious
348 */
349 public function testGetPrevious() {
350 $oldestRevision = $this->testPage->getOldestRevision();
351 $latestRevision = $this->testPage->getLatest();
352
353 $this->assertNull( $oldestRevision->getPrevious() );
354
355 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
356 $newRevision = $this->testPage->getRevision();
357
358 $this->assertNotNull( $newRevision->getPrevious() );
359 $this->assertEquals( $latestRevision, $newRevision->getPrevious()->getId() );
360 }
361
362 /**
363 * @covers Revision::getNext
364 */
365 public function testGetNext() {
366 $rev1 = $this->testPage->getRevision();
367
368 $this->assertNull( $rev1->getNext() );
369
370 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
371 $rev2 = $this->testPage->getRevision();
372
373 $this->assertNotNull( $rev1->getNext() );
374 $this->assertEquals( $rev2->getId(), $rev1->getNext()->getId() );
375 }
376
377 /**
378 * @covers Revision::newNullRevision
379 */
380 public function testNewNullRevision() {
381 $this->testPage->doEditContent( new WikitextContent( __METHOD__ ), __METHOD__ );
382 $orig = $this->testPage->getRevision();
383
384 $dbw = wfGetDB( DB_MASTER );
385 $rev = Revision::newNullRevision( $dbw, $this->testPage->getId(), 'a null revision', false );
386
387 $this->assertNotEquals( $orig->getId(), $rev->getId(),
388 'new null revision should have a different id from the original revision' );
389 $this->assertEquals( $orig->getTextId(), $rev->getTextId(),
390 'new null revision should have the same text id as the original revision' );
391 $this->assertEquals( __METHOD__, $rev->getContent()->getNativeData() );
392 }
393
394 /**
395 * @covers Revision::insertOn
396 */
397 public function testInsertOn() {
398 $ip = '2600:387:ed7:947e:8c16:a1ad:dd34:1dd7';
399
400 $orig = $this->makeRevisionWithProps( [
401 'user_text' => $ip
402 ] );
403
404 // Make sure the revision was copied to ip_changes
405 $dbr = wfGetDB( DB_REPLICA );
406 $res = $dbr->select( 'ip_changes', '*', [ 'ipc_rev_id' => $orig->getId() ] );
407 $row = $res->fetchObject();
408
409 $this->assertEquals( IP::toHex( $ip ), $row->ipc_hex );
410 $this->assertEquals( $orig->getTimestamp(), $row->ipc_rev_timestamp );
411 }
412
413 public static function provideUserWasLastToEdit() {
414 yield 'actually the last edit' => [ 3, true ];
415 yield 'not the current edit, but still by this user' => [ 2, true ];
416 yield 'edit by another user' => [ 1, false ];
417 yield 'first edit, by this user, but another user edited in the mean time' => [ 0, false ];
418 }
419
420 /**
421 * @dataProvider provideUserWasLastToEdit
422 */
423 public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) {
424 $userA = User::newFromName( "RevisionStorageTest_userA" );
425 $userB = User::newFromName( "RevisionStorageTest_userB" );
426
427 if ( $userA->getId() === 0 ) {
428 $userA = User::createNew( $userA->getName() );
429 }
430
431 if ( $userB->getId() === 0 ) {
432 $userB = User::createNew( $userB->getName() );
433 }
434
435 $ns = $this->getDefaultWikitextNS();
436
437 $dbw = wfGetDB( DB_MASTER );
438 $revisions = [];
439
440 // create revisions -----------------------------
441 $page = WikiPage::factory( Title::newFromText(
442 'RevisionStorageTest_testUserWasLastToEdit', $ns ) );
443 $page->insertOn( $dbw );
444
445 $revisions[0] = new Revision( [
446 'page' => $page->getId(),
447 // we need the title to determine the page's default content model
448 'title' => $page->getTitle(),
449 'timestamp' => '20120101000000',
450 'user' => $userA->getId(),
451 'text' => 'zero',
452 'content_model' => CONTENT_MODEL_WIKITEXT,
453 'summary' => 'edit zero'
454 ] );
455 $revisions[0]->insertOn( $dbw );
456
457 $revisions[1] = new Revision( [
458 'page' => $page->getId(),
459 // still need the title, because $page->getId() is 0 (there's no entry in the page table)
460 'title' => $page->getTitle(),
461 'timestamp' => '20120101000100',
462 'user' => $userA->getId(),
463 'text' => 'one',
464 'content_model' => CONTENT_MODEL_WIKITEXT,
465 'summary' => 'edit one'
466 ] );
467 $revisions[1]->insertOn( $dbw );
468
469 $revisions[2] = new Revision( [
470 'page' => $page->getId(),
471 'title' => $page->getTitle(),
472 'timestamp' => '20120101000200',
473 'user' => $userB->getId(),
474 'text' => 'two',
475 'content_model' => CONTENT_MODEL_WIKITEXT,
476 'summary' => 'edit two'
477 ] );
478 $revisions[2]->insertOn( $dbw );
479
480 $revisions[3] = new Revision( [
481 'page' => $page->getId(),
482 'title' => $page->getTitle(),
483 'timestamp' => '20120101000300',
484 'user' => $userA->getId(),
485 'text' => 'three',
486 'content_model' => CONTENT_MODEL_WIKITEXT,
487 'summary' => 'edit three'
488 ] );
489 $revisions[3]->insertOn( $dbw );
490
491 $revisions[4] = new Revision( [
492 'page' => $page->getId(),
493 'title' => $page->getTitle(),
494 'timestamp' => '20120101000200',
495 'user' => $userA->getId(),
496 'text' => 'zero',
497 'content_model' => CONTENT_MODEL_WIKITEXT,
498 'summary' => 'edit four'
499 ] );
500 $revisions[4]->insertOn( $dbw );
501
502 // test it ---------------------------------
503 $since = $revisions[$sinceIdx]->getTimestamp();
504
505 $wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
506
507 $this->assertEquals( $expectedLast, $wasLast );
508 }
509
510 /**
511 * @param string $text
512 * @param string $title
513 * @param string $model
514 * @param string $format
515 *
516 * @return Revision
517 */
518 private function newTestRevision( $text, $title = "Test",
519 $model = CONTENT_MODEL_WIKITEXT, $format = null
520 ) {
521 if ( is_string( $title ) ) {
522 $title = Title::newFromText( $title );
523 }
524
525 $content = ContentHandler::makeContent( $text, $title, $model, $format );
526
527 $rev = new Revision(
528 [
529 'id' => 42,
530 'page' => 23,
531 'title' => $title,
532
533 'content' => $content,
534 'length' => $content->getSize(),
535 'comment' => "testing",
536 'minor_edit' => false,
537
538 'content_format' => $format,
539 ]
540 );
541
542 return $rev;
543 }
544
545 public function provideGetContentModel() {
546 // NOTE: we expect the help namespace to always contain wikitext
547 return [
548 [ 'hello world', 'Help:Hello', null, null, CONTENT_MODEL_WIKITEXT ],
549 [ 'hello world', 'User:hello/there.css', null, null, CONTENT_MODEL_CSS ],
550 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentForTesting::MODEL_ID ],
551 ];
552 }
553
554 /**
555 * @dataProvider provideGetContentModel
556 * @covers Revision::getContentModel
557 */
558 public function testGetContentModel( $text, $title, $model, $format, $expectedModel ) {
559 $rev = $this->newTestRevision( $text, $title, $model, $format );
560
561 $this->assertEquals( $expectedModel, $rev->getContentModel() );
562 }
563
564 public function provideGetContentFormat() {
565 // NOTE: we expect the help namespace to always contain wikitext
566 return [
567 [ 'hello world', 'Help:Hello', null, null, CONTENT_FORMAT_WIKITEXT ],
568 [ 'hello world', 'Help:Hello', CONTENT_MODEL_CSS, null, CONTENT_FORMAT_CSS ],
569 [ 'hello world', 'User:hello/there.css', null, null, CONTENT_FORMAT_CSS ],
570 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, DummyContentForTesting::MODEL_ID ],
571 ];
572 }
573
574 /**
575 * @dataProvider provideGetContentFormat
576 * @covers Revision::getContentFormat
577 */
578 public function testGetContentFormat( $text, $title, $model, $format, $expectedFormat ) {
579 $rev = $this->newTestRevision( $text, $title, $model, $format );
580
581 $this->assertEquals( $expectedFormat, $rev->getContentFormat() );
582 }
583
584 public function provideGetContentHandler() {
585 // NOTE: we expect the help namespace to always contain wikitext
586 return [
587 [ 'hello world', 'Help:Hello', null, null, 'WikitextContentHandler' ],
588 [ 'hello world', 'User:hello/there.css', null, null, 'CssContentHandler' ],
589 [ serialize( 'hello world' ), 'Dummy:Hello', null, null, 'DummyContentHandlerForTesting' ],
590 ];
591 }
592
593 /**
594 * @dataProvider provideGetContentHandler
595 * @covers Revision::getContentHandler
596 */
597 public function testGetContentHandler( $text, $title, $model, $format, $expectedClass ) {
598 $rev = $this->newTestRevision( $text, $title, $model, $format );
599
600 $this->assertEquals( $expectedClass, get_class( $rev->getContentHandler() ) );
601 }
602
603 public function provideGetContent() {
604 // NOTE: we expect the help namespace to always contain wikitext
605 return [
606 [ 'hello world', 'Help:Hello', null, null, Revision::FOR_PUBLIC, 'hello world' ],
607 [
608 serialize( 'hello world' ),
609 'Hello',
610 DummyContentForTesting::MODEL_ID,
611 null,
612 Revision::FOR_PUBLIC,
613 serialize( 'hello world' )
614 ],
615 [
616 serialize( 'hello world' ),
617 'Dummy:Hello',
618 null,
619 null,
620 Revision::FOR_PUBLIC,
621 serialize( 'hello world' )
622 ],
623 ];
624 }
625
626 /**
627 * @dataProvider provideGetContent
628 * @covers Revision::getContent
629 */
630 public function testGetContent( $text, $title, $model, $format,
631 $audience, $expectedSerialization
632 ) {
633 $rev = $this->newTestRevision( $text, $title, $model, $format );
634 $content = $rev->getContent( $audience );
635
636 $this->assertEquals(
637 $expectedSerialization,
638 is_null( $content ) ? null : $content->serialize( $format )
639 );
640 }
641
642 /**
643 * @covers Revision::getContent
644 */
645 public function testGetContent_failure() {
646 $rev = new Revision( [
647 'page' => $this->testPage->getId(),
648 'content_model' => $this->testPage->getContentModel(),
649 'text_id' => 123456789, // not in the test DB
650 ] );
651
652 $this->assertNull( $rev->getContent(),
653 "getContent() should return null if the revision's text blob could not be loaded." );
654
655 // NOTE: check this twice, once for lazy initialization, and once with the cached value.
656 $this->assertNull( $rev->getContent(),
657 "getContent() should return null if the revision's text blob could not be loaded." );
658 }
659
660 public function provideGetSize() {
661 return [
662 [ "hello world.", CONTENT_MODEL_WIKITEXT, 12 ],
663 [ serialize( "hello world." ), DummyContentForTesting::MODEL_ID, 12 ],
664 ];
665 }
666
667 /**
668 * @covers Revision::getSize
669 * @dataProvider provideGetSize
670 */
671 public function testGetSize( $text, $model, $expected_size ) {
672 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSize', $model );
673 $this->assertEquals( $expected_size, $rev->getSize() );
674 }
675
676 public function provideGetSha1() {
677 return [
678 [ "hello world.", CONTENT_MODEL_WIKITEXT, Revision::base36Sha1( "hello world." ) ],
679 [
680 serialize( "hello world." ),
681 DummyContentForTesting::MODEL_ID,
682 Revision::base36Sha1( serialize( "hello world." ) )
683 ],
684 ];
685 }
686
687 /**
688 * @covers Revision::getSha1
689 * @dataProvider provideGetSha1
690 */
691 public function testGetSha1( $text, $model, $expected_hash ) {
692 $rev = $this->newTestRevision( $text, 'RevisionTest_testGetSha1', $model );
693 $this->assertEquals( $expected_hash, $rev->getSha1() );
694 }
695
696 /**
697 * Tests whether $rev->getContent() returns a clone when needed.
698 *
699 * @covers Revision::getContent
700 */
701 public function testGetContentClone() {
702 $content = new RevisionTestModifyableContent( "foo" );
703
704 $rev = new Revision(
705 [
706 'id' => 42,
707 'page' => 23,
708 'title' => Title::newFromText( "testGetContentClone_dummy" ),
709
710 'content' => $content,
711 'length' => $content->getSize(),
712 'comment' => "testing",
713 'minor_edit' => false,
714 ]
715 );
716
717 /** @var RevisionTestModifyableContent $content */
718 $content = $rev->getContent( Revision::RAW );
719 $content->setText( "bar" );
720
721 /** @var RevisionTestModifyableContent $content2 */
722 $content2 = $rev->getContent( Revision::RAW );
723 // content is mutable, expect clone
724 $this->assertNotSame( $content, $content2, "expected a clone" );
725 // clone should contain the original text
726 $this->assertEquals( "foo", $content2->getText() );
727
728 $content2->setText( "bla bla" );
729 // clones should be independent
730 $this->assertEquals( "bar", $content->getText() );
731 }
732
733 /**
734 * Tests whether $rev->getContent() returns the same object repeatedly if appropriate.
735 * @covers Revision::getContent
736 */
737 public function testGetContentUncloned() {
738 $rev = $this->newTestRevision( "hello", "testGetContentUncloned_dummy", CONTENT_MODEL_WIKITEXT );
739 $content = $rev->getContent( Revision::RAW );
740 $content2 = $rev->getContent( Revision::RAW );
741
742 // for immutable content like wikitext, this should be the same object
743 $this->assertSame( $content, $content2 );
744 }
745
746 }