MediaWiki  REL1_22
RevisionStorageTest.php
Go to the documentation of this file.
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     public 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 
00173 
00177     public function testNewFromArchiveRow() {
00178         $page = $this->createPage( 'RevisionStorageTest_testNewFromArchiveRow', 'Lorem Ipsum', CONTENT_MODEL_WIKITEXT );
00179         $orig = $page->getRevision();
00180         $page->doDeleteArticle( 'test Revision::newFromArchiveRow' );
00181 
00182         $dbr = wfgetDB( DB_SLAVE );
00183         $res = $dbr->select( 'archive', '*', array( 'ar_rev_id' => $orig->getId() ) );
00184         $this->assertTrue( is_object( $res ), 'query failed' );
00185 
00186         $row = $res->fetchObject();
00187         $res->free();
00188 
00189         $rev = Revision::newFromArchiveRow( $row );
00190 
00191         $this->assertRevEquals( $orig, $rev );
00192     }
00193 
00197     public function testNewFromId() {
00198         $orig = $this->makeRevision();
00199 
00200         $rev = Revision::newFromId( $orig->getId() );
00201 
00202         $this->assertRevEquals( $orig, $rev );
00203     }
00204 
00208     public function testFetchRevision() {
00209         $page = $this->createPage( 'RevisionStorageTest_testFetchRevision', 'one', CONTENT_MODEL_WIKITEXT );
00210         $id1 = $page->getRevision()->getId();
00211 
00212         $page->doEditContent( new WikitextContent( 'two' ), 'second rev' );
00213         $id2 = $page->getRevision()->getId();
00214 
00215         $res = Revision::fetchRevision( $page->getTitle() );
00216 
00217         #note: order is unspecified
00218         $rows = array();
00219         while ( ( $row = $res->fetchObject() ) ) {
00220             $rows[$row->rev_id] = $row;
00221         }
00222 
00223         $row = $res->fetchObject();
00224         $this->assertEquals( 1, count( $rows ), 'expected exactly one revision' );
00225         $this->assertArrayHasKey( $id2, $rows, 'missing revision with id ' . $id2 );
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 testRevText() {
00305         $this->hideDeprecated( 'Revision::revText' );
00306         $orig = $this->makeRevision( array( 'text' => 'hello hello rev.' ) );
00307         $rev = Revision::newFromId( $orig->getId() );
00308 
00309         $this->assertEquals( 'hello hello rev.', $rev->revText() );
00310     }
00311 
00315     public function testGetRawText() {
00316         $this->hideDeprecated( 'Revision::getRawText' );
00317 
00318         $orig = $this->makeRevision( array( 'text' => 'hello hello raw.' ) );
00319         $rev = Revision::newFromId( $orig->getId() );
00320 
00321         $this->assertEquals( 'hello hello raw.', $rev->getRawText() );
00322     }
00323 
00327     public function testGetContentModel() {
00328         global $wgContentHandlerUseDB;
00329 
00330         if ( !$wgContentHandlerUseDB ) {
00331             $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
00332         }
00333 
00334         $orig = $this->makeRevision( array( 'text' => 'hello hello.',
00335             'content_model' => CONTENT_MODEL_JAVASCRIPT ) );
00336         $rev = Revision::newFromId( $orig->getId() );
00337 
00338         $this->assertEquals( CONTENT_MODEL_JAVASCRIPT, $rev->getContentModel() );
00339     }
00340 
00344     public function testGetContentFormat() {
00345         global $wgContentHandlerUseDB;
00346 
00347         if ( !$wgContentHandlerUseDB ) {
00348             $this->markTestSkipped( '$wgContentHandlerUseDB is disabled' );
00349         }
00350 
00351         $orig = $this->makeRevision( array(
00352             'text' => 'hello hello.',
00353             'content_model' => CONTENT_MODEL_JAVASCRIPT,
00354             'content_format' => CONTENT_FORMAT_JAVASCRIPT
00355         ) );
00356         $rev = Revision::newFromId( $orig->getId() );
00357 
00358         $this->assertEquals( CONTENT_FORMAT_JAVASCRIPT, $rev->getContentFormat() );
00359     }
00360 
00364     public function testIsCurrent() {
00365         $page = $this->createPage( 'RevisionStorageTest_testIsCurrent', 'Lorem Ipsum', CONTENT_MODEL_WIKITEXT );
00366         $rev1 = $page->getRevision();
00367 
00368         # @todo find out if this should be true
00369         # $this->assertTrue( $rev1->isCurrent() );
00370 
00371         $rev1x = Revision::newFromId( $rev1->getId() );
00372         $this->assertTrue( $rev1x->isCurrent() );
00373 
00374         $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ), 'second rev' );
00375         $rev2 = $page->getRevision();
00376 
00377         # @todo find out if this should be true
00378         # $this->assertTrue( $rev2->isCurrent() );
00379 
00380         $rev1x = Revision::newFromId( $rev1->getId() );
00381         $this->assertFalse( $rev1x->isCurrent() );
00382 
00383         $rev2x = Revision::newFromId( $rev2->getId() );
00384         $this->assertTrue( $rev2x->isCurrent() );
00385     }
00386 
00390     public function testGetPrevious() {
00391         $page = $this->createPage( 'RevisionStorageTest_testGetPrevious', 'Lorem Ipsum testGetPrevious', CONTENT_MODEL_WIKITEXT );
00392         $rev1 = $page->getRevision();
00393 
00394         $this->assertNull( $rev1->getPrevious() );
00395 
00396         $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
00397             'second rev testGetPrevious' );
00398         $rev2 = $page->getRevision();
00399 
00400         $this->assertNotNull( $rev2->getPrevious() );
00401         $this->assertEquals( $rev1->getId(), $rev2->getPrevious()->getId() );
00402     }
00403 
00407     public function testGetNext() {
00408         $page = $this->createPage( 'RevisionStorageTest_testGetNext', 'Lorem Ipsum testGetNext', CONTENT_MODEL_WIKITEXT );
00409         $rev1 = $page->getRevision();
00410 
00411         $this->assertNull( $rev1->getNext() );
00412 
00413         $page->doEditContent( ContentHandler::makeContent( 'Bla bla', $page->getTitle(), CONTENT_MODEL_WIKITEXT ),
00414             'second rev testGetNext' );
00415         $rev2 = $page->getRevision();
00416 
00417         $this->assertNotNull( $rev1->getNext() );
00418         $this->assertEquals( $rev2->getId(), $rev1->getNext()->getId() );
00419     }
00420 
00424     public function testNewNullRevision() {
00425         $page = $this->createPage( 'RevisionStorageTest_testNewNullRevision', 'some testing text', CONTENT_MODEL_WIKITEXT );
00426         $orig = $page->getRevision();
00427 
00428         $dbw = wfGetDB( DB_MASTER );
00429         $rev = Revision::newNullRevision( $dbw, $page->getId(), 'a null revision', false );
00430 
00431         $this->assertNotEquals( $orig->getId(), $rev->getId(),
00432             'new null revision shold have a different id from the original revision' );
00433         $this->assertEquals( $orig->getTextId(), $rev->getTextId(),
00434             'new null revision shold have the same text id as the original revision' );
00435         $this->assertEquals( 'some testing text', $rev->getContent()->getNativeData() );
00436     }
00437 
00438     public static function provideUserWasLastToEdit() {
00439         return array(
00440             array( #0
00441                 3, true, # actually the last edit
00442             ),
00443             array( #1
00444                 2, true, # not the current edit, but still by this user
00445             ),
00446             array( #2
00447                 1, false, # edit by another user
00448             ),
00449             array( #3
00450                 0, false, # first edit, by this user, but another user edited in the mean time
00451             ),
00452         );
00453     }
00454 
00458     public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) {
00459         $userA = User::newFromName( "RevisionStorageTest_userA" );
00460         $userB = User::newFromName( "RevisionStorageTest_userB" );
00461 
00462         if ( $userA->getId() === 0 ) {
00463             $userA = User::createNew( $userA->getName() );
00464         }
00465 
00466         if ( $userB->getId() === 0 ) {
00467             $userB = User::createNew( $userB->getName() );
00468         }
00469 
00470         $ns = $this->getDefaultWikitextNS();
00471 
00472         $dbw = wfGetDB( DB_MASTER );
00473         $revisions = array();
00474 
00475         // create revisions -----------------------------
00476         $page = WikiPage::factory( Title::newFromText(
00477             'RevisionStorageTest_testUserWasLastToEdit', $ns ) );
00478 
00479         # zero
00480         $revisions[0] = new Revision( array(
00481             'page' => $page->getId(),
00482             'title' => $page->getTitle(), // we need the title to determine the page's default content model
00483             'timestamp' => '20120101000000',
00484             'user' => $userA->getId(),
00485             'text' => 'zero',
00486             'content_model' => CONTENT_MODEL_WIKITEXT,
00487             'summary' => 'edit zero'
00488         ) );
00489         $revisions[0]->insertOn( $dbw );
00490 
00491         # one
00492         $revisions[1] = new Revision( array(
00493             'page' => $page->getId(),
00494             'title' => $page->getTitle(), // still need the title, because $page->getId() is 0 (there's no entry in the page table)
00495             'timestamp' => '20120101000100',
00496             'user' => $userA->getId(),
00497             'text' => 'one',
00498             'content_model' => CONTENT_MODEL_WIKITEXT,
00499             'summary' => 'edit one'
00500         ) );
00501         $revisions[1]->insertOn( $dbw );
00502 
00503         # two
00504         $revisions[2] = new Revision( array(
00505             'page' => $page->getId(),
00506             'title' => $page->getTitle(),
00507             'timestamp' => '20120101000200',
00508             'user' => $userB->getId(),
00509             'text' => 'two',
00510             'content_model' => CONTENT_MODEL_WIKITEXT,
00511             'summary' => 'edit two'
00512         ) );
00513         $revisions[2]->insertOn( $dbw );
00514 
00515         # three
00516         $revisions[3] = new Revision( array(
00517             'page' => $page->getId(),
00518             'title' => $page->getTitle(),
00519             'timestamp' => '20120101000300',
00520             'user' => $userA->getId(),
00521             'text' => 'three',
00522             'content_model' => CONTENT_MODEL_WIKITEXT,
00523             'summary' => 'edit three'
00524         ) );
00525         $revisions[3]->insertOn( $dbw );
00526 
00527         # four
00528         $revisions[4] = new Revision( array(
00529             'page' => $page->getId(),
00530             'title' => $page->getTitle(),
00531             'timestamp' => '20120101000200',
00532             'user' => $userA->getId(),
00533             'text' => 'zero',
00534             'content_model' => CONTENT_MODEL_WIKITEXT,
00535             'summary' => 'edit four'
00536         ) );
00537         $revisions[4]->insertOn( $dbw );
00538 
00539         // test it ---------------------------------
00540         $since = $revisions[$sinceIdx]->getTimestamp();
00541 
00542         $wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
00543 
00544         $this->assertEquals( $expectedLast, $wasLast );
00545     }
00546 }