X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=tests%2Fphpunit%2Fincludes%2Fwatcheditem%2FWatchedItemStoreUnitTest.php;h=82308de4eaf7cf5627418595544a9416d308933a;hp=6249c49961b87dbd6b2c2412fdb3e5930f4a0caf;hb=a3cd158d8433e41cbeb299f0e268dfef363b2afd;hpb=ceb5637e3d0b052978efd9583f808a43527b5765 diff --git a/tests/phpunit/includes/watcheditem/WatchedItemStoreUnitTest.php b/tests/phpunit/includes/watcheditem/WatchedItemStoreUnitTest.php index 6249c49961..82308de4ea 100644 --- a/tests/phpunit/includes/watcheditem/WatchedItemStoreUnitTest.php +++ b/tests/phpunit/includes/watcheditem/WatchedItemStoreUnitTest.php @@ -1,8 +1,10 @@ getMock(); $mock->expects( $this->any() ) ->method( 'makeKey' ) - ->will( $this->returnCallback( function () { - return implode( ':', func_get_args() ); + ->will( $this->returnCallback( function ( ...$args ) { + return implode( ':', $args ); } ) ); return $mock; } @@ -109,25 +111,42 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } /** - * @param int $id - * @return PHPUnit_Framework_MockObject_MockObject|User + * Assumes that only getSubjectPage and getTalkPage will ever be called, and everything passed + * to them will have namespace 0. */ - private function getMockNonAnonUserWithId( $id ) { - $mock = $this->createMock( User::class ); - $mock->expects( $this->any() ) - ->method( 'isAnon' ) - ->will( $this->returnValue( false ) ); - $mock->expects( $this->any() ) - ->method( 'getId' ) - ->will( $this->returnValue( $id ) ); + private function getMockNsInfo() : NamespaceInfo { + $mock = $this->createMock( NamespaceInfo::class ); + $mock->method( 'getSubjectPage' )->will( $this->returnArgument( 0 ) ); + $mock->method( 'getTalkPage' )->will( $this->returnCallback( + function ( $target ) { + return new TitleValue( 1, $target->getDbKey() ); + } + ) ); + $mock->expects( $this->never() ) + ->method( $this->anythingBut( 'getSubjectPage', 'getTalkPage' ) ); return $mock; } /** - * @return User + * No methods may be called except provided callbacks, if any. + * + * @param array $callbacks Keys are method names, values are callbacks + * @param array $counts Keys are method names, values are expected number of times to be called + * (default is any number is okay) */ - private function getAnonUser() { - return User::newFromName( 'Anon_User' ); + private function getMockRevisionLookup( + array $callbacks = [], array $counts = [] + ) : RevisionLookup { + $mock = $this->createMock( RevisionLookup::class ); + foreach ( $callbacks as $method => $callback ) { + $count = isset( $counts[$method] ) ? $this->exactly( $counts[$method] ) : $this->any(); + $mock->expects( $count ) + ->method( $method ) + ->will( $this->returnCallback( $callbacks[$method] ) ); + } + $mock->expects( $this->never() ) + ->method( $this->anythingBut( ...array_keys( $callbacks ) ) ); + return $mock; } private function getFakeRow( array $rowValues ) { @@ -138,24 +157,33 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { return $fakeRow; } - private function newWatchedItemStore( - LBFactory $lbFactory, - JobQueueGroup $queueGroup, - HashBagOStuff $cache, - ReadOnlyMode $readOnlyMode - ) { + /** + * @param array $mocks Associative array providing mocks to use when constructing the + * WatchedItemStore. Anything not provided will fall back to a default. Valid keys: + * * lbFactory + * * db + * * queueGroup + * * cache + * * readOnlyMode + * * nsInfo + * * revisionLookup + */ + private function newWatchedItemStore( array $mocks = [] ) : WatchedItemStore { return new WatchedItemStore( - $lbFactory, - $queueGroup, + $mocks['lbFactory'] ?? + $this->getMockLBFactory( $mocks['db'] ?? $this->getMockDb() ), + $mocks['queueGroup'] ?? $this->getMockJobQueueGroup(), new HashBagOStuff(), - $cache, - $readOnlyMode, - 1000 + $mocks['cache'] ?? $this->getMockCache(), + $mocks['readOnlyMode'] ?? $this->getMockReadOnlyMode(), + 1000, + $mocks['nsInfo'] ?? $this->getMockNsInfo(), + $mocks['revisionLookup'] ?? $this->getMockRevisionLookup() ); } public function testClearWatchedItems() { - $user = $this->getMockNonAnonUserWithId( 7 ); + $user = new UserIdentityValue( 7, 'MockUser', 0 ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->once() ) @@ -184,12 +212,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->method( 'delete' ) ->with( 'RM-KEY' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); TestingAccessWrapper::newFromObject( $store ) ->cacheIndex = [ 0 => [ 'F' => [ 7 => 'RM-KEY', 9 => 'KEEP-KEY' ] ] ]; @@ -197,7 +220,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } public function testClearWatchedItems_tooManyItemsWatched() { - $user = $this->getMockNonAnonUserWithId( 7 ); + $user = new UserIdentityValue( 7, 'MockUser', 0 ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->once() ) @@ -217,18 +240,13 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->clearUserWatchedItems( $user ) ); } public function testCountWatchedItems() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->exactly( 1 ) ) @@ -248,12 +266,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( 12, $store->countWatchedItems( $user ) ); } @@ -280,12 +293,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( 7, $store->countWatchers( $titleValue ) ); } @@ -333,12 +341,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $expected = [ 0 => [ 'SomeDbKey' => 100, 'OtherDbKey' => 300 ], @@ -401,12 +404,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $expected = [ 0 => [ 'SomeDbKey' => 100, 'OtherDbKey' => 300 ], @@ -451,12 +449,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( 7, $store->countVisitingWatchers( $titleValue, '111' ) ); } @@ -534,12 +527,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $expected = [ 0 => [ 'SomeDbKey' => 100, 'OtherDbKey' => 300 ], @@ -640,12 +628,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $expected = [ 0 => [ @@ -695,12 +678,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $expected = [ 0 => [ 'SomeDbKey' => 0, 'OtherDbKey' => 0 ], @@ -713,7 +691,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } public function testCountUnreadNotifications() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->exactly( 1 ) ) @@ -734,12 +712,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( 9, $store->countUnreadNotifications( $user ) ); } @@ -748,7 +721,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { * @dataProvider provideIntWithDbUnsafeVersion */ public function testCountUnreadNotifications_withUnreadLimit_overLimit( $limit ) { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->exactly( 1 ) ) @@ -770,12 +743,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertSame( true, @@ -787,7 +755,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { * @dataProvider provideIntWithDbUnsafeVersion */ public function testCountUnreadNotifications_withUnreadLimit_underLimit( $limit ) { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->exactly( 1 ) ) @@ -809,12 +777,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( 9, @@ -841,16 +804,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ) ->will( $this->returnValue( new FakeResultWrapper( [] ) ) ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $this->getMockCache(), - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb ] ); $store->duplicateEntry( - Title::newFromText( 'Old_Title' ), - Title::newFromText( 'New_Title' ) + new TitleValue( 0, 'Old_Title' ), + new TitleValue( 0, 'New_Title' ) ); } @@ -901,16 +859,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $store->duplicateEntry( - Title::newFromText( 'Old_Title' ), - Title::newFromText( 'New_Title' ) + new TitleValue( 0, 'Old_Title' ), + new TitleValue( 0, 'New_Title' ) ); } @@ -949,22 +902,17 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $store->duplicateAllAssociatedEntries( - Title::newFromText( 'Old_Title' ), - Title::newFromText( 'New_Title' ) + new TitleValue( 0, 'Old_Title' ), + new TitleValue( 0, 'New_Title' ) ); } public function provideLinkTargetPairs() { return [ - [ Title::newFromText( 'Old_Title' ), Title::newFromText( 'New_Title' ) ], + [ new TitleValue( 0, 'Old_Title' ), new TitleValue( 0, 'New_Title' ) ], [ new TitleValue( 0, 'Old_Title' ), new TitleValue( 0, 'New_Title' ) ], ]; } @@ -1044,12 +992,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $store->duplicateAllAssociatedEntries( $oldTarget, @@ -1078,16 +1021,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->method( 'delete' ) ->with( '0:Some_Page:1' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $store->addWatch( - $this->getMockNonAnonUserWithId( 1 ), - Title::newFromText( 'Some_Page' ) + new UserIdentityValue( 1, 'MockUser', 0 ), + new TitleValue( 0, 'Some_Page' ) ); } @@ -1100,30 +1038,21 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() ) ->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $store->addWatch( - $this->getAnonUser(), - Title::newFromText( 'Some_Page' ) + new UserIdentityValue( 0, 'AnonUser', 0 ), + new TitleValue( 0, 'Some_Page' ) ); } public function testAddWatchBatchForUser_readOnlyDBReturnsFalse() { $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $this->getMockDb() ), - $this->getMockJobQueueGroup(), - $this->getMockCache(), - $this->getMockReadOnlyMode( true ) - ); + [ 'readOnlyMode' => $this->getMockReadOnlyMode( true ) ] ); $this->assertFalse( $store->addWatchBatchForUser( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), [ new TitleValue( 0, 'Some_Page' ), new TitleValue( 1, 'Some_Page' ) ] ) ); @@ -1165,14 +1094,9 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->method( 'delete' ) ->with( '1:Some_Page:1' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); - $mockUser = $this->getMockNonAnonUserWithId( 1 ); + $mockUser = new UserIdentityValue( 1, 'MockUser', 0 ); $this->assertTrue( $store->addWatchBatchForUser( @@ -1191,23 +1115,18 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() ) ->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->addWatchBatchForUser( - $this->getAnonUser(), + new UserIdentityValue( 0, 'AnonUser', 0 ), [ new TitleValue( 0, 'Other_Page' ) ] ) ); } public function testAddWatchBatchReturnsTrue_whenGivenEmptyList() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->never() ) ->method( 'insert' ); @@ -1216,12 +1135,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() ) ->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertTrue( $store->addWatchBatchForUser( $user, [] ) @@ -1252,15 +1166,10 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { '0:SomeDbKey:1' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $watchedItem = $store->loadWatchedItem( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ); $this->assertInstanceOf( WatchedItem::class, $watchedItem ); @@ -1288,16 +1197,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->loadWatchedItem( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ) ); @@ -1312,16 +1216,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->loadWatchedItem( - $this->getAnonUser(), + new UserIdentityValue( 0, 'AnonUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ) ); @@ -1362,18 +1261,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { [ '1:SomeDbKey:1' ] ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); - $titleValue = new TitleValue( 0, 'SomeDbKey' ); $this->assertTrue( $store->removeWatch( - $this->getMockNonAnonUserWithId( 1 ), - Title::newFromTitleValue( $titleValue ) + new UserIdentityValue( 1, 'MockUser', 0 ), + new TitleValue( 0, 'SomeDbKey' ) ) ); } @@ -1414,18 +1307,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { [ '1:SomeDbKey:1' ] ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); - $titleValue = new TitleValue( 0, 'SomeDbKey' ); $this->assertFalse( $store->removeWatch( - $this->getMockNonAnonUserWithId( 1 ), - Title::newFromTitleValue( $titleValue ) + new UserIdentityValue( 1, 'MockUser', 0 ), + new TitleValue( 0, 'SomeDbKey' ) ) ); } @@ -1440,16 +1327,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() ) ->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->removeWatch( - $this->getAnonUser(), + new UserIdentityValue( 0, 'AnonUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ) ); @@ -1486,15 +1368,10 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { '0:SomeDbKey:1' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $watchedItem = $store->getWatchedItem( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ); $this->assertInstanceOf( WatchedItem::class, $watchedItem ); @@ -1508,7 +1385,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockDb->expects( $this->never() ) ->method( 'selectRow' ); - $mockUser = $this->getMockNonAnonUserWithId( 1 ); + $mockUser = new UserIdentityValue( 1, 'MockUser', 0 ); $linkTarget = new TitleValue( 0, 'SomeDbKey' ); $cachedItem = new WatchedItem( $mockUser, $linkTarget, '20151212010101' ); @@ -1522,12 +1399,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ) ->will( $this->returnValue( $cachedItem ) ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( $cachedItem, @@ -1561,16 +1433,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->with( '0:SomeDbKey:1' ) ->will( $this->returnValue( false ) ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->getWatchedItem( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ) ); @@ -1586,16 +1453,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->getWatchedItem( - $this->getAnonUser(), + new UserIdentityValue( 0, 'AnonUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ) ); @@ -1628,13 +1490,8 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'set' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); - $user = $this->getMockNonAnonUserWithId( 1 ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $watchedItems = $store->getWatchedItemsForUser( $user ); @@ -1667,7 +1524,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockDb = $this->getMockDb(); $mockCache = $this->getMockCache(); $mockLoadBalancer = $this->getMockLBFactory( $mockDb, $dbType ); - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $mockDb->expects( $this->once() ) ->method( 'select' ) @@ -1681,11 +1538,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->will( $this->returnValue( [] ) ); $store = $this->newWatchedItemStore( - $mockLoadBalancer, - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + [ 'lbFactory' => $mockLoadBalancer, 'cache' => $mockCache ] ); $watchedItems = $store->getWatchedItemsForUser( $user, @@ -1695,16 +1548,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } public function testGetWatchedItemsForUser_badSortOptionThrowsException() { - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $this->getMockDb() ), - $this->getMockJobQueueGroup(), - $this->getMockCache(), - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore(); $this->setExpectedException( InvalidArgumentException::class ); $store->getWatchedItemsForUser( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), [ 'sort' => 'foo' ] ); } @@ -1738,16 +1586,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { '0:SomeDbKey:1' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertTrue( $store->isWatched( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ) ); @@ -1776,16 +1619,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->with( '0:SomeDbKey:1' ) ->will( $this->returnValue( false ) ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->isWatched( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ) ); @@ -1801,16 +1639,11 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->isWatched( - $this->getAnonUser(), + new UserIdentityValue( 0, 'AnonUser', 0 ), new TitleValue( 0, 'SomeDbKey' ) ) ); @@ -1870,19 +1703,15 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( [ 0 => [ 'SomeDbKey' => '20151212010101', ], 1 => [ 'AnotherDbKey' => null, ], ], - $store->getNotificationTimestampsBatch( $this->getMockNonAnonUserWithId( 1 ), $targets ) + $store->getNotificationTimestampsBatch( + new UserIdentityValue( 1, 'MockUser', 0 ), $targets ) ); } @@ -1922,18 +1751,14 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( [ 0 => [ 'OtherDbKey' => false, ], ], - $store->getNotificationTimestampsBatch( $this->getMockNonAnonUserWithId( 1 ), $targets ) + $store->getNotificationTimestampsBatch( + new UserIdentityValue( 1, 'MockUser', 0 ), $targets ) ); } @@ -1943,7 +1768,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { new TitleValue( 1, 'AnotherDbKey' ), ]; - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $cachedItem = new WatchedItem( $user, $targets[0], '20151212010101' ); $mockDb = $this->getMockDb(); @@ -1985,12 +1810,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( [ @@ -2007,7 +1827,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { new TitleValue( 1, 'AnotherDbKey' ), ]; - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $cachedItems = [ new WatchedItem( $user, $targets[0], '20151212010101' ), new WatchedItem( $user, $targets[1], null ), @@ -2027,12 +1847,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( [ @@ -2055,19 +1870,15 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache = $this->getMockCache(); $mockCache->expects( $this->never() )->method( $this->anything() ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( [ 0 => [ 'SomeDbKey' => false, ], 1 => [ 'AnotherDbKey' => false, ], ], - $store->getNotificationTimestampsBatch( $this->getAnonUser(), $targets ) + $store->getNotificationTimestampsBatch( + new UserIdentityValue( 0, 'AnonUser', 0 ), $targets ) ); } @@ -2081,17 +1892,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->resetNotificationTimestamp( - $this->getAnonUser(), - Title::newFromText( 'SomeDbKey' ) + new UserIdentityValue( 0, 'AnonUser', 0 ), + new TitleValue( 0, 'SomeDbKey' ) ) ); } @@ -2116,24 +1922,19 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'set' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertFalse( $store->resetNotificationTimestamp( - $this->getMockNonAnonUserWithId( 1 ), - Title::newFromText( 'SomeDbKey' ) + new UserIdentityValue( 1, 'MockUser', 0 ), + new TitleValue( 0, 'SomeDbKey' ) ) ); } public function testResetNotificationTimestamp_item() { - $user = $this->getMockNonAnonUserWithId( 1 ); - $title = Title::newFromText( 'SomeDbKey' ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); + $title = new TitleValue( 0, 'SomeDbKey' ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->once() ) @@ -2170,12 +1971,22 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { // don't run } ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $mockQueueGroup, - $mockCache, - $this->getMockReadOnlyMode() - ); + // We don't care if these methods actually do anything here + $mockRevisionLookup = $this->getMockRevisionLookup( [ + 'getRevisionByTitle' => function () { + return null; + }, + 'getTimestampFromId' => function () { + return '00000000000000'; + }, + ] ); + + $store = $this->newWatchedItemStore( [ + 'db' => $mockDb, + 'queueGroup' => $mockQueueGroup, + 'cache' => $mockCache, + 'revisionLookup' => $mockRevisionLookup, + ] ); $this->assertTrue( $store->resetNotificationTimestamp( @@ -2186,8 +1997,8 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } public function testResetNotificationTimestamp_noItemForced() { - $user = $this->getMockNonAnonUserWithId( 1 ); - $title = Title::newFromText( 'SomeDbKey' ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); + $title = new TitleValue( 0, 'SomeDbKey' ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->never() ) @@ -2201,12 +2012,23 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->with( '0:SomeDbKey:1' ); $mockQueueGroup = $this->getMockJobQueueGroup(); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $mockQueueGroup, - $mockCache, - $this->getMockReadOnlyMode() - ); + + // We don't care if these methods actually do anything here + $mockRevisionLookup = $this->getMockRevisionLookup( [ + 'getRevisionByTitle' => function () { + return null; + }, + 'getTimestampFromId' => function () { + return '00000000000000'; + }, + ] ); + + $store = $this->newWatchedItemStore( [ + 'db' => $mockDb, + 'queueGroup' => $mockQueueGroup, + 'cache' => $mockCache, + 'revisionLookup' => $mockRevisionLookup, + ] ); $mockQueueGroup->expects( $this->any() ) ->method( 'lazyPush' ) @@ -2223,26 +2045,6 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ); } - /** - * @param string $text - * @param int $ns - * - * @return PHPUnit_Framework_MockObject_MockObject|Title - */ - private function getMockTitle( $text, $ns = 0 ) { - $title = $this->createMock( Title::class ); - $title->expects( $this->any() ) - ->method( 'getText' ) - ->will( $this->returnValue( str_replace( '_', ' ', $text ) ) ); - $title->expects( $this->any() ) - ->method( 'getDbKey' ) - ->will( $this->returnValue( str_replace( '_', ' ', $text ) ) ); - $title->expects( $this->any() ) - ->method( 'getNamespace' ) - ->will( $this->returnValue( $ns ) ); - return $title; - } - private function verifyCallbackJob( ActivityUpdateJob $job, LinkTarget $expectedTitle, @@ -2262,13 +2064,9 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } public function testResetNotificationTimestamp_oldidSpecifiedLatestRevisionForced() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $oldid = 22; - $title = $this->getMockTitle( 'SomeTitle' ); - $title->expects( $this->once() ) - ->method( 'getNextRevisionID' ) - ->with( $oldid ) - ->will( $this->returnValue( false ) ); + $title = new TitleValue( 0, 'SomeTitle' ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->never() ) @@ -2282,12 +2080,35 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->with( '0:SomeTitle:1' ); $mockQueueGroup = $this->getMockJobQueueGroup(); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $mockQueueGroup, - $mockCache, - $this->getMockReadOnlyMode() - ); + + $mockRevisionRecord = $this->createMock( RevisionRecord::class ); + $mockRevisionRecord->expects( $this->never() )->method( $this->anything() ); + + $mockRevisionLookup = $this->getMockRevisionLookup( [ + 'getTimestampFromId' => function () { + return '00000000000000'; + }, + 'getRevisionById' => function ( $id, $flags ) use ( $oldid, $mockRevisionRecord ) { + $this->assertSame( $oldid, $id ); + $this->assertSame( 0, $flags ); + return $mockRevisionRecord; + }, + 'getNextRevision' => + function ( $oldRev, $titleArg ) use ( $mockRevisionRecord, $title ) { + $this->assertSame( $mockRevisionRecord, $oldRev ); + $this->assertSame( $title, $titleArg ); + return false; + }, + ], [ + 'getNextRevision' => 1, + ] ); + + $store = $this->newWatchedItemStore( [ + 'db' => $mockDb, + 'queueGroup' => $mockQueueGroup, + 'cache' => $mockCache, + 'revisionLookup' => $mockRevisionLookup, + ] ); $mockQueueGroup->expects( $this->any() ) ->method( 'lazyPush' ) @@ -2315,13 +2136,15 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } public function testResetNotificationTimestamp_oldidSpecifiedNotLatestRevisionForced() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $oldid = 22; - $title = $this->getMockTitle( 'SomeDbKey' ); - $title->expects( $this->once() ) - ->method( 'getNextRevisionID' ) - ->with( $oldid ) - ->will( $this->returnValue( 33 ) ); + $title = new TitleValue( 0, 'SomeDbKey' ); + + $mockRevision = $this->createMock( RevisionRecord::class ); + $mockRevision->expects( $this->never() )->method( $this->anything() ); + + $mockNextRevision = $this->createMock( RevisionRecord::class ); + $mockNextRevision->expects( $this->never() )->method( $this->anything() ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->once() ) @@ -2349,12 +2172,34 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->with( '0:SomeDbKey:1' ); $mockQueueGroup = $this->getMockJobQueueGroup(); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $mockQueueGroup, - $mockCache, - $this->getMockReadOnlyMode() - ); + + $mockRevisionLookup = $this->getMockRevisionLookup( + [ + 'getTimestampFromId' => function ( $oldidParam ) use ( $oldid ) { + $this->assertSame( $oldid, $oldidParam ); + }, + 'getRevisionById' => function ( $id ) use ( $oldid, $mockRevision ) { + $this->assertSame( $oldid, $id ); + return $mockRevision; + }, + 'getNextRevision' => + function ( RevisionRecord $rev ) use ( $mockRevision, $mockNextRevision ) { + $this->assertSame( $mockRevision, $rev ); + return $mockNextRevision; + }, + ], + [ + 'getTimestampFromId' => 2, + 'getRevisionById' => 1, + 'getNextRevision' => 1, + ] + ); + $store = $this->newWatchedItemStore( [ + 'db' => $mockDb, + 'queueGroup' => $mockQueueGroup, + 'cache' => $mockCache, + 'revisionLookup' => $mockRevisionLookup, + ] ); $mockQueueGroup->expects( $this->any() ) ->method( 'lazyPush' ) @@ -2371,15 +2216,6 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } ) ); - $getTimestampCallCounter = 0; - $scopedOverrideRevision = $store->overrideRevisionGetTimestampFromIdCallback( - function ( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) { - $getTimestampCallCounter++; - $this->assertEquals( $title, $titleParam ); - $this->assertEquals( $oldid, $oldidParam ); - } - ); - $this->assertTrue( $store->resetNotificationTimestamp( $user, @@ -2388,19 +2224,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $oldid ) ); - $this->assertEquals( 2, $getTimestampCallCounter ); - - ScopedCallback::consume( $scopedOverrideRevision ); } public function testResetNotificationTimestamp_notWatchedPageForced() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $oldid = 22; - $title = $this->getMockTitle( 'SomeDbKey' ); - $title->expects( $this->once() ) - ->method( 'getNextRevisionID' ) - ->with( $oldid ) - ->will( $this->returnValue( 33 ) ); + $title = new TitleValue( 0, 'SomeDbKey' ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->once() ) @@ -2424,13 +2253,42 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->with( '0:SomeDbKey:1' ); $mockQueueGroup = $this->getMockJobQueueGroup(); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $mockQueueGroup, - $mockCache, - $this->getMockReadOnlyMode() + + $mockRevision = $this->createMock( RevisionRecord::class ); + $mockRevision->expects( $this->never() )->method( $this->anything() ); + + $mockNextRevision = $this->createMock( RevisionRecord::class ); + $mockNextRevision->expects( $this->never() )->method( $this->anything() ); + + $mockRevisionLookup = $this->getMockRevisionLookup( + [ + 'getTimestampFromId' => function ( $oldidParam ) use ( $oldid ) { + $this->assertSame( $oldid, $oldidParam ); + }, + 'getRevisionById' => function ( $id ) use ( $oldid, $mockRevision ) { + $this->assertSame( $oldid, $id ); + return $mockRevision; + }, + 'getNextRevision' => + function ( RevisionRecord $rev ) use ( $mockRevision, $mockNextRevision ) { + $this->assertSame( $mockRevision, $rev ); + return $mockNextRevision; + }, + ], + [ + 'getTimestampFromId' => 1, + 'getRevisionById' => 1, + 'getNextRevision' => 1, + ] ); + $store = $this->newWatchedItemStore( [ + 'db' => $mockDb, + 'queueGroup' => $mockQueueGroup, + 'cache' => $mockCache, + 'revisionLookup' => $mockRevisionLookup, + ] ); + $mockQueueGroup->expects( $this->any() ) ->method( 'lazyPush' ) ->will( $this->returnCallback( @@ -2457,13 +2315,9 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } public function testResetNotificationTimestamp_futureNotificationTimestampForced() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $oldid = 22; - $title = $this->getMockTitle( 'SomeDbKey' ); - $title->expects( $this->once() ) - ->method( 'getNextRevisionID' ) - ->with( $oldid ) - ->will( $this->returnValue( 33 ) ); + $title = new TitleValue( 0, 'SomeDbKey' ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->once() ) @@ -2491,13 +2345,42 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->with( '0:SomeDbKey:1' ); $mockQueueGroup = $this->getMockJobQueueGroup(); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $mockQueueGroup, - $mockCache, - $this->getMockReadOnlyMode() + + $mockRevision = $this->createMock( RevisionRecord::class ); + $mockRevision->expects( $this->never() )->method( $this->anything() ); + + $mockNextRevision = $this->createMock( RevisionRecord::class ); + $mockNextRevision->expects( $this->never() )->method( $this->anything() ); + + $mockRevisionLookup = $this->getMockRevisionLookup( + [ + 'getTimestampFromId' => function ( $oldidParam ) use ( $oldid ) { + $this->assertEquals( $oldid, $oldidParam ); + }, + 'getRevisionById' => function ( $id ) use ( $oldid, $mockRevision ) { + $this->assertSame( $oldid, $id ); + return $mockRevision; + }, + 'getNextRevision' => + function ( RevisionRecord $rev ) use ( $mockRevision, $mockNextRevision ) { + $this->assertSame( $mockRevision, $rev ); + return $mockNextRevision; + }, + ], + [ + 'getTimestampFromId' => 2, + 'getRevisionById' => 1, + 'getNextRevision' => 1, + ] ); + $store = $this->newWatchedItemStore( [ + 'db' => $mockDb, + 'queueGroup' => $mockQueueGroup, + 'cache' => $mockCache, + 'revisionLookup' => $mockRevisionLookup, + ] ); + $mockQueueGroup->expects( $this->any() ) ->method( 'lazyPush' ) ->will( $this->returnCallback( @@ -2513,15 +2396,6 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } ) ); - $getTimestampCallCounter = 0; - $scopedOverrideRevision = $store->overrideRevisionGetTimestampFromIdCallback( - function ( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) { - $getTimestampCallCounter++; - $this->assertEquals( $title, $titleParam ); - $this->assertEquals( $oldid, $oldidParam ); - } - ); - $this->assertTrue( $store->resetNotificationTimestamp( $user, @@ -2530,19 +2404,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $oldid ) ); - $this->assertEquals( 2, $getTimestampCallCounter ); - - ScopedCallback::consume( $scopedOverrideRevision ); } public function testResetNotificationTimestamp_futureNotificationTimestampNotForced() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $oldid = 22; - $title = $this->getMockTitle( 'SomeDbKey' ); - $title->expects( $this->once() ) - ->method( 'getNextRevisionID' ) - ->with( $oldid ) - ->will( $this->returnValue( 33 ) ); + $title = new TitleValue( 0, 'SomeDbKey' ); $mockDb = $this->getMockDb(); $mockDb->expects( $this->once() ) @@ -2570,12 +2437,40 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->with( '0:SomeDbKey:1' ); $mockQueueGroup = $this->getMockJobQueueGroup(); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $mockQueueGroup, - $mockCache, - $this->getMockReadOnlyMode() - ); + + $mockRevision = $this->createMock( RevisionRecord::class ); + $mockRevision->expects( $this->never() )->method( $this->anything() ); + + $mockNextRevision = $this->createMock( RevisionRecord::class ); + $mockNextRevision->expects( $this->never() )->method( $this->anything() ); + + $mockRevisionLookup = $this->getMockRevisionLookup( + [ + 'getTimestampFromId' => function ( $oldidParam ) use ( $oldid ) { + $this->assertEquals( $oldid, $oldidParam ); + }, + 'getRevisionById' => function ( $id ) use ( $oldid, $mockRevision ) { + $this->assertSame( $oldid, $id ); + return $mockRevision; + }, + 'getNextRevision' => + function ( RevisionRecord $rev ) use ( $mockRevision, $mockNextRevision ) { + $this->assertSame( $mockRevision, $rev ); + return $mockNextRevision; + }, + ], + [ + 'getTimestampFromId' => 2, + 'getRevisionById' => 1, + 'getNextRevision' => 1, + ] + ); + $store = $this->newWatchedItemStore( [ + 'db' => $mockDb, + 'queueGroup' => $mockQueueGroup, + 'cache' => $mockCache, + 'revisionLookup' => $mockRevisionLookup, + ] ); $mockQueueGroup->expects( $this->any() ) ->method( 'lazyPush' ) @@ -2592,15 +2487,6 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } ) ); - $getTimestampCallCounter = 0; - $scopedOverrideRevision = $store->overrideRevisionGetTimestampFromIdCallback( - function ( $titleParam, $oldidParam ) use ( &$getTimestampCallCounter, $title, $oldid ) { - $getTimestampCallCounter++; - $this->assertEquals( $title, $titleParam ); - $this->assertEquals( $oldid, $oldidParam ); - } - ); - $this->assertTrue( $store->resetNotificationTimestamp( $user, @@ -2609,77 +2495,47 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $oldid ) ); - $this->assertEquals( 2, $getTimestampCallCounter ); - - ScopedCallback::consume( $scopedOverrideRevision ); } public function testSetNotificationTimestampsForUser_anonUser() { - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $this->getMockDb() ), - $this->getMockJobQueueGroup(), - $this->getMockCache(), - $this->getMockReadOnlyMode() - ); - $this->assertFalse( $store->setNotificationTimestampsForUser( $this->getAnonUser(), '' ) ); + $store = $this->newWatchedItemStore(); + $this->assertFalse( $store->setNotificationTimestampsForUser( + new UserIdentityValue( 0, 'AnonUser', 0 ), '' ) ); } public function testSetNotificationTimestampsForUser_allRows() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $timestamp = '20100101010101'; - $mockDb = $this->getMockDb(); - $mockDb->expects( $this->once() ) - ->method( 'update' ) - ->with( - 'watchlist', - [ 'wl_notificationtimestamp' => 'TS' . $timestamp . 'TS' ], - [ 'wl_user' => 1 ] - ) - ->will( $this->returnValue( true ) ); - $mockDb->expects( $this->exactly( 1 ) ) - ->method( 'timestamp' ) - ->will( $this->returnCallback( function ( $value ) { - return 'TS' . $value . 'TS'; - } ) ); + $store = $this->newWatchedItemStore(); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $this->getMockCache(), - $this->getMockReadOnlyMode() - ); + // Note: This does not actually assert the job is correct + $callableCallCounter = 0; + $mockCallback = function ( $callable ) use ( &$callableCallCounter ) { + $callableCallCounter++; + $this->assertInternalType( 'callable', $callable ); + }; + $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback( $mockCallback ); $this->assertTrue( $store->setNotificationTimestampsForUser( $user, $timestamp ) ); + $this->assertEquals( 1, $callableCallCounter ); } public function testSetNotificationTimestampsForUser_nullTimestamp() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $timestamp = null; - $mockDb = $this->getMockDb(); - $mockDb->expects( $this->once() ) - ->method( 'update' ) - ->with( - 'watchlist', - [ 'wl_notificationtimestamp' => null ], - [ 'wl_user' => 1 ] - ) - ->will( $this->returnValue( true ) ); - $mockDb->expects( $this->exactly( 0 ) ) - ->method( 'timestamp' ) - ->will( $this->returnCallback( function ( $value ) { - return 'TS' . $value . 'TS'; - } ) ); + $store = $this->newWatchedItemStore(); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $this->getMockCache(), - $this->getMockReadOnlyMode() - ); + // Note: This does not actually assert the job is correct + $callableCallCounter = 0; + $mockCallback = function ( $callable ) use ( &$callableCallCounter ) { + $callableCallCounter++; + $this->assertInternalType( 'callable', $callable ); + }; + $scopedOverride = $store->overrideDeferredUpdatesAddCallableUpdateCallback( $mockCallback ); $this->assertTrue( $store->setNotificationTimestampsForUser( $user, $timestamp ) @@ -2687,7 +2543,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } public function testSetNotificationTimestampsForUser_specificTargets() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $timestamp = '20100101010101'; $targets = [ new TitleValue( 0, 'Foo' ), new TitleValue( 0, 'Bar' ) ]; @@ -2697,7 +2553,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->with( 'watchlist', [ 'wl_notificationtimestamp' => 'TS' . $timestamp . 'TS' ], - [ 'wl_user' => 1, 0 => 'makeWhereFrom2d return value' ] + [ 'wl_user' => 1, 'wl_namespace' => 0, 'wl_title' => [ 'Foo', 'Bar' ] ] ) ->will( $this->returnValue( true ) ); $mockDb->expects( $this->exactly( 1 ) ) @@ -2706,20 +2562,10 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { return 'TS' . $value . 'TS'; } ) ); $mockDb->expects( $this->once() ) - ->method( 'makeWhereFrom2d' ) - ->with( - [ [ 'Foo' => 1, 'Bar' => 1 ] ], - $this->isType( 'string' ), - $this->isType( 'string' ) - ) - ->will( $this->returnValue( 'makeWhereFrom2d return value' ) ); + ->method( 'affectedRows' ) + ->will( $this->returnValue( 2 ) ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $this->getMockCache(), - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb ] ); $this->assertTrue( $store->setNotificationTimestampsForUser( $user, $timestamp, $targets ) @@ -2758,17 +2604,12 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $this->assertEquals( [ 2, 3 ], $store->updateNotificationTimestamp( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), new TitleValue( 0, 'SomeDbKey' ), '20151212010101' ) @@ -2800,15 +2641,10 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { $mockCache->expects( $this->never() )->method( 'get' ); $mockCache->expects( $this->never() )->method( 'delete' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); $watchers = $store->updateNotificationTimestamp( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), new TitleValue( 0, 'SomeDbKey' ), '20151212010101' ); @@ -2817,7 +2653,7 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { } public function testUpdateNotificationTimestamp_clearsCachedItems() { - $user = $this->getMockNonAnonUserWithId( 1 ); + $user = new UserIdentityValue( 1, 'MockUser', 0 ); $titleValue = new TitleValue( 0, 'SomeDbKey' ); $mockDb = $this->getMockDb(); @@ -2845,18 +2681,13 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase { ->method( 'delete' ) ->with( '0:SomeDbKey:1' ); - $store = $this->newWatchedItemStore( - $this->getMockLBFactory( $mockDb ), - $this->getMockJobQueueGroup(), - $mockCache, - $this->getMockReadOnlyMode() - ); + $store = $this->newWatchedItemStore( [ 'db' => $mockDb, 'cache' => $mockCache ] ); // This will add the item to the cache $store->getWatchedItem( $user, $titleValue ); $store->updateNotificationTimestamp( - $this->getMockNonAnonUserWithId( 1 ), + new UserIdentityValue( 1, 'MockUser', 0 ), $titleValue, '20151212010101' );