This commit depends on the introduction of MediaWikiTestCase::setMwGlobals in change Iccf6ea81f4. Various tests already set their globals, but forgot to restore them afterwards, or forgot to call the parent setUp, tearDown... Either way they won't have to anymore with setMwGlobals. Consistent use of function characteristics: * protected function setUp * protected function tearDown * public static function (provide..) (Matching the function signature with PHPUnit/Framework/TestCase.php) Replaces: * public function (setUp|tearDown)\( * protected function $1( * \tfunction (setUp|tearDown)\( * \tprotected function $1( * \tfunction (data|provide)\( * \tpublic static function $1\( Also renamed a few "data#", "provider#" and "provides#" functions to "provide#" for consistency. This also removes confusion where the /media tests had a few private methods called dataFile(), which were sometimes expected to be data providers. Fixes: TimestampTest often failed due to a previous test setting a different language (it tests "1 hour ago" so need to make sure it is set to English). MWNamespaceTest became a lot cleaner now that it executes with a known context. Though the now-redundant code that was removed didn't work anyway because wgContentNamespaces isn't keyed by namespace id, it had them was values... FileBackendTest: * Fixed: "PHP Fatal: Using $this when not in object context" HttpTest * Added comment about: "PHP Fatal: Call to protected MWHttpRequest::__construct()" (too much unrelated code to fix in this commit) ExternalStoreTest * Add an assertTrue as well, without it the test is useless because regardless of whether wgExternalStores is true or false it only uses it if it is an array. Change-Id: I9d2b148e57bada64afeb7d5a99bec0e58f8e1561
408 lines
11 KiB
PHP
408 lines
11 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Test class for Revision storage.
|
|
*
|
|
* @group Database
|
|
* ^--- important, causes temporary tables to be used instead of the real database
|
|
*
|
|
* @group medium
|
|
* ^--- important, causes tests not to fail with timeout
|
|
*/
|
|
class RevisionStorageTest extends MediaWikiTestCase {
|
|
|
|
var $the_page;
|
|
|
|
function __construct( $name = null, array $data = array(), $dataName = '' ) {
|
|
parent::__construct( $name, $data, $dataName );
|
|
|
|
$this->tablesUsed = array_merge( $this->tablesUsed,
|
|
array( 'page',
|
|
'revision',
|
|
'text',
|
|
|
|
'recentchanges',
|
|
'logging',
|
|
|
|
'page_props',
|
|
'pagelinks',
|
|
'categorylinks',
|
|
'langlinks',
|
|
'externallinks',
|
|
'imagelinks',
|
|
'templatelinks',
|
|
'iwlinks' ) );
|
|
}
|
|
|
|
protected function setUp() {
|
|
if ( !$this->the_page ) {
|
|
$this->the_page = $this->createPage( 'RevisionStorageTest_the_page', "just a dummy page" );
|
|
}
|
|
}
|
|
|
|
protected function makeRevision( $props = null ) {
|
|
if ( $props === null ) $props = array();
|
|
|
|
if ( !isset( $props['content'] ) && !isset( $props['text'] ) ) $props['text'] = 'Lorem Ipsum';
|
|
if ( !isset( $props['comment'] ) ) $props['comment'] = 'just a test';
|
|
if ( !isset( $props['page'] ) ) $props['page'] = $this->the_page->getId();
|
|
|
|
$rev = new Revision( $props );
|
|
|
|
$dbw = wfgetDB( DB_MASTER );
|
|
$rev->insertOn( $dbw );
|
|
|
|
return $rev;
|
|
}
|
|
|
|
protected function createPage( $page, $text, $model = null ) {
|
|
if ( is_string( $page ) ) $page = Title::newFromText( $page );
|
|
if ( $page instanceof Title ) $page = new WikiPage( $page );
|
|
|
|
if ( $page->exists() ) {
|
|
$page->doDeleteArticle( "done" );
|
|
}
|
|
|
|
$page->doEdit( $text, "testing", EDIT_NEW );
|
|
|
|
return $page;
|
|
}
|
|
|
|
protected function assertRevEquals( Revision $orig, Revision $rev = null ) {
|
|
$this->assertNotNull( $rev, 'missing revision' );
|
|
|
|
$this->assertEquals( $orig->getId(), $rev->getId() );
|
|
$this->assertEquals( $orig->getPage(), $rev->getPage() );
|
|
$this->assertEquals( $orig->getTimestamp(), $rev->getTimestamp() );
|
|
$this->assertEquals( $orig->getUser(), $rev->getUser() );
|
|
$this->assertEquals( $orig->getSha1(), $rev->getSha1() );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::__construct
|
|
*/
|
|
public function testConstructFromRow()
|
|
{
|
|
$orig = $this->makeRevision();
|
|
|
|
$dbr = wfgetDB( DB_SLAVE );
|
|
$res = $dbr->select( 'revision', '*', array( 'rev_id' => $orig->getId() ) );
|
|
$this->assertTrue( is_object( $res ), 'query failed' );
|
|
|
|
$row = $res->fetchObject();
|
|
$res->free();
|
|
|
|
$rev = new Revision( $row );
|
|
|
|
$this->assertRevEquals( $orig, $rev );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::newFromRow
|
|
*/
|
|
public function testNewFromRow()
|
|
{
|
|
$orig = $this->makeRevision();
|
|
|
|
$dbr = wfgetDB( DB_SLAVE );
|
|
$res = $dbr->select( 'revision', '*', array( 'rev_id' => $orig->getId() ) );
|
|
$this->assertTrue( is_object( $res ), 'query failed' );
|
|
|
|
$row = $res->fetchObject();
|
|
$res->free();
|
|
|
|
$rev = Revision::newFromRow( $row );
|
|
|
|
$this->assertRevEquals( $orig, $rev );
|
|
}
|
|
|
|
|
|
/**
|
|
* @covers Revision::newFromArchiveRow
|
|
*/
|
|
public function testNewFromArchiveRow()
|
|
{
|
|
$page = $this->createPage( 'RevisionStorageTest_testNewFromArchiveRow', 'Lorem Ipsum' );
|
|
$orig = $page->getRevision();
|
|
$page->doDeleteArticle( 'test Revision::newFromArchiveRow' );
|
|
|
|
$dbr = wfgetDB( DB_SLAVE );
|
|
$res = $dbr->select( 'archive', '*', array( 'ar_rev_id' => $orig->getId() ) );
|
|
$this->assertTrue( is_object( $res ), 'query failed' );
|
|
|
|
$row = $res->fetchObject();
|
|
$res->free();
|
|
|
|
$rev = Revision::newFromArchiveRow( $row );
|
|
|
|
$this->assertRevEquals( $orig, $rev );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::newFromId
|
|
*/
|
|
public function testNewFromId()
|
|
{
|
|
$orig = $this->makeRevision();
|
|
|
|
$rev = Revision::newFromId( $orig->getId() );
|
|
|
|
$this->assertRevEquals( $orig, $rev );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::fetchRevision
|
|
*/
|
|
public function testFetchRevision()
|
|
{
|
|
$page = $this->createPage( 'RevisionStorageTest_testFetchRevision', 'one' );
|
|
$id1 = $page->getRevision()->getId();
|
|
|
|
$page->doEdit( 'two', 'second rev' );
|
|
$id2 = $page->getRevision()->getId();
|
|
|
|
$res = Revision::fetchRevision( $page->getTitle() );
|
|
|
|
#note: order is unspecified
|
|
$rows = array();
|
|
while ( ( $row = $res->fetchObject() ) ) {
|
|
$rows[ $row->rev_id ]= $row;
|
|
}
|
|
|
|
$row = $res->fetchObject();
|
|
$this->assertEquals( 1, count($rows), 'expected exactly one revision' );
|
|
$this->assertArrayHasKey( $id2, $rows, 'missing revision with id ' . $id2 );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::selectFields
|
|
*/
|
|
public function testSelectFields()
|
|
{
|
|
$fields = Revision::selectFields();
|
|
|
|
$this->assertTrue( in_array( 'rev_id', $fields ), 'missing rev_id in list of fields');
|
|
$this->assertTrue( in_array( 'rev_page', $fields ), 'missing rev_page in list of fields');
|
|
$this->assertTrue( in_array( 'rev_timestamp', $fields ), 'missing rev_timestamp in list of fields');
|
|
$this->assertTrue( in_array( 'rev_user', $fields ), 'missing rev_user in list of fields');
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::getPage
|
|
*/
|
|
public function testGetPage()
|
|
{
|
|
$page = $this->the_page;
|
|
|
|
$orig = $this->makeRevision( array( 'page' => $page->getId() ) );
|
|
$rev = Revision::newFromId( $orig->getId() );
|
|
|
|
$this->assertEquals( $page->getId(), $rev->getPage() );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::getText
|
|
*/
|
|
public function testGetText()
|
|
{
|
|
$orig = $this->makeRevision( array( 'text' => 'hello hello.' ) );
|
|
$rev = Revision::newFromId( $orig->getId() );
|
|
|
|
$this->assertEquals( 'hello hello.', $rev->getText() );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::revText
|
|
*/
|
|
public function testRevText()
|
|
{
|
|
$this->hideDeprecated( 'Revision::revText' );
|
|
$orig = $this->makeRevision( array( 'text' => 'hello hello rev.' ) );
|
|
$rev = Revision::newFromId( $orig->getId() );
|
|
|
|
$this->assertEquals( 'hello hello rev.', $rev->revText() );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::getRawText
|
|
*/
|
|
public function testGetRawText()
|
|
{
|
|
$orig = $this->makeRevision( array( 'text' => 'hello hello raw.' ) );
|
|
$rev = Revision::newFromId( $orig->getId() );
|
|
|
|
$this->assertEquals( 'hello hello raw.', $rev->getRawText() );
|
|
}
|
|
/**
|
|
* @covers Revision::isCurrent
|
|
*/
|
|
public function testIsCurrent()
|
|
{
|
|
$page = $this->createPage( 'RevisionStorageTest_testIsCurrent', 'Lorem Ipsum' );
|
|
$rev1 = $page->getRevision();
|
|
|
|
# @todo: find out if this should be true
|
|
# $this->assertTrue( $rev1->isCurrent() );
|
|
|
|
$rev1x = Revision::newFromId( $rev1->getId() );
|
|
$this->assertTrue( $rev1x->isCurrent() );
|
|
|
|
$page->doEdit( 'Bla bla', 'second rev' );
|
|
$rev2 = $page->getRevision();
|
|
|
|
# @todo: find out if this should be true
|
|
# $this->assertTrue( $rev2->isCurrent() );
|
|
|
|
$rev1x = Revision::newFromId( $rev1->getId() );
|
|
$this->assertFalse( $rev1x->isCurrent() );
|
|
|
|
$rev2x = Revision::newFromId( $rev2->getId() );
|
|
$this->assertTrue( $rev2x->isCurrent() );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::getPrevious
|
|
*/
|
|
public function testGetPrevious()
|
|
{
|
|
$page = $this->createPage( 'RevisionStorageTest_testGetPrevious', 'Lorem Ipsum testGetPrevious' );
|
|
$rev1 = $page->getRevision();
|
|
|
|
$this->assertNull( $rev1->getPrevious() );
|
|
|
|
$page->doEdit( 'Bla bla', 'second rev testGetPrevious' );
|
|
$rev2 = $page->getRevision();
|
|
|
|
$this->assertNotNull( $rev2->getPrevious() );
|
|
$this->assertEquals( $rev1->getId(), $rev2->getPrevious()->getId() );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::getNext
|
|
*/
|
|
public function testGetNext()
|
|
{
|
|
$page = $this->createPage( 'RevisionStorageTest_testGetNext', 'Lorem Ipsum testGetNext' );
|
|
$rev1 = $page->getRevision();
|
|
|
|
$this->assertNull( $rev1->getNext() );
|
|
|
|
$page->doEdit( 'Bla bla', 'second rev testGetNext' );
|
|
$rev2 = $page->getRevision();
|
|
|
|
$this->assertNotNull( $rev1->getNext() );
|
|
$this->assertEquals( $rev2->getId(), $rev1->getNext()->getId() );
|
|
}
|
|
|
|
/**
|
|
* @covers Revision::newNullRevision
|
|
*/
|
|
public function testNewNullRevision()
|
|
{
|
|
$page = $this->createPage( 'RevisionStorageTest_testNewNullRevision', 'some testing text' );
|
|
$orig = $page->getRevision();
|
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
|
$rev = Revision::newNullRevision( $dbw, $page->getId(), 'a null revision', false );
|
|
|
|
$this->assertNotEquals( $orig->getId(), $rev->getId(), 'new null revision shold have a different id from the original revision' );
|
|
$this->assertEquals( $orig->getTextId(), $rev->getTextId(), 'new null revision shold have the same text id as the original revision' );
|
|
$this->assertEquals( 'some testing text', $rev->getText() );
|
|
}
|
|
|
|
public static function provideUserWasLastToEdit() {
|
|
return array(
|
|
array( #0
|
|
3, true, # actually the last edit
|
|
),
|
|
array( #1
|
|
2, true, # not the current edit, but still by this user
|
|
),
|
|
array( #2
|
|
1, false, # edit by another user
|
|
),
|
|
array( #3
|
|
0, false, # first edit, by this user, but another user edited in the mean time
|
|
),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideUserWasLastToEdit
|
|
*/
|
|
public function testUserWasLastToEdit( $sinceIdx, $expectedLast ) {
|
|
$userA = \User::newFromName( "RevisionStorageTest_userA" );
|
|
$userB = \User::newFromName( "RevisionStorageTest_userB" );
|
|
|
|
if ( $userA->getId() === 0 ) {
|
|
$userA = \User::createNew( $userA->getName() );
|
|
}
|
|
|
|
if ( $userB->getId() === 0 ) {
|
|
$userB = \User::createNew( $userB->getName() );
|
|
}
|
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
|
$revisions = array();
|
|
|
|
// create revisions -----------------------------
|
|
$page = WikiPage::factory( Title::newFromText( 'RevisionStorageTest_testUserWasLastToEdit' ) );
|
|
|
|
# zero
|
|
$revisions[0] = new Revision( array(
|
|
'page' => $page->getId(),
|
|
'timestamp' => '20120101000000',
|
|
'user' => $userA->getId(),
|
|
'text' => 'zero',
|
|
'summary' => 'edit zero'
|
|
) );
|
|
$revisions[0]->insertOn( $dbw );
|
|
|
|
# one
|
|
$revisions[1] = new Revision( array(
|
|
'page' => $page->getId(),
|
|
'timestamp' => '20120101000100',
|
|
'user' => $userA->getId(),
|
|
'text' => 'one',
|
|
'summary' => 'edit one'
|
|
) );
|
|
$revisions[1]->insertOn( $dbw );
|
|
|
|
# two
|
|
$revisions[2] = new Revision( array(
|
|
'page' => $page->getId(),
|
|
'timestamp' => '20120101000200',
|
|
'user' => $userB->getId(),
|
|
'text' => 'two',
|
|
'summary' => 'edit two'
|
|
) );
|
|
$revisions[2]->insertOn( $dbw );
|
|
|
|
# three
|
|
$revisions[3] = new Revision( array(
|
|
'page' => $page->getId(),
|
|
'timestamp' => '20120101000300',
|
|
'user' => $userA->getId(),
|
|
'text' => 'three',
|
|
'summary' => 'edit three'
|
|
) );
|
|
$revisions[3]->insertOn( $dbw );
|
|
|
|
# four
|
|
$revisions[4] = new Revision( array(
|
|
'page' => $page->getId(),
|
|
'timestamp' => '20120101000200',
|
|
'user' => $userA->getId(),
|
|
'text' => 'zero',
|
|
'summary' => 'edit four'
|
|
) );
|
|
$revisions[4]->insertOn( $dbw );
|
|
|
|
// test it ---------------------------------
|
|
$since = $revisions[ $sinceIdx ]->getTimestamp();
|
|
|
|
$wasLast = Revision::userWasLastToEdit( $dbw, $page->getId(), $userA->getId(), $since );
|
|
|
|
$this->assertEquals( $expectedLast, $wasLast );
|
|
}
|
|
}
|