Merge "Fix more UnitTests for databases that do not use integer timestamps"
[lhc/web/wiklou.git] / tests / phpunit / includes / api / ApiEditPageTest.php
index 624cf49..1efbaea 100644 (file)
@@ -7,6 +7,7 @@
  *
  * @group API
  * @group Database
+ * @group medium
  */
 class ApiEditPageTest extends ApiTestCase {
 
@@ -42,14 +43,15 @@ class ApiEditPageTest extends ApiTestCase {
                parent::teardown();
        }
 
-       function testEdit( ) {
+       function testEdit() {
                $name = 'Help:ApiEditPageTest_testEdit'; // assume Help namespace to default to wikitext
 
                // -- test new page --------------------------------------------
                $apiResult = $this->doApiRequestWithToken( array(
-                               'action' => 'edit',
-                               'title' => $name,
-                               'text' => 'some text', ) );
+                       'action' => 'edit',
+                       'title' => $name,
+                       'text' => 'some text',
+               ) );
                $apiResult = $apiResult[0];
 
                // Validate API result data
@@ -64,9 +66,10 @@ class ApiEditPageTest extends ApiTestCase {
 
                // -- test existing page, no change ----------------------------
                $data = $this->doApiRequestWithToken( array(
-                               'action' => 'edit',
-                               'title' => $name,
-                               'text' => 'some text', ) );
+                       'action' => 'edit',
+                       'title' => $name,
+                       'text' => 'some text',
+               ) );
 
                $this->assertEquals( 'Success', $data[0]['edit']['result'] );
 
@@ -75,9 +78,10 @@ class ApiEditPageTest extends ApiTestCase {
 
                // -- test existing page, with change --------------------------
                $data = $this->doApiRequestWithToken( array(
-                               'action' => 'edit',
-                               'title' => $name,
-                               'text' => 'different text' ) );
+                       'action' => 'edit',
+                       'title' => $name,
+                       'text' => 'different text'
+               ) );
 
                $this->assertEquals( 'Success', $data[0]['edit']['result'] );
 
@@ -93,7 +97,7 @@ class ApiEditPageTest extends ApiTestCase {
                );
        }
 
-       function testNonTextEdit( ) {
+       function testNonTextEdit() {
                $name = 'Dummy:ApiEditPageTest_testNonTextEdit';
                $data = serialize( 'some bla bla text' );
 
@@ -157,13 +161,13 @@ class ApiEditPageTest extends ApiTestCase {
                if ( $text !== null ) {
                        if ( $text === '' ) {
                                // can't create an empty page, so create it with some content
-                               list( $re,, ) = $this->doApiRequestWithToken( array(
+                               list( $re, , ) = $this->doApiRequestWithToken( array(
                                        'action' => 'edit',
                                        'title' => $name,
                                        'text' => '(dummy)', ) );
                        }
 
-                       list( $re,, ) = $this->doApiRequestWithToken( array(
+                       list( $re, , ) = $this->doApiRequestWithToken( array(
                                'action' => 'edit',
                                'title' => $name,
                                'text' => $text, ) );
@@ -172,7 +176,7 @@ class ApiEditPageTest extends ApiTestCase {
                }
 
                // -- try append/prepend --------------------------------------------
-               list( $re,, ) = $this->doApiRequestWithToken( array(
+               list( $re, , ) = $this->doApiRequestWithToken( array(
                        'action' => 'edit',
                        'title' => $name,
                        $op . 'text' => $append, ) );
@@ -196,4 +200,153 @@ class ApiEditPageTest extends ApiTestCase {
        function testUndo() {
                $this->markTestIncomplete( "not yet implemented" );
        }
+
+       function testEditConflict() {
+               static $count = 0;
+               $count++;
+
+               // assume NS_HELP defaults to wikitext
+               $name = "Help:ApiEditPageTest_testEditConflict_$count";
+               $title = Title::newFromText( $name );
+
+               $page = WikiPage::factory( $title );
+
+               // base edit
+               $page->doEditContent( new WikitextContent( "Foo" ),
+                       "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
+               $this->forceRevisionDate( $page, '20120101000000' );
+               $baseTime = $page->getRevision()->getTimestamp();
+
+               // conflicting edit
+               $page->doEditContent( new WikitextContent( "Foo bar" ),
+                       "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
+               $this->forceRevisionDate( $page, '20120101020202' );
+
+               // try to save edit, expect conflict
+               try {
+                       list( $re, , ) = $this->doApiRequestWithToken( array(
+                               'action' => 'edit',
+                               'title' => $name,
+                               'text' => 'nix bar!',
+                               'basetimestamp' => $baseTime,
+                       ), null, self::$users['sysop']->user );
+
+                       $this->fail( 'edit conflict expected' );
+               } catch ( UsageException $ex ) {
+                       $this->assertEquals( 'editconflict', $ex->getCodeString() );
+               }
+       }
+
+       function testEditConflict_redirect() {
+               static $count = 0;
+               $count++;
+
+               // assume NS_HELP defaults to wikitext
+               $name = "Help:ApiEditPageTest_testEditConflict_redirect_$count";
+               $title = Title::newFromText( $name );
+               $page = WikiPage::factory( $title );
+
+               $rname = "Help:ApiEditPageTest_testEditConflict_redirect_r$count";
+               $rtitle = Title::newFromText( $rname );
+               $rpage = WikiPage::factory( $rtitle );
+
+               // base edit for content
+               $page->doEditContent( new WikitextContent( "Foo" ),
+                       "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
+               $this->forceRevisionDate( $page, '20120101000000' );
+               $baseTime = $page->getRevision()->getTimestamp();
+
+               // base edit for redirect
+               $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
+                       "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
+               $this->forceRevisionDate( $rpage, '20120101000000' );
+
+               // conflicting edit to redirect
+               $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]\n\n[[Category:Test]]" ),
+                       "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
+               $this->forceRevisionDate( $rpage, '20120101020202' );
+
+               // try to save edit; should work, because we follow the redirect
+               list( $re, , ) = $this->doApiRequestWithToken( array(
+                       'action' => 'edit',
+                       'title' => $rname,
+                       'text' => 'nix bar!',
+                       'basetimestamp' => $baseTime,
+                       'redirect' => true,
+               ), null, self::$users['sysop']->user );
+
+               $this->assertEquals( 'Success', $re['edit']['result'],
+                       "no edit conflict expected when following redirect" );
+
+               // try again, without following the redirect. Should fail.
+               try {
+                       list( $re, , ) = $this->doApiRequestWithToken( array(
+                               'action' => 'edit',
+                               'title' => $rname,
+                               'text' => 'nix bar!',
+                               'basetimestamp' => $baseTime,
+                       ), null, self::$users['sysop']->user );
+
+                       $this->fail( 'edit conflict expected' );
+               } catch ( UsageException $ex ) {
+                       $this->assertEquals( 'editconflict', $ex->getCodeString() );
+               }
+       }
+
+       function testEditConflict_bug41990() {
+               static $count = 0;
+               $count++;
+
+               /*
+               * bug 41990: if the target page has a newer revision than the redirect, then editing the
+               * redirect while specifying 'redirect' and *not* specifying 'basetimestamp' erronously
+               * caused an edit conflict to be detected.
+               */
+
+               // assume NS_HELP defaults to wikitext
+               $name = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_$count";
+               $title = Title::newFromText( $name );
+               $page = WikiPage::factory( $title );
+
+               $rname = "Help:ApiEditPageTest_testEditConflict_redirect_bug41990_r$count";
+               $rtitle = Title::newFromText( $rname );
+               $rpage = WikiPage::factory( $rtitle );
+
+               // base edit for content
+               $page->doEditContent( new WikitextContent( "Foo" ),
+                       "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
+               $this->forceRevisionDate( $page, '20120101000000' );
+
+               // base edit for redirect
+               $rpage->doEditContent( new WikitextContent( "#REDIRECT [[$name]]" ),
+                       "testing 1", EDIT_NEW, false, self::$users['sysop']->user );
+               $this->forceRevisionDate( $rpage, '20120101000000' );
+               $baseTime = $rpage->getRevision()->getTimestamp();
+
+               // new edit to content
+               $page->doEditContent( new WikitextContent( "Foo bar" ),
+                       "testing 2", EDIT_UPDATE, $page->getLatest(), self::$users['uploader']->user );
+               $this->forceRevisionDate( $rpage, '20120101020202' );
+
+               // try to save edit; should work, following the redirect.
+               list( $re, , ) = $this->doApiRequestWithToken( array(
+                       'action' => 'edit',
+                       'title' => $rname,
+                       'text' => 'nix bar!',
+                       'redirect' => true,
+               ), null, self::$users['sysop']->user );
+
+               $this->assertEquals( 'Success', $re['edit']['result'],
+                       "no edit conflict expected here" );
+       }
+
+       protected function forceRevisionDate( WikiPage $page, $timestamp ) {
+               $dbw = wfGetDB( DB_MASTER );
+
+               $dbw->update( 'revision',
+                       array( 'rev_timestamp' => $dbw->timestamp( $timestamp ) ),
+                       array( 'rev_id' => $page->getLatest() ) );
+
+               $page->clear();
+       }
 }