Localisation updates from https://translatewiki.net.
[mediawiki.git] / tests / phpunit / includes / cache / LinkBatchTest.php
blob2358a1bb8e059bedf105c2607c044ddfe361214d
1 <?php
3 use MediaWiki\Cache\CacheKeyHelper;
4 use MediaWiki\Cache\GenderCache;
5 use MediaWiki\Cache\LinkBatch;
6 use MediaWiki\Cache\LinkCache;
7 use MediaWiki\Language\Language;
8 use MediaWiki\Linker\LinksMigration;
9 use MediaWiki\Linker\LinkTarget;
10 use MediaWiki\Logger\LoggerFactory;
11 use MediaWiki\Page\PageReference;
12 use MediaWiki\Page\PageReferenceValue;
13 use MediaWiki\Title\Title;
14 use MediaWiki\Title\TitleFormatter;
15 use MediaWiki\Title\TitleValue;
16 use Wikimedia\Rdbms\IConnectionProvider;
18 /**
19 * @group Database
20 * @group Cache
21 * @covers \MediaWiki\Cache\LinkBatch
23 class LinkBatchTest extends MediaWikiIntegrationTestCase {
25 /**
26 * @covers \MediaWiki\Cache\LinkBatch::__construct()
27 * @covers \MediaWiki\Cache\LinkBatch::getSize()
28 * @covers \MediaWiki\Cache\LinkBatch::isEmpty()
30 public function testConstructEmptyWithServices() {
31 $batch = new LinkBatch(
32 [],
33 $this->createMock( LinkCache::class ),
34 $this->createMock( TitleFormatter::class ),
35 $this->createMock( Language::class ),
36 $this->createMock( GenderCache::class ),
37 $this->createMock( IConnectionProvider::class ),
38 $this->createMock( LinksMigration::class ),
39 LoggerFactory::getInstance( 'LinkBatch' )
42 $this->assertTrue( $batch->isEmpty() );
43 $this->assertSame( 0, $batch->getSize() );
46 /**
47 * @covers \MediaWiki\Cache\LinkBatch::__construct()
48 * @covers \MediaWiki\Cache\LinkBatch::getSize()
49 * @covers \MediaWiki\Cache\LinkBatch::isEmpty()
51 public function testConstructWithServices() {
52 $batch = new LinkBatch(
54 new TitleValue( NS_MAIN, 'Foo' ),
55 new TitleValue( NS_TALK, 'Bar' ),
57 $this->createMock( LinkCache::class ),
58 $this->createMock( TitleFormatter::class ),
59 $this->createMock( Language::class ),
60 $this->createMock( GenderCache::class ),
61 $this->createMock( IConnectionProvider::class ),
62 $this->createMock( LinksMigration::class ),
63 LoggerFactory::getInstance( 'LinkBatch' )
66 $this->assertFalse( $batch->isEmpty() );
67 $this->assertSame( 2, $batch->getSize() );
70 /**
71 * @param iterable<LinkTarget>|iterable<PageReference> $objects
73 * @return LinkBatch
74 * @throws Exception
76 private function newLinkBatch( $objects = [] ) {
77 return new LinkBatch(
78 $objects,
79 $this->createMock( LinkCache::class ),
80 $this->createMock( TitleFormatter::class ),
81 $this->createMock( Language::class ),
82 $this->createMock( GenderCache::class ),
83 $this->getServiceContainer()->getConnectionProvider(),
84 $this->getServiceContainer()->getLinksMigration(),
85 LoggerFactory::getInstance( 'LinkBatch' )
89 /**
90 * @covers \MediaWiki\Cache\LinkBatch::addObj()
91 * @covers \MediaWiki\Cache\LinkBatch::getSize()
93 public function testAddObj() {
94 $batch = $this->newLinkBatch(
96 new TitleValue( NS_MAIN, 'Foo' ),
97 new PageReferenceValue( NS_USER, 'Foo', PageReference::LOCAL ),
101 $batch->addObj( new PageReferenceValue( NS_TALK, 'Bar', PageReference::LOCAL ) );
102 $batch->addObj( new TitleValue( NS_MAIN, 'Foo' ) );
104 $this->assertSame( 3, $batch->getSize() );
105 $this->assertCount( 3, $batch->getPageIdentities() );
109 * @covers \MediaWiki\Cache\LinkBatch::add()
110 * @covers \MediaWiki\Cache\LinkBatch::getSize()
112 public function testAdd() {
113 $batch = $this->newLinkBatch(
115 new TitleValue( NS_MAIN, 'Foo' )
119 $batch->add( NS_TALK, 'Bar' );
120 $batch->add( NS_MAIN, 'Foo' );
122 $this->assertSame( 2, $batch->getSize() );
123 $this->assertCount( 2, $batch->getPageIdentities() );
126 public function testExecute() {
127 $existing1 = $this->getExistingTestPage( __METHOD__ . '1' )->getTitle();
128 $existing2 = $this->getExistingTestPage( __METHOD__ . '2' )->getTitle();
129 $nonexisting1 = $this->getNonexistingTestPage( __METHOD__ . 'x' )->getTitle();
130 $nonexisting2 = $this->getNonexistingTestPage( __METHOD__ . 'y' )->getTitle();
132 $cache = $this->createMock( LinkCache::class );
134 $good = [];
135 $bad = [];
137 $cache->expects( $this->exactly( 2 ) )
138 ->method( 'addGoodLinkObjFromRow' )
139 ->willReturnCallback( static function ( TitleValue $title, $row ) use ( &$good ) {
140 $good["$title"] = $title;
141 } );
143 $cache->expects( $this->exactly( 2 ) )
144 ->method( 'addBadLinkObj' )
145 ->willReturnCallback( static function ( TitleValue $title ) use ( &$bad ) {
146 $bad["$title"] = $title;
147 } );
149 $services = $this->getServiceContainer();
151 $batch = new LinkBatch(
153 $cache,
154 // TODO: This would be even better with mocked dependencies
155 $services->getTitleFormatter(),
156 $services->getContentLanguage(),
157 $services->getGenderCache(),
158 $services->getConnectionProvider(),
159 $services->getLinksMigration(),
160 LoggerFactory::getInstance( 'LinkBatch' )
163 $batch->addObj( $existing1 );
164 $batch->addObj( $existing2 );
165 $batch->addObj( $nonexisting1 );
166 $batch->addObj( $nonexisting2 );
168 // Bad stuff, should be skipped!
169 $batch->add( NS_MAIN, '_X' );
170 $batch->add( NS_MAIN, 'X_' );
171 $batch->add( NS_MAIN, '' );
173 @$batch->execute();
175 $this->assertArrayHasKey( $existing1->getTitleValue()->__toString(), $good );
176 $this->assertArrayHasKey( $existing2->getTitleValue()->__toString(), $good );
178 $this->assertArrayHasKey( $nonexisting1->getTitleValue()->__toString(), $bad );
179 $this->assertArrayHasKey( $nonexisting2->getTitleValue()->__toString(), $bad );
181 $expected = array_map(
182 [ CacheKeyHelper::class, 'getKeyForPage' ],
183 [ $existing1, $existing2, $nonexisting1, $nonexisting2 ]
186 $actual = array_map(
187 [ CacheKeyHelper::class, 'getKeyForPage' ],
188 $batch->getPageIdentities()
191 sort( $expected );
192 sort( $actual );
194 $this->assertEquals( $expected, $actual );
197 public function testDoGenderQueryWithEmptyLinkBatch() {
198 $batch = new LinkBatch(
200 $this->createMock( LinkCache::class ),
201 $this->createMock( TitleFormatter::class ),
202 $this->createNoOpMock( Language::class ),
203 $this->createNoOpMock( GenderCache::class ),
204 $this->createMock( IConnectionProvider::class ),
205 $this->createMock( LinksMigration::class ),
206 LoggerFactory::getInstance( 'LinkBatch' )
209 $this->assertFalse( $batch->doGenderQuery() );
212 public function testDoGenderQueryWithLanguageWithoutGenderDistinction() {
213 $language = $this->createMock( Language::class );
214 $language->method( 'needsGenderDistinction' )->willReturn( false );
216 $batch = new LinkBatch(
218 $this->createMock( LinkCache::class ),
219 $this->createMock( TitleFormatter::class ),
220 $language,
221 $this->createNoOpMock( GenderCache::class ),
222 $this->createMock( IConnectionProvider::class ),
223 $this->createMock( LinksMigration::class ),
224 LoggerFactory::getInstance( 'LinkBatch' )
226 $batch->addObj(
227 new TitleValue( NS_MAIN, 'Foo' )
230 $this->assertFalse( $batch->doGenderQuery() );
233 public function testDoGenderQueryWithLanguageWithGenderDistinction() {
234 $language = $this->createMock( Language::class );
235 $language->method( 'needsGenderDistinction' )->willReturn( true );
237 $genderCache = $this->createMock( GenderCache::class );
238 $genderCache->expects( $this->once() )->method( 'doLinkBatch' );
240 $batch = new LinkBatch(
242 $this->createMock( LinkCache::class ),
243 $this->createMock( TitleFormatter::class ),
244 $language,
245 $genderCache,
246 $this->createMock( IConnectionProvider::class ),
247 $this->createMock( LinksMigration::class ),
248 LoggerFactory::getInstance( 'LinkBatch' )
250 $batch->addObj(
251 new TitleValue( NS_MAIN, 'Foo' )
254 $this->assertTrue( $batch->doGenderQuery() );
257 public static function provideBadObjects() {
258 yield 'null' => [ null ];
259 yield 'empty' => [ Title::makeTitle( NS_MAIN, '' ) ];
260 yield 'bad user' => [ Title::makeTitle( NS_USER, '#12345' ) ];
261 yield 'section' => [ new TitleValue( NS_MAIN, '', '#See_also' ) ];
262 yield 'special' => [ new TitleValue( NS_SPECIAL, 'RecentChanges' ) ];
266 * @dataProvider provideBadObjects
268 public function testAddBadObj( $obj ) {
269 $linkBatch = $this->newLinkBatch();
270 $linkBatch->addObj( $obj );
271 $linkBatch->execute();
272 $this->addToAssertionCount( 1 );
275 public static function provideBadDBKeys() {
276 yield 'empty' => [ '' ];
277 yield 'section' => [ '#See_also' ];
278 yield 'pipe' => [ 'foo|bar' ];
282 * @dataProvider provideBadDBKeys
284 public function testAddBadDBKeys( $key ) {
285 $linkBatch = $this->newLinkBatch();
286 $linkBatch->add( NS_MAIN, $key );
287 $linkBatch->execute();
288 $this->addToAssertionCount( 1 );