Change RevisionStoreCacheRecord callback signature

In order to convert the tests into tru unit tests.

Bug: T272669
Change-Id: I6055b43381fdcc6dcdf69e9311979db0dccdb16b
This commit is contained in:
Petr Pchelko 2021-01-22 19:00:26 -06:00 committed by Ppchelko
parent 4dffcdd720
commit 1fb76fefbb
4 changed files with 39 additions and 43 deletions

View file

@ -1574,19 +1574,30 @@ class RevisionStore
if ( !$row && !( $queryFlags & self::READ_LATEST ) ) { if ( !$row && !( $queryFlags & self::READ_LATEST ) ) {
// If we found no slots, try looking on the master database (T259738) // If we found no slots, try looking on the master database (T259738)
$this->logger->info( $this->logger->info(
'RevisionStoreCacheRecord refresh callback falling back to READ_LATEST.', 'RevisionStoreCacheRecord refresh callback falling back to READ_LATEST.',
[ [
'revid' => $revId, 'revid' => $revId,
'trace' => wfBacktrace( true ) 'trace' => wfBacktrace( true )
] ]
); );
$dbw = $this->getDBConnectionRefForQueryFlags( self::READ_LATEST ); $dbw = $this->getDBConnectionRefForQueryFlags( self::READ_LATEST );
return $this->fetchRevisionRowFromConds( $row = $this->fetchRevisionRowFromConds(
$dbw, $dbw,
[ 'rev_id' => intval( $revId ) ] [ 'rev_id' => intval( $revId ) ]
); );
} }
return $row; if ( !$row ) {
return [ null, null ];
}
return [
$row->rev_deleted,
User::newFromAnyId(
$row->rev_user ?? null,
$row->rev_user_text ?? null,
$row->rev_actor ?? null,
$this->dbDomain
)
];
}, },
$title, $user, $comment, $row, $slots, $this->dbDomain $title, $user, $comment, $row, $slots, $this->dbDomain
); );

View file

@ -23,23 +23,21 @@
namespace MediaWiki\Revision; namespace MediaWiki\Revision;
use CommentStoreComment; use CommentStoreComment;
use InvalidArgumentException;
use MediaWiki\Page\PageIdentity; use MediaWiki\Page\PageIdentity;
use MediaWiki\Permissions\Authority; use MediaWiki\Permissions\Authority;
use MediaWiki\User\UserIdentity; use MediaWiki\User\UserIdentity;
use MediaWiki\User\UserIdentityValue;
use User;
/** /**
* A cached RevisionStoreRecord. Ensures that changes performed "behind the back" * A cached RevisionStoreRecord. Ensures that changes performed "behind the back"
* of the cache do not cause the revision record to deliver stale data. * of the cache do not cause the revision record to deliver stale data.
* *
* @internal
* @since 1.33 * @since 1.33
*/ */
class RevisionStoreCacheRecord extends RevisionStoreRecord { class RevisionStoreCacheRecord extends RevisionStoreRecord {
/** /**
* @var callable * @var callable ( int $revId ): [ int $rev_deleted, UserIdentity $user ]
*/ */
private $mCallback; private $mCallback;
@ -47,7 +45,8 @@ class RevisionStoreCacheRecord extends RevisionStoreRecord {
* @note Avoid calling this constructor directly. Use the appropriate methods * @note Avoid calling this constructor directly. Use the appropriate methods
* in RevisionStore instead. * in RevisionStore instead.
* *
* @param callable $callback Callback for loading data. Signature: function ( $id ): \stdClass * @param callable $callback Callback for loading data.
* Signature: function ( int $revId ): [ int $rev_deleted, UserIdentity $user ]
* @param PageIdentity $page The page this Revision is associated with. * @param PageIdentity $page The page this Revision is associated with.
* @param UserIdentity $user * @param UserIdentity $user
* @param CommentStoreComment $comment * @param CommentStoreComment $comment
@ -57,7 +56,7 @@ class RevisionStoreCacheRecord extends RevisionStoreRecord {
* @param bool|string $dbDomain DB domain of the relevant wiki or false for the current one. * @param bool|string $dbDomain DB domain of the relevant wiki or false for the current one.
*/ */
public function __construct( public function __construct(
$callback, callable $callback,
PageIdentity $page, PageIdentity $page,
UserIdentity $user, UserIdentity $user,
CommentStoreComment $comment, CommentStoreComment $comment,
@ -102,31 +101,15 @@ class RevisionStoreCacheRecord extends RevisionStoreRecord {
* @throws RevisionAccessException if the row could not be loaded * @throws RevisionAccessException if the row could not be loaded
*/ */
private function loadFreshRow() { private function loadFreshRow() {
$freshRow = call_user_func( $this->mCallback, $this->mId ); list( $freshRevDeleted, $freshUser ) = call_user_func( $this->mCallback, $this->mId );
// Set to null to ensure we do not make unnecessary queries for subsequent getter calls, // Set to null to ensure we do not make unnecessary queries for subsequent getter calls,
// and to allow the closure to be freed. // and to allow the closure to be freed.
$this->mCallback = null; $this->mCallback = null;
if ( $freshRow ) { if ( $freshRevDeleted !== null && $freshUser !== null ) {
$this->mDeleted = intval( $freshRow->rev_deleted ); $this->mDeleted = intval( $freshRevDeleted );
$this->mUser = $freshUser;
try {
$this->mUser = User::newFromAnyId(
$freshRow->rev_user ?? null,
$freshRow->rev_user_text ?? null,
$freshRow->rev_actor ?? null
);
} catch ( InvalidArgumentException $ex ) {
wfWarn(
__METHOD__
. ': '
. $this->mPage
. ': '
. $ex->getMessage()
);
$this->mUser = new UserIdentityValue( 0, 'Unknown user', 0 );
}
} else { } else {
throw new RevisionAccessException( throw new RevisionAccessException(
'Unable to load fresh row for rev_id: ' . $this->mId 'Unable to load fresh row for rev_id: ' . $this->mId

View file

@ -177,7 +177,6 @@ $wgAutoloadClasses += [
# tests/phpunit/includes/Revision # tests/phpunit/includes/Revision
'MediaWiki\Tests\Revision\RevisionSlotsTest' => "$testDir/phpunit/includes/Revision/RevisionSlotsTest.php", 'MediaWiki\Tests\Revision\RevisionSlotsTest' => "$testDir/phpunit/includes/Revision/RevisionSlotsTest.php",
'MediaWiki\Tests\Revision\RevisionStoreDbTestBase' => "$testDir/phpunit/includes/Revision/RevisionStoreDbTestBase.php", 'MediaWiki\Tests\Revision\RevisionStoreDbTestBase' => "$testDir/phpunit/includes/Revision/RevisionStoreDbTestBase.php",
'MediaWiki\Tests\Revision\RevisionStoreRecordTest' => "$testDir/phpunit/includes/Revision/RevisionStoreRecordTest.php",
# test/phpunit/includes/user # test/phpunit/includes/user
'UserOptionsLookupTest' => "$testDir/phpunit/includes/user/UserOptionsLookupTest.php", 'UserOptionsLookupTest' => "$testDir/phpunit/includes/user/UserOptionsLookupTest.php",

View file

@ -1,17 +1,17 @@
<?php <?php
namespace MediaWiki\Tests\Revision; namespace MediaWiki\Tests\Unit\Revision;
use CommentStoreComment; use CommentStoreComment;
use MediaWiki\Page\PageIdentity;
use MediaWiki\Page\PageIdentityValue;
use MediaWiki\Revision\RevisionRecord; use MediaWiki\Revision\RevisionRecord;
use MediaWiki\Revision\RevisionSlots; use MediaWiki\Revision\RevisionSlots;
use MediaWiki\Revision\RevisionStoreCacheRecord; use MediaWiki\Revision\RevisionStoreCacheRecord;
use MediaWiki\Revision\RevisionStoreRecord; use MediaWiki\Revision\RevisionStoreRecord;
use MediaWiki\Revision\SlotRecord; use MediaWiki\Revision\SlotRecord;
use MediaWiki\Tests\Unit\Revision\RevisionRecordTests;
use MediaWiki\User\UserIdentityValue; use MediaWiki\User\UserIdentityValue;
use TextContent; use TextContent;
use Title;
/** /**
* @covers \MediaWiki\Revision\RevisionStoreCacheRecord * @covers \MediaWiki\Revision\RevisionStoreCacheRecord
@ -29,8 +29,7 @@ class RevisionStoreCacheRecordTest extends RevisionStoreRecordTest {
* @return RevisionStoreRecord * @return RevisionStoreRecord
*/ */
protected function newRevision( array $rowOverrides = [], $callback = false ) { protected function newRevision( array $rowOverrides = [], $callback = false ) {
$title = Title::newFromText( 'Dummy' ); $title = new PageIdentityValue( 17, NS_MAIN, 'Dummy', PageIdentity::LOCAL );
$title->resetArticleID( 17 );
$user = new UserIdentityValue( 11, 'Tester', 0 ); $user = new UserIdentityValue( 11, 'Tester', 0 );
$comment = CommentStoreComment::newUnsavedComment( 'Hello World' ); $comment = CommentStoreComment::newUnsavedComment( 'Hello World' );
@ -41,7 +40,7 @@ class RevisionStoreCacheRecordTest extends RevisionStoreRecordTest {
$row = [ $row = [
'rev_id' => '7', 'rev_id' => '7',
'rev_page' => strval( $title->getArticleID() ), 'rev_page' => '17',
'rev_timestamp' => '20200101000000', 'rev_timestamp' => '20200101000000',
'rev_deleted' => 0, 'rev_deleted' => 0,
'rev_minor_edit' => 0, 'rev_minor_edit' => 0,
@ -56,7 +55,11 @@ class RevisionStoreCacheRecordTest extends RevisionStoreRecordTest {
if ( !$callback ) { if ( !$callback ) {
$callback = function ( $revId ) use ( $row ) { $callback = function ( $revId ) use ( $row ) {
return (object)$row; $this->assertSame( 7, $revId );
return [
$row['rev_deleted'],
new UserIdentityValue( intval( $row['rev_user'] ), 'Bla', 10 )
];
}; };
} }
@ -74,14 +77,14 @@ class RevisionStoreCacheRecordTest extends RevisionStoreRecordTest {
// Provide a callback that returns non-default values. Asserting the revision returns // Provide a callback that returns non-default values. Asserting the revision returns
// these values confirms callback execution and behavior. Also confirm the callback // these values confirms callback execution and behavior. Also confirm the callback
// is only invoked once, even for multiple getter calls. // is only invoked once, even for multiple getter calls.
$rowOverrides = [
'rev_deleted' => RevisionRecord::DELETED_TEXT,
'rev_user' => 12,
];
$callbackInvoked = 0; $callbackInvoked = 0;
$callback = function ( $revId ) use ( &$callbackInvoked, $rowOverrides ) { $callback = function ( $revId ) use ( &$callbackInvoked ) {
$this->assertSame( 7, $revId );
$callbackInvoked++; $callbackInvoked++;
return (object)$rowOverrides; return [
RevisionRecord::DELETED_TEXT,
new UserIdentityValue( 12, 'Lalala', 24 )
];
}; };
$rev = $this->newRevision( [], $callback ); $rev = $this->newRevision( [], $callback );