Just an auto-replace from codesniffer for now. Change-Id: I5240dc9ac5929d291b0ef1c743ea2bfd3f428266
237 lines
7.4 KiB
PHP
237 lines
7.4 KiB
PHP
<?php
|
|
|
|
use MediaWiki\MediaWikiServices;
|
|
use Wikimedia\Timestamp\ConvertibleTimestamp;
|
|
|
|
/**
|
|
* @coversDefaultClass DBFileJournal
|
|
* @covers ::__construct
|
|
* @covers ::getMasterDB
|
|
* @group Database
|
|
*/
|
|
class DBFileJournalIntegrationTest extends MediaWikiIntegrationTestCase {
|
|
public function addDBDataOnce() {
|
|
global $IP;
|
|
$db = MediaWikiServices::getInstance()->getDBLoadBalancer()->getConnection( DB_PRIMARY );
|
|
if ( $db->getType() !== 'mysql' ) {
|
|
return;
|
|
}
|
|
if ( !$db->tableExists( 'filejournal' ) ) {
|
|
$db->sourceFile( "$IP/maintenance/archives/patch-filejournal.sql" );
|
|
}
|
|
}
|
|
|
|
protected function setUp() : void {
|
|
parent::setUp();
|
|
|
|
$db = MediaWikiServices::getInstance()->getDBLoadBalancer()->getConnection( DB_PRIMARY );
|
|
if ( $db->getType() !== 'mysql' ) {
|
|
$this->markTestSkipped( 'No filejournal schema available for this database type' );
|
|
}
|
|
|
|
$this->tablesUsed[] = 'filejournal';
|
|
}
|
|
|
|
private function getJournal( $options = [] ) {
|
|
return new DBFileJournal(
|
|
$options + [ 'domain' => wfWikiID(), 'backend' => 'local-backend' ] );
|
|
}
|
|
|
|
/**
|
|
* @covers ::doLogChangeBatch
|
|
*/
|
|
public function testDoLogChangeBatch_exceptionDbConnect() {
|
|
$this->setNullLogger( 'DBConnection' );
|
|
$journal = $this->getJournal( [ 'domain' => 'no-such-domain' ] );
|
|
|
|
$this->assertEquals(
|
|
StatusValue::newFatal( 'filejournal-fail-dbconnect', 'local-backend' ),
|
|
$journal->logChangeBatch( [ [] ], 'batch' ) );
|
|
}
|
|
|
|
/**
|
|
* @covers ::doLogChangeBatch
|
|
*/
|
|
public function testDoLogChangeBatch_exceptionDbQuery() {
|
|
$this->setNullLogger( 'DBQuery' );
|
|
$journal = $this->getJournal();
|
|
|
|
// Null value for 'op' will make the query fail
|
|
$this->assertEquals(
|
|
StatusValue::newFatal( 'filejournal-fail-dbquery', 'local-backend' ),
|
|
$journal->logChangeBatch(
|
|
[ [ 'op' => null, 'path' => '', 'newSha1' => false ] ], 'batch' ) );
|
|
}
|
|
|
|
/**
|
|
* @covers ::doLogChangeBatch
|
|
* @covers ::doGetCurrentPosition
|
|
*/
|
|
public function testDoGetCurrentPosition() {
|
|
$journal = $this->getJournal();
|
|
|
|
$this->assertNull( $journal->getCurrentPosition() );
|
|
|
|
$journal->logChangeBatch(
|
|
[ [ 'op' => 'create', 'path' => '/path', 'newSha1' => false ] ], 'batch1' );
|
|
|
|
$this->assertSame( '1', $journal->getCurrentPosition() );
|
|
|
|
$journal->logChangeBatch(
|
|
[ [ 'op' => 'create', 'path' => '/path', 'newSha1' => false ] ], 'batch2' );
|
|
|
|
$this->assertSame( '2', $journal->getCurrentPosition() );
|
|
}
|
|
|
|
/**
|
|
* @covers ::doLogChangeBatch
|
|
* @covers ::doGetPositionAtTime
|
|
*/
|
|
public function testDoGetPositionAtTime() {
|
|
$journal = $this->getJournal();
|
|
|
|
$now = time();
|
|
|
|
$this->assertFalse( $journal->getPositionAtTime( $now ) );
|
|
|
|
ConvertibleTimestamp::setFakeTime( $now - 86400 );
|
|
|
|
$journal->logChangeBatch(
|
|
[ [ 'op' => 'create', 'path' => '/path', 'newSha1' => false ] ], 'batch1' );
|
|
|
|
ConvertibleTimestamp::setFakeTime( $now - 3600 );
|
|
|
|
$journal->logChangeBatch(
|
|
[ [ 'op' => 'create', 'path' => '/path', 'newSha1' => false ] ], 'batch2' );
|
|
|
|
$this->assertFalse( $journal->getPositionAtTime( $now - 86401 ) );
|
|
$this->assertSame( '1', $journal->getPositionAtTime( $now - 86400 ) );
|
|
$this->assertSame( '1', $journal->getPositionAtTime( $now - 3601 ) );
|
|
$this->assertSame( '2', $journal->getPositionAtTime( $now - 3600 ) );
|
|
}
|
|
|
|
/**
|
|
* @param int $expectedStart First index expected to be returned (0-based)
|
|
* @param int|null $expectedCount Number of entries expected to be returned (null for all)
|
|
* @param string|null|false $expectedNext Expected value of $next, or false not to pass
|
|
* @param array $args If any third argument is present, $next will also be tested
|
|
* @dataProvider provideDoGetChangeEntries
|
|
* @covers ::doLogChangeBatch
|
|
* @covers ::doGetChangeEntries
|
|
*/
|
|
public function testDoGetChangeEntries(
|
|
$expectedStart, $expectedCount, $expectedNext, array $args
|
|
) {
|
|
$journal = $this->getJournal();
|
|
|
|
$i = 0;
|
|
$makeExpectedEntry = static function ( $op, $path, $newSha1, $batch, $time ) use ( &$i ) {
|
|
$i++;
|
|
return [
|
|
'id' => (string)$i,
|
|
'batch_uuid' => $batch,
|
|
'backend' => 'local-backend',
|
|
'path' => $path,
|
|
'op' => $op ?? '',
|
|
'new_sha1' => $newSha1 !== false ? $newSha1 : '0',
|
|
'timestamp' => ConvertibleTimestamp::convert( TS_MW, $time ),
|
|
];
|
|
};
|
|
|
|
$expectedEntries = [];
|
|
|
|
$now = time();
|
|
|
|
ConvertibleTimestamp::setFakeTime( $now - 3600 );
|
|
$changes = [
|
|
[ 'op' => 'create', 'path' => '/path1',
|
|
'newSha1' => base_convert( sha1( 'a' ), 16, 36 ) ],
|
|
[ 'op' => 'delete', 'path' => '/path2', 'newSha1' => false ],
|
|
[ 'op' => 'null', 'path' => '', 'newSha1' => false ],
|
|
];
|
|
$this->assertEquals( StatusValue::newGood(),
|
|
$journal->logChangeBatch( $changes, 'batch1' ) );
|
|
foreach ( $changes as $change ) {
|
|
$expectedEntries[] = $makeExpectedEntry(
|
|
...array_merge( array_values( $change ), [ 'batch1', $now - 3600 ] ) );
|
|
}
|
|
|
|
ConvertibleTimestamp::setFakeTime( $now - 60 );
|
|
$change = [ 'op' => 'update', 'path' => '/path1',
|
|
'newSha1' => base_convert( sha1( 'b' ), 16, 36 ) ];
|
|
$this->assertEquals(
|
|
StatusValue::newGood(), $journal->logChangeBatch( [ $change ], 'batch2' ) );
|
|
$expectedEntries[] = $makeExpectedEntry(
|
|
...array_merge( array_values( $change ), [ 'batch2', $now - 60 ] ) );
|
|
|
|
if ( $expectedNext === false ) {
|
|
$this->assertSame(
|
|
array_slice( $expectedEntries, $expectedStart, $expectedCount ),
|
|
$journal->getChangeEntries( ...$args )
|
|
);
|
|
} else {
|
|
$next = false;
|
|
$this->assertSame(
|
|
array_slice( $expectedEntries, $expectedStart, $expectedCount ),
|
|
$journal->getChangeEntries( $args[0], $args[1], $next )
|
|
);
|
|
$this->assertSame( $expectedNext, $next );
|
|
}
|
|
}
|
|
|
|
public static function provideDoGetChangeEntries() {
|
|
return [
|
|
'No args' => [ 0, 4, false, [] ],
|
|
'null' => [ 0, 4, false, [ null ] ],
|
|
'1' => [ 0, 4, false, [ 1 ] ],
|
|
'2' => [ 1, 3, false, [ 2 ] ],
|
|
'4' => [ 3, 1, false, [ 4 ] ],
|
|
'5' => [ 0, 0, false, [ 5 ] ],
|
|
'null, 0' => [ 0, 4, null, [ null, 0 ] ],
|
|
'1, 0' => [ 0, 4, null, [ 1, 0 ] ],
|
|
'2, 0' => [ 1, 3, null, [ 2, 0 ] ],
|
|
'4, 0' => [ 3, 1, null, [ 4, 0 ] ],
|
|
'5, 0' => [ 0, 0, null, [ 5, 0 ] ],
|
|
'1, 1' => [ 0, 1, '2', [ 1, 1 ] ],
|
|
'1, 2' => [ 0, 2, '3', [ 1, 2 ] ],
|
|
'1, 4' => [ 0, 4, null, [ 1, 4 ] ],
|
|
'1, 5' => [ 0, 4, null, [ 1, 5 ] ],
|
|
'2, 2' => [ 1, 2, '4', [ 2, 2 ] ],
|
|
'1, 2 with no $next' => [ 0, 2, false, [ 1, 2 ] ],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @covers ::doPurgeOldLogs
|
|
*/
|
|
public function testDoPurgeOldLogs_noop() {
|
|
// If we tried to access the database, it would throw, because the domain doesn't exist
|
|
$journal = $this->getJournal( [ 'domain' => 'no-such-domain' ] );
|
|
$this->assertEquals( StatusValue::newGood(), $journal->purgeOldLogs() );
|
|
}
|
|
|
|
/**
|
|
* @covers ::doPurgeOldLogs
|
|
* @covers ::doLogChangeBatch
|
|
* @covers ::doGetChangeEntries
|
|
*/
|
|
public function testDoPurgeOldLogs() {
|
|
$journal = $this->getJournal( [ 'ttlDays' => 1 ] );
|
|
$now = time();
|
|
|
|
// One day and one second ago
|
|
ConvertibleTimestamp::setFakeTime( $now - 86401 );
|
|
$this->assertEquals( StatusValue::newGood(), $journal->logChangeBatch(
|
|
[ [ 'op' => 'null', 'path' => '', 'newSha1' => false ] ], 'batch1' ) );
|
|
|
|
// One day ago exactly, won't get purged
|
|
ConvertibleTimestamp::setFakeTime( $now - 86400 );
|
|
$this->assertEquals( StatusValue::newGood(), $journal->logChangeBatch(
|
|
[ [ 'op' => 'null', 'path' => '', 'newSha1' => false ] ], 'batch2' ) );
|
|
|
|
ConvertibleTimestamp::setFakeTime( $now );
|
|
$this->assertCount( 2, $journal->getChangeEntries() );
|
|
$journal->purgeOldLogs();
|
|
$this->assertCount( 1, $journal->getChangeEntries() );
|
|
}
|
|
}
|