MediaWiki  REL1_23
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     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 }