MediaWiki
REL1_23
|
00001 <?php 00002 00013 class RevisionStorageTest extends MediaWikiTestCase { 00014 00018 var $the_page; 00019 00020 function __construct( $name = null, array $data = array(), $dataName = '' ) { 00021 parent::__construct( $name, $data, $dataName ); 00022 00023 $this->tablesUsed = array_merge( $this->tablesUsed, 00024 array( 'page', 00025 'revision', 00026 'text', 00027 00028 'recentchanges', 00029 'logging', 00030 00031 'page_props', 00032 'pagelinks', 00033 'categorylinks', 00034 'langlinks', 00035 'externallinks', 00036 'imagelinks', 00037 'templatelinks', 00038 'iwlinks' ) ); 00039 } 00040 00041 protected function setUp() { 00042 global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang; 00043 00044 parent::setUp(); 00045 00046 $wgExtraNamespaces[12312] = 'Dummy'; 00047 $wgExtraNamespaces[12313] = 'Dummy_talk'; 00048 00049 $wgNamespaceContentModels[12312] = 'DUMMY'; 00050 $wgContentHandlers['DUMMY'] = 'DummyContentHandlerForTesting'; 00051 00052 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache 00053 $wgContLang->resetNamespaces(); # reset namespace cache 00054 if ( !$this->the_page ) { 00055 $this->the_page = $this->createPage( 'RevisionStorageTest_the_page', "just a dummy page", CONTENT_MODEL_WIKITEXT ); 00056 } 00057 } 00058 00059 protected function tearDown() { 00060 global $wgExtraNamespaces, $wgNamespaceContentModels, $wgContentHandlers, $wgContLang; 00061 00062 parent::tearDown(); 00063 00064 unset( $wgExtraNamespaces[12312] ); 00065 unset( $wgExtraNamespaces[12313] ); 00066 00067 unset( $wgNamespaceContentModels[12312] ); 00068 unset( $wgContentHandlers['DUMMY'] ); 00069 00070 MWNamespace::getCanonicalNamespaces( true ); # reset namespace cache 00071 $wgContLang->resetNamespaces(); # reset namespace cache 00072 } 00073 00074 protected function makeRevision( $props = null ) { 00075 if ( $props === null ) { 00076 $props = array(); 00077 } 00078 00079 if ( !isset( $props['content'] ) && !isset( $props['text'] ) ) { 00080 $props['text'] = 'Lorem Ipsum'; 00081 } 00082 00083 if ( !isset( $props['comment'] ) ) { 00084 $props['comment'] = 'just a test'; 00085 } 00086 00087 if ( !isset( $props['page'] ) ) { 00088 $props['page'] = $this->the_page->getId(); 00089 } 00090 00091 $rev = new Revision( $props ); 00092 00093 $dbw = wfgetDB( DB_MASTER ); 00094 $rev->insertOn( $dbw ); 00095 00096 return $rev; 00097 } 00098 00099 protected function createPage( $page, $text, $model = null ) { 00100 if ( is_string( $page ) ) { 00101 if ( !preg_match( '/:/', $page ) && 00102 ( $model === null || $model === CONTENT_MODEL_WIKITEXT ) 00103 ) { 00104 $ns = $this->getDefaultWikitextNS(); 00105 $page = MWNamespace::getCanonicalName( $ns ) . ':' . $page; 00106 } 00107 00108 $page = Title::newFromText( $page ); 00109 } 00110 00111 if ( $page instanceof Title ) { 00112 $page = new WikiPage( $page ); 00113 } 00114 00115 if ( $page->exists() ) { 00116 $page->doDeleteArticle( "done" ); 00117 } 00118 00119 $content = ContentHandler::makeContent( $text, $page->getTitle(), $model ); 00120 $page->doEditContent( $content, "testing", EDIT_NEW ); 00121 00122 return $page; 00123 } 00124 00125 protected function assertRevEquals( Revision $orig, Revision $rev = null ) { 00126 $this->assertNotNull( $rev, 'missing revision' ); 00127 00128 $this->assertEquals( $orig->getId(), $rev->getId() ); 00129 $this->assertEquals( $orig->getPage(), $rev->getPage() ); 00130 $this->assertEquals( $orig->getTimestamp(), $rev->getTimestamp() ); 00131 $this->assertEquals( $orig->getUser(), $rev->getUser() ); 00132 $this->assertEquals( $orig->getContentModel(), $rev->getContentModel() ); 00133 $this->assertEquals( $orig->getContentFormat(), $rev->getContentFormat() ); 00134 $this->assertEquals( $orig->getSha1(), $rev->getSha1() ); 00135 } 00136 00140 public function testConstructFromRow() { 00141 $orig = $this->makeRevision(); 00142 00143 $dbr = wfgetDB( DB_SLAVE ); 00144 $res = $dbr->select( 'revision', '*', array( 'rev_id' => $orig->getId() ) ); 00145 $this->assertTrue( is_object( $res ), 'query failed' ); 00146 00147 $row = $res->fetchObject(); 00148 $res->free(); 00149 00150 $rev = new Revision( $row ); 00151 00152 $this->assertRevEquals( $orig, $rev ); 00153 } 00154 00158 public function testNewFromRow() { 00159 $orig = $this->makeRevision(); 00160 00161 $dbr = wfgetDB( DB_SLAVE ); 00162 $res = $dbr->select( 'revision', '*', array( 'rev_id' => $orig->getId() ) ); 00163 $this->assertTrue( is_object( $res ), 'query failed' ); 00164 00165 $row = $res->fetchObject(); 00166 $res->free(); 00167 00168 $rev = Revision::newFromRow( $row ); 00169 00170 $this->assertRevEquals( $orig, $rev ); 00171 } 00172 00176 public function testNewFromArchiveRow() { 00177 $page = $this->createPage( 'RevisionStorageTest_testNewFromArchiveRow', 'Lorem Ipsum', CONTENT_MODEL_WIKITEXT ); 00178 $orig = $page->getRevision(); 00179 $page->doDeleteArticle( 'test Revision::newFromArchiveRow' ); 00180 00181 $dbr = wfgetDB( DB_SLAVE ); 00182 $res = $dbr->select( 'archive', '*', array( 'ar_rev_id' => $orig->getId() ) ); 00183 $this->assertTrue( is_object( $res ), 'query failed' ); 00184 00185 $row = $res->fetchObject(); 00186 $res->free(); 00187 00188 $rev = Revision::newFromArchiveRow( $row ); 00189 00190 $this->assertRevEquals( $orig, $rev ); 00191 } 00192 00196 public function testNewFromId() { 00197 $orig = $this->makeRevision(); 00198 00199 $rev = Revision::newFromId( $orig->getId() ); 00200 00201 $this->assertRevEquals( $orig, $rev ); 00202 } 00203 00207 public function testFetchRevision() { 00208 $page = $this->createPage( 'RevisionStorageTest_testFetchRevision', 'one', CONTENT_MODEL_WIKITEXT ); 00209 00210 // Hidden process cache assertion below 00211 $page->getRevision()->getId(); 00212 00213 $page->doEditContent( new WikitextContent( 'two' ), 'second rev' ); 00214 $id = $page->getRevision()->getId(); 00215 00216 $res = Revision::fetchRevision( $page->getTitle() ); 00217 00218 #note: order is unspecified 00219 $rows = array(); 00220 while ( ( $row = $res->fetchObject() ) ) { 00221 $rows[$row->rev_id] = $row; 00222 } 00223 00224 $this->assertEquals( 1, count( $rows ), 'expected exactly one revision' ); 00225 $this->assertArrayHasKey( $id, $rows, 'missing revision with id ' . $id ); 00226 } 00227 00231 public function testSelectFields() { 00232 global $wgContentHandlerUseDB; 00233 00234 $fields = Revision::selectFields(); 00235 00236 $this->assertTrue( in_array( 'rev_id', $fields ), 'missing rev_id in list of fields' ); 00237 $this->assertTrue( in_array( 'rev_page', $fields ), 'missing rev_page in list of fields' ); 00238 $this->assertTrue( in_array( 'rev_timestamp', $fields ), 'missing rev_timestamp in list of fields' ); 00239 $this->assertTrue( in_array( 'rev_user', $fields ), 'missing rev_user in list of fields' ); 00240 00241 if ( $wgContentHandlerUseDB ) { 00242 $this->assertTrue( in_array( 'rev_content_model', $fields ), 00243 'missing rev_content_model in list of fields' ); 00244 $this->assertTrue( in_array( 'rev_content_format', $fields ), 00245 'missing rev_content_format in list of fields' ); 00246 } 00247 } 00248 00252 public function testGetPage() { 00253 $page = $this->the_page; 00254 00255 $orig = $this->makeRevision( array( 'page' => $page->getId() ) ); 00256 $rev = Revision::newFromId( $orig->getId() ); 00257 00258 $this->assertEquals( $page->getId(), $rev->getPage() ); 00259 } 00260 00264 public function testGetText() { 00265 $this->hideDeprecated( 'Revision::getText' ); 00266 00267 $orig = $this->makeRevision( array( 'text' => 'hello hello.' ) ); 00268 $rev = Revision::newFromId( $orig->getId() ); 00269 00270 $this->assertEquals( 'hello hello.', $rev->getText() ); 00271 } 00272 00276 public function testGetContent_failure() { 00277 $rev = new Revision( array( 00278 'page' => $this->the_page->getId(), 00279 'content_model' => $this->the_page->getContentModel(), 00280 'text_id' => 123456789, // not in the test DB 00281 ) ); 00282 00283 $this->assertNull( $rev->getContent(), 00284 "getContent() should return null if the revision's text blob could not be loaded." ); 00285 00286 //NOTE: check this twice, once for lazy initialization, and once with the cached value. 00287 $this->assertNull( $rev->getContent(), 00288 "getContent() should return null if the revision's text blob could not be loaded." ); 00289 } 00290 00294 public function testGetContent() { 00295 $orig = $this->makeRevision( array( 'text' => 'hello hello.' ) ); 00296 $rev = Revision::newFromId( $orig->getId() ); 00297 00298 $this->assertEquals( 'hello hello.', $rev->getContent()->getNativeData() ); 00299 } 00300 00304 public function testGetRawText() { 00305 $this->hideDeprecated( 'Revision::getRawText' ); 00306 00307 $orig = $this->makeRevision( array( 'text' => 'hello hello raw.' ) ); 00308 $rev = Revision::newFromId( $orig->getId() ); 00309 00310 $this->assertEquals( 'hello hello raw.', $rev->getRawText() ); 00311 } 00312 00316 public function testGetContentModel() { 00317 global $wgContentHandlerUseDB; 00318 00319 if ( !$wgContentHandlerUseDB ) { 00320 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' ); 00321 } 00322 00323 $orig = $this->makeRevision( array( 'text' => 'hello hello.', 00324 'content_model' => CONTENT_MODEL_JAVASCRIPT ) ); 00325 $rev = Revision::newFromId( $orig->getId() ); 00326 00327 $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContentModel() ); 00328 } 00329 00333 public function testGetContentFormat() { 00334 global $wgContentHandlerUseDB; 00335 00336 if ( !$wgContentHandlerUseDB ) { 00337 $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' ); 00338 } 00339 00340 $orig = $this->makeRevision( array( 00341 'text' => 'hello hello.', 00342 'content_model' => CONTENT_MODEL_JAVASCRIPT, 00343 'content_format' => CONTENT_FORMAT_JAVASCRIPT 00344 ) ); 00345 $rev = Revision::newFromId( $orig->getId() ); 00346 00347 $this->assertEquals( CONTENT_FORMAT_JAVASCRIPT, $rev->getContentFormat() ); 00348 } 00349 00353 public function testIsCurrent() { 00354 $page = $this->createPage( 'RevisionStorageTest_testIsCurrent', 'Lorem Ipsum', CONTENT_MODEL_WIKITEXT ); 00355 $rev1 = $page->getRevision(); 00356 00357 # @todo find out if this should be true 00358 # $this->assertTrue( $rev1->isCurrent() ); 00359 00360 $rev1x = Revision::newFromId( $rev1->getId() ); 00361 $this->assertTrue( $rev1x->isCurrent() ); 00362 00363 $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ), 'second rev' ); 00364 $rev2 = $page->getRevision(); 00365 00366 # @todo find out if this should be true 00367 # $this->assertTrue( $rev2->isCurrent() ); 00368 00369 $rev1x = Revision::newFromId( $rev1->getId() ); 00370 $this->assertFalse( $rev1x->isCurrent() ); 00371 00372 $rev2x = Revision::newFromId( $rev2->getId() ); 00373 $this->assertTrue( $rev2x->isCurrent() ); 00374 } 00375 00379 public function testGetPrevious() { 00380 $page = $this->createPage( 'RevisionStorageTest_testGetPrevious', 'Lorem Ipsum testGetPrevious', CONTENT_MODEL_WIKITEXT ); 00381 $rev1 = $page->getRevision(); 00382 00383 $this->assertNull( $rev1->getPrevious() ); 00384 00385 $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ), 00386 'second rev testGetPrevious' ); 00387 $rev2 = $page->getRevision(); 00388 00389 $this->assertNotNull( $rev2->getPrevious() ); 00390 $this->assertEquals( $rev1->getId(), $rev2->getPrevious()->getId() ); 00391 } 00392 00396 public function testGetNext() { 00397 $page = $this->createPage( 'RevisionStorageTest_testGetNext', 'Lorem Ipsum testGetNext', CONTENT_MODEL_WIKITEXT ); 00398 $rev1 = $page->getRevision(); 00399 00400 $this->assertNull( $rev1->getNext() ); 00401 00402 $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ), 00403 'second rev testGetNext' ); 00404 $rev2 = $page->getRevision(); 00405 00406 $this->assertNotNull( $rev1->getNext() ); 00407 $this->assertEquals( $rev2->getId(), $rev1->getNext()->getId() ); 00408 } 00409 00413 public function testNewNullRevision() { 00414 $page = $this->createPage( 'RevisionStorageTest_testNewNullRevision', 'some testing text', CONTENT_MODEL_WIKITEXT ); 00415 $orig = $page->getRevision(); 00416 00417 $dbw = wfGetDB( DB_MASTER ); 00418 $rev = Revision::newNullRevision( $dbw, $page->getId(), 'a null revision', false ); 00419 00420 $this->assertNotEquals( $orig->getId(), $rev->getId(), 00421 'new null revision shold have a different id from the original revision' ); 00422 $this->assertEquals( $orig->getTextId(), $rev->getTextId(), 00423 'new null revision shold have the same text id as the original revision' ); 00424 $this->assertEquals( 'some testing text', $rev->getContent()->getNativeData() ); 00425 } 00426 00427 public static function provideUserWasLastToEdit() { 00428 return array( 00429 array( #0 00430 3, true, # actually the last edit 00431 ), 00432 array( #1 00433 2, true, # not the current edit, but still by this user 00434 ), 00435 array( #2 00436 1, false, # edit by another user 00437 ), 00438 array( #3 00439 0, false, # first edit, by this user, but another user edited in the mean time 00440 ), 00441 ); 00442 } 00443 00447 public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) { 00448 $userA = User::newFromName( "RevisionStorageTest_userA" ); 00449 $userB = User::newFromName( "RevisionStorageTest_userB" ); 00450 00451 if ( $userA->getId() === 0 ) { 00452 $userA = User::createNew( $userA->getName() ); 00453 } 00454 00455 if ( $userB->getId() === 0 ) { 00456 $userB = User::createNew( $userB->getName() ); 00457 } 00458 00459 $ns = $this->getDefaultWikitextNS(); 00460 00461 $dbw = wfGetDB( DB_MASTER ); 00462 $revisions = array(); 00463 00464 // create revisions ----------------------------- 00465 $page = WikiPage::factory( Title::newFromText( 00466 'RevisionStorageTest_testUserWasLastToEdit', $ns ) ); 00467 $page->insertOn( $dbw ); 00468 00469 # zero 00470 $revisions[0] = new Revision( array( 00471 'page' => $page->getId(), 00472 'title' => $page->getTitle(), // we need the title to determine the page's default content model 00473 'timestamp' => '20120101000000', 00474 'user' => $userA->getId(), 00475 'text' => 'zero', 00476 'content_model' => CONTENT_MODEL_WIKITEXT, 00477 'summary' => 'edit zero' 00478 ) ); 00479 $revisions[0]->insertOn( $dbw ); 00480 00481 # one 00482 $revisions[1] = new Revision( array( 00483 'page' => $page->getId(), 00484 'title' => $page->getTitle(), // still need the title, because $page->getId() is 0 (there's no entry in the page table) 00485 'timestamp' => '20120101000100', 00486 'user' => $userA->getId(), 00487 'text' => 'one', 00488 'content_model' => CONTENT_MODEL_WIKITEXT, 00489 'summary' => 'edit one' 00490 ) ); 00491 $revisions[1]->insertOn( $dbw ); 00492 00493 # two 00494 $revisions[2] = new Revision( array( 00495 'page' => $page->getId(), 00496 'title' => $page->getTitle(), 00497 'timestamp' => '20120101000200', 00498 'user' => $userB->getId(), 00499 'text' => 'two', 00500 'content_model' => CONTENT_MODEL_WIKITEXT, 00501 'summary' => 'edit two' 00502 ) ); 00503 $revisions[2]->insertOn( $dbw ); 00504 00505 # three 00506 $revisions[3] = new Revision( array( 00507 'page' => $page->getId(), 00508 'title' => $page->getTitle(), 00509 'timestamp' => '20120101000300', 00510 'user' => $userA->getId(), 00511 'text' => 'three', 00512 'content_model' => CONTENT_MODEL_WIKITEXT, 00513 'summary' => 'edit three' 00514 ) ); 00515 $revisions[3]->insertOn( $dbw ); 00516 00517 # four 00518 $revisions[4] = new Revision( array( 00519 'page' => $page->getId(), 00520 'title' => $page->getTitle(), 00521 'timestamp' => '20120101000200', 00522 'user' => $userA->getId(), 00523 'text' => 'zero', 00524 'content_model' => CONTENT_MODEL_WIKITEXT, 00525 'summary' => 'edit four' 00526 ) ); 00527 $revisions[4]->insertOn( $dbw ); 00528 00529 // test it --------------------------------- 00530 $since = $revisions[$sinceIdx]->getTimestamp(); 00531 00532 $wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since ); 00533 00534 $this->assertEquals( $expectedLast, $wasLast ); 00535 } 00536 }