Localisation updates from https://translatewiki.net.
[mediawiki.git] / tests / phpunit / includes / jobqueue / jobs / RefreshLinksJobTest.php
bloba4b8ad57bbf6044299c5ba3799db282c36d0e7e4
1 <?php
3 use MediaWiki\CommentStore\CommentStoreComment;
4 use MediaWiki\Content\Content;
5 use MediaWiki\Content\WikitextContent;
6 use MediaWiki\Page\PageAssertionException;
7 use MediaWiki\Title\Title;
8 use Wikimedia\Rdbms\Platform\ISQLPlatform;
9 use Wikimedia\Stats\StatsFactory;
11 /**
12 * @covers \RefreshLinksJob
14 * @group JobQueue
15 * @group Database
17 * @license GPL-2.0-or-later
18 * @author Addshore
20 class RefreshLinksJobTest extends MediaWikiIntegrationTestCase {
21 /** @var StatsFactory */
22 private $statsFactory;
24 protected function setUp(): void {
25 parent::setUp();
26 $this->statsFactory = StatsFactory::newNull();
27 $this->setService( 'StatsFactory', $this->statsFactory );
30 /**
31 * @param string $name
32 * @param Content[] $content
34 * @return WikiPage
36 private function createPage( $name, array $content ) {
37 $title = Title::makeTitle( $this->getDefaultWikitextNS(), $name );
38 $page = $this->getServiceContainer()->getWikiPageFactory()->newFromTitle( $title );
40 $updater = $page->newPageUpdater( $this->getTestUser()->getUser() );
42 foreach ( $content as $slot => $cnt ) {
43 $updater->setContent( $slot, $cnt );
46 $updater->saveRevision( CommentStoreComment::newUnsavedComment( 'Test' ) );
48 return $page;
51 // TODO: test multi-page
52 // TODO: test recursive
53 // TODO: test partition
55 public function testBadTitle() {
56 $specialBlankPage = Title::makeTitle( NS_SPECIAL, 'Blankpage' );
58 $this->expectException( PageAssertionException::class );
59 new RefreshLinksJob( $specialBlankPage, [] );
62 public function testRunForNonexistentPage() {
63 $nonexistentPage = $this->getNonexistingTestPage();
64 $job = new RefreshLinksJob( $nonexistentPage, [] );
65 $totalFailuresCounter = $this->statsFactory->getCounter( 'refreshlinks_failures_total' );
67 $result = $job->run();
69 $this->assertFalse( $result );
70 $this->assertSame( 1, $totalFailuresCounter->getSampleCount() );
73 public function testUpdateSuperseded() {
74 $page = $this->getExistingTestPage();
75 $job = new RefreshLinksJob( $page->getTitle(), [ 'rootJobTimestamp' => '20240101000000' ] );
76 $supersededUpdatesCounter = $this->statsFactory->getCounter( 'refreshlinks_superseded_updates_total' );
78 $result = $job->run();
80 $this->assertTrue( $result );
81 $this->assertSame( 1, $supersededUpdatesCounter->getSampleCount() );
84 public function testStaleRevision() {
85 $page = $this->getExistingTestPage();
86 $prevRev = $page->getRevisionRecord();
87 $this->editPage( $page, 'New content' );
89 $job = new RefreshLinksJob( $page->getTitle(), [ 'triggeringRevisionId' => $prevRev->getId() ] );
90 $totalFailuresCounter = $this->statsFactory->getCounter( 'refreshlinks_failures_total' );
92 $result = $job->run();
94 // We don't want to retry the job so it is returned with true.
95 $this->assertTrue( $result );
96 $this->assertSame( 1, $totalFailuresCounter->getSampleCount() );
97 $this->assertSame( "Revision {$prevRev->getId()} is not current", $job->getLastError() );
100 public function testRunForSinglePage() {
101 $this->getServiceContainer()->getSlotRoleRegistry()->defineRoleWithModel(
102 'aux',
103 CONTENT_MODEL_WIKITEXT
106 $cacheOpsCounter = $this->statsFactory->getCounter( 'refreshlinks_parsercache_operations_total' );
108 $mainContent = new WikitextContent( 'MAIN [[Kittens]]' );
109 $auxContent = new WikitextContent( 'AUX [[Category:Goats]]' );
110 $page = $this->createPage( __METHOD__, [ 'main' => $mainContent, 'aux' => $auxContent ] );
112 // clear state
113 $parserCache = $this->getServiceContainer()->getParserCache();
114 $parserCache->deleteOptionsKey( $page );
116 $this->getDb()->newDeleteQueryBuilder()
117 ->deleteFrom( 'pagelinks' )
118 ->where( ISQLPlatform::ALL_ROWS )
119 ->caller( __METHOD__ )
120 ->execute();
121 $this->getDb()->newDeleteQueryBuilder()
122 ->deleteFrom( 'categorylinks' )
123 ->where( ISQLPlatform::ALL_ROWS )
124 ->caller( __METHOD__ )
125 ->execute();
127 // run job
128 $job = new RefreshLinksJob( $page->getTitle(), [ 'parseThreshold' => 0 ] );
129 $result = $job->run();
131 $this->newSelectQueryBuilder()
132 ->select( 'lt_title' )
133 ->from( 'pagelinks' )
134 ->join( 'linktarget', null, 'pl_target_id=lt_id' )
135 ->where( [ 'pl_from' => $page->getId() ] )
136 ->assertFieldValue( 'Kittens' );
137 $this->newSelectQueryBuilder()
138 ->select( 'cl_to' )
139 ->from( 'categorylinks' )
140 ->where( [ 'cl_from' => $page->getId() ] )
141 ->assertFieldValue( 'Goats' );
143 $this->assertTrue( $result );
144 $this->assertSame( 1, $cacheOpsCounter->getSampleCount() );
147 public function testRunForMultiPage() {
148 $this->getServiceContainer()->getSlotRoleRegistry()->defineRoleWithModel(
149 'aux',
150 CONTENT_MODEL_WIKITEXT
153 $fname = __METHOD__;
155 $mainContent = new WikitextContent( 'MAIN [[Kittens]]' );
156 $auxContent = new WikitextContent( 'AUX [[Category:Goats]]' );
157 $page1 = $this->createPage( "$fname-1", [ 'main' => $mainContent, 'aux' => $auxContent ] );
159 $mainContent = new WikitextContent( 'MAIN [[Dogs]]' );
160 $auxContent = new WikitextContent( 'AUX [[Category:Hamsters]]' );
161 $page2 = $this->createPage( "$fname-2", [ 'main' => $mainContent, 'aux' => $auxContent ] );
163 // clear state
164 $parserCache = $this->getServiceContainer()->getParserCache();
165 $parserCache->deleteOptionsKey( $page1 );
166 $parserCache->deleteOptionsKey( $page2 );
168 $this->getDb()->newDeleteQueryBuilder()
169 ->deleteFrom( 'pagelinks' )
170 ->where( ISQLPlatform::ALL_ROWS )
171 ->caller( __METHOD__ )
172 ->execute();
173 $this->getDb()->newDeleteQueryBuilder()
174 ->deleteFrom( 'categorylinks' )
175 ->where( ISQLPlatform::ALL_ROWS )
176 ->caller( __METHOD__ )
177 ->execute();
179 // run job
180 $job = new RefreshLinksJob(
181 Title::makeTitle( NS_SPECIAL, 'Blankpage' ),
182 [ 'pages' => [ [ 0, "$fname-1" ], [ 0, "$fname-2" ] ] ]
184 $job->run();
186 $this->newSelectQueryBuilder()
187 ->select( 'lt_title' )
188 ->from( 'pagelinks' )
189 ->join( 'linktarget', null, 'pl_target_id=lt_id' )
190 ->where( [ 'pl_from' => $page1->getId() ] )
191 ->assertFieldValue( 'Kittens' );
192 $this->newSelectQueryBuilder()
193 ->select( 'cl_to' )
194 ->from( 'categorylinks' )
195 ->where( [ 'cl_from' => $page1->getId() ] )
196 ->assertFieldValue( 'Goats' );
197 $this->newSelectQueryBuilder()
198 ->select( 'lt_title' )
199 ->from( 'pagelinks' )
200 ->join( 'linktarget', null, 'pl_target_id=lt_id' )
201 ->where( [ 'pl_from' => $page2->getId() ] )
202 ->assertFieldValue( 'Dogs' );
203 $this->newSelectQueryBuilder()
204 ->select( 'cl_to' )
205 ->from( 'categorylinks' )
206 ->where( [ 'cl_from' => $page2->getId() ] )
207 ->assertFieldValue( 'Hamsters' );