wiki.techinc.nl/tests/phpunit/includes/cache/BacklinkCacheTest.php

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

154 lines
5.1 KiB
PHP
Raw Normal View History

<?php
use MediaWiki\Title\Title;
/**
* @group Database
* @group Cache
* @covers \MediaWiki\Cache\BacklinkCache
*/
class BacklinkCacheTest extends MediaWikiIntegrationTestCase {
private static $backlinkCacheTest;
public function addDBDataOnce() {
$this->insertPage( 'Template:BacklinkCacheTestA', 'wooooooo' );
$this->insertPage( 'Template:BacklinkCacheTestB', '{{BacklinkCacheTestA}}' );
self::$backlinkCacheTest = $this->insertPage( 'BacklinkCacheTest_1', '{{BacklinkCacheTestB}}' );
$this->insertPage( 'BacklinkCacheTest_2', '[[BacklinkCacheTest_1]] [[Image:test.png]]' );
$this->insertPage( 'BacklinkCacheTest_3', '[[BacklinkCacheTest_1]]' );
$this->insertPage( 'BacklinkCacheTest_4', '[[BacklinkCacheTest_1]]' );
$this->insertPage( 'BacklinkCacheTest_5', '[[BacklinkCacheTest_1]]' );
$cascade = 1;
$this->getServiceContainer()->getWikiPageFactory()->newFromTitle( self::$backlinkCacheTest['title'] )->doUpdateRestrictions(
[ 'edit' => 'sysop' ],
[],
$cascade,
'test',
$this->getTestSysop()->getUser()
);
}
public static function provideCasesForHasLink() {
return [
[ true, 'BacklinkCacheTest_1', 'pagelinks' ],
[ false, 'BacklinkCacheTest_2', 'pagelinks' ],
[ true, 'Image:test.png', 'imagelinks' ]
];
}
/**
* @dataProvider provideCasesForHasLink
* @covers \MediaWiki\Cache\BacklinkCache::hasLinks
*/
public function testHasLink( bool $expected, string $title, string $table, string $msg = '' ) {
$blcFactory = $this->getServiceContainer()->getBacklinkCacheFactory();
$backlinkCache = $blcFactory->getBacklinkCache( Title::newFromText( $title ) );
$this->assertEquals( $expected, $backlinkCache->hasLinks( $table ), $msg );
}
public static function provideCasesForGetNumLinks() {
return [
[ 4, 'BacklinkCacheTest_1', 'pagelinks' ],
[ 0, 'BacklinkCacheTest_2', 'pagelinks' ],
[ 1, 'Image:test.png', 'imagelinks' ],
];
}
/**
* @dataProvider provideCasesForGetNumLinks
* @covers \MediaWiki\Cache\BacklinkCache::getNumLinks
*/
Fix use of stale backlink partition cache If a template is created, and then used on a page, and then the template is updated, all within an hour, then the page_touched of the page is never updated and the user will always see the old template contents. This is because htmlCacheUpdate jobs are fully suppressed for one hour following template creation, due to the WAN backlink partition cache. So: * Revert 4f3efbf4065a9, so that htmlCacheUpdate jobs always do something regardless of the state of the partition cache. * Factor out the job queueing parts of WikiPage::onArticleCreate, ::onArticleDelete and ::onArticleEdit. Instead of queueing a job unconditionally, check for the existence of backlinks in a post-send deferred update. If there are none, don't queue the job. * It's convenient to use BacklinkCache::hasLinks(), however, it suffered from the same stale cache problem as BacklinkCache::partition(). It's a short and fast query, and code review shows that none of the callers are particularly performance sensitive. So, do not use the WAN cache in BacklinkCache::hasLinks(). * Since hasLinks() and getNumLinks() no longer share a significant amount of code, separate them. Remove the $max parameter from getNumLinks(), which only existed to support hasLinks() and has no other usages in codesearch. * Log a debug message when entering the post-send request stage, so that it's easier to confirm that no additional pre-send queries are done. * Add a regression test, confirmed to previously fail. Bug: T368006 Change-Id: Id5c7af6d4fcdbeb6724a9036133742c5f76624df
2024-06-25 01:22:35 +00:00
public function testGetNumLinks( int $numLinks, string $title, string $table ) {
$blcFactory = $this->getServiceContainer()->getBacklinkCacheFactory();
$backlinkCache = $blcFactory->getBacklinkCache( Title::newFromText( $title ) );
Fix use of stale backlink partition cache If a template is created, and then used on a page, and then the template is updated, all within an hour, then the page_touched of the page is never updated and the user will always see the old template contents. This is because htmlCacheUpdate jobs are fully suppressed for one hour following template creation, due to the WAN backlink partition cache. So: * Revert 4f3efbf4065a9, so that htmlCacheUpdate jobs always do something regardless of the state of the partition cache. * Factor out the job queueing parts of WikiPage::onArticleCreate, ::onArticleDelete and ::onArticleEdit. Instead of queueing a job unconditionally, check for the existence of backlinks in a post-send deferred update. If there are none, don't queue the job. * It's convenient to use BacklinkCache::hasLinks(), however, it suffered from the same stale cache problem as BacklinkCache::partition(). It's a short and fast query, and code review shows that none of the callers are particularly performance sensitive. So, do not use the WAN cache in BacklinkCache::hasLinks(). * Since hasLinks() and getNumLinks() no longer share a significant amount of code, separate them. Remove the $max parameter from getNumLinks(), which only existed to support hasLinks() and has no other usages in codesearch. * Log a debug message when entering the post-send request stage, so that it's easier to confirm that no additional pre-send queries are done. * Add a regression test, confirmed to previously fail. Bug: T368006 Change-Id: Id5c7af6d4fcdbeb6724a9036133742c5f76624df
2024-06-25 01:22:35 +00:00
$this->assertEquals( $numLinks, $backlinkCache->getNumLinks( $table ) );
}
public static function provideCasesForGetLinks() {
return [
[
[ 'BacklinkCacheTest_2', 'BacklinkCacheTest_3', 'BacklinkCacheTest_4', 'BacklinkCacheTest_5' ],
'BacklinkCacheTest_1',
'pagelinks'
],
[
[ 'BacklinkCacheTest_4', 'BacklinkCacheTest_5' ],
'BacklinkCacheTest_1',
'pagelinks',
'BacklinkCacheTest_4'
],
[
[ 'BacklinkCacheTest_2', 'BacklinkCacheTest_3' ],
'BacklinkCacheTest_1',
'pagelinks',
false,
'BacklinkCacheTest_3'
],
[
[ 'BacklinkCacheTest_3', 'BacklinkCacheTest_4' ],
'BacklinkCacheTest_1',
'pagelinks',
'BacklinkCacheTest_3',
'BacklinkCacheTest_4'
],
[ [ 'BacklinkCacheTest_2' ], 'BacklinkCacheTest_1', 'pagelinks', false, false, 1 ],
[ [], 'BacklinkCacheTest_2', 'pagelinks' ],
[ [ 'BacklinkCacheTest_2' ], 'Image:test.png', 'imagelinks' ],
];
}
/**
* @dataProvider provideCasesForGetLinks
* @covers \MediaWiki\Cache\BacklinkCache::getLinkPages
*/
public function testGetLinkPages(
array $expectedTitles, string $title, string $table, $startId = false, $endId = false, $max = INF
) {
$startId = $startId ? Title::newFromText( $startId )->getId() : false;
$endId = $endId ? Title::newFromText( $endId )->getId() : false;
$blcFactory = $this->getServiceContainer()->getBacklinkCacheFactory();
$backlinkCache = $blcFactory->getBacklinkCache( Title::newFromText( $title ) );
$titlesArray = iterator_to_array( $backlinkCache->getLinkPages( $table, $startId, $endId, $max ) );
$this->assertSameSize( $expectedTitles, $titlesArray );
$numOfTitles = count( $titlesArray );
for ( $i = 0; $i < $numOfTitles; $i++ ) {
$this->assertEquals( $expectedTitles[$i], $titlesArray[$i]->getDbKey() );
}
}
/**
* @covers \MediaWiki\Cache\BacklinkCache::partition
*/
public function testPartition() {
$targetId = $this->getServiceContainer()->getLinkTargetLookup()->acquireLinkTargetId(
Title::makeTitle( NS_MAIN, 'BLCTest1234' ),
$this->getDb()
);
$targetRow = [
'tl_target_id' => $targetId,
];
$this->getDb()->newInsertQueryBuilder()
->insertInto( 'templatelinks' )
->rows( [
[ 'tl_from' => 56890, 'tl_from_namespace' => 0 ] + $targetRow,
[ 'tl_from' => 56891, 'tl_from_namespace' => 0 ] + $targetRow,
[ 'tl_from' => 56892, 'tl_from_namespace' => 0 ] + $targetRow,
[ 'tl_from' => 56893, 'tl_from_namespace' => 0 ] + $targetRow,
[ 'tl_from' => 56894, 'tl_from_namespace' => 0 ] + $targetRow,
] )
->caller( __METHOD__ )
->execute();
$blcFactory = $this->getServiceContainer()->getBacklinkCacheFactory();
$backlinkCache = $blcFactory->getBacklinkCache( Title::makeTitle( NS_MAIN, 'BLCTest1234' ) );
$partition = $backlinkCache->partition( 'templatelinks', 2 );
$this->assertArrayEquals( [
[ false, 56891 ],
[ 56892, 56893 ],
[ 56894, false ]
], $partition );
}
}