3 namespace MediaWiki\Tests\Storage
;
5 use MediaWiki\Storage\RevisionAccessException
;
6 use MediaWiki\Storage\RevisionStore
;
7 use MediaWiki\Storage\SqlBlobStore
;
10 use Wikimedia\Rdbms\Database
;
11 use Wikimedia\Rdbms\LoadBalancer
;
13 class RevisionStoreTest
extends MediaWikiTestCase
{
16 * @param LoadBalancer $loadBalancer
17 * @param SqlBlobStore $blobStore
18 * @param WANObjectCache $WANObjectCache
20 * @return RevisionStore
22 private function getRevisionStore(
25 $WANObjectCache = null
27 return new RevisionStore(
28 $loadBalancer ?
$loadBalancer : $this->getMockLoadBalancer(),
29 $blobStore ?
$blobStore : $this->getMockSqlBlobStore(),
30 $WANObjectCache ?
$WANObjectCache : $this->getHashWANObjectCache()
35 * @return \PHPUnit_Framework_MockObject_MockObject|LoadBalancer
37 private function getMockLoadBalancer() {
38 return $this->getMockBuilder( LoadBalancer
::class )
39 ->disableOriginalConstructor()->getMock();
43 * @return \PHPUnit_Framework_MockObject_MockObject|Database
45 private function getMockDatabase() {
46 return $this->getMockBuilder( Database
::class )
47 ->disableOriginalConstructor()->getMock();
51 * @return \PHPUnit_Framework_MockObject_MockObject|SqlBlobStore
53 private function getMockSqlBlobStore() {
54 return $this->getMockBuilder( SqlBlobStore
::class )
55 ->disableOriginalConstructor()->getMock();
58 private function getHashWANObjectCache() {
59 return new WANObjectCache( [ 'cache' => new \
HashBagOStuff() ] );
63 * @covers \MediaWiki\Storage\RevisionStore::getContentHandlerUseDB
64 * @covers \MediaWiki\Storage\RevisionStore::setContentHandlerUseDB
66 public function testGetSetContentHandlerDb() {
67 $store = $this->getRevisionStore();
68 $this->assertTrue( $store->getContentHandlerUseDB() );
69 $store->setContentHandlerUseDB( false );
70 $this->assertFalse( $store->getContentHandlerUseDB() );
71 $store->setContentHandlerUseDB( true );
72 $this->assertTrue( $store->getContentHandlerUseDB() );
75 private function getDefaultQueryFields() {
91 private function getCommentQueryFields() {
93 'rev_comment_text' => 'rev_comment',
94 'rev_comment_data' => 'NULL',
95 'rev_comment_cid' => 'NULL',
99 private function getContentHandlerQueryFields() {
101 'rev_content_format',
106 public function provideGetQueryInfo() {
111 'tables' => [ 'revision' ],
112 'fields' => array_merge(
113 $this->getDefaultQueryFields(),
114 $this->getCommentQueryFields(),
115 $this->getContentHandlerQueryFields()
124 'tables' => [ 'revision' ],
125 'fields' => array_merge(
126 $this->getDefaultQueryFields(),
127 $this->getCommentQueryFields()
136 'tables' => [ 'revision', 'page' ],
137 'fields' => array_merge(
138 $this->getDefaultQueryFields(),
139 $this->getCommentQueryFields(),
150 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
158 'tables' => [ 'revision', 'user' ],
159 'fields' => array_merge(
160 $this->getDefaultQueryFields(),
161 $this->getCommentQueryFields(),
167 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
175 'tables' => [ 'revision', 'text' ],
176 'fields' => array_merge(
177 $this->getDefaultQueryFields(),
178 $this->getCommentQueryFields(),
185 'text' => [ 'INNER JOIN', [ 'rev_text_id=old_id' ] ],
191 [ 'page', 'user', 'text' ],
193 'tables' => [ 'revision', 'page', 'user', 'text' ],
194 'fields' => array_merge(
195 $this->getDefaultQueryFields(),
196 $this->getCommentQueryFields(),
197 $this->getContentHandlerQueryFields(),
211 'page' => [ 'INNER JOIN', [ 'page_id = rev_page' ] ],
212 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
213 'text' => [ 'INNER JOIN', [ 'rev_text_id=old_id' ] ],
220 * @dataProvider provideGetQueryInfo
221 * @covers \MediaWiki\Storage\RevisionStore::getQueryInfo
223 public function testGetQueryInfo( $contentHandlerUseDb, $options, $expected ) {
224 $store = $this->getRevisionStore();
225 $store->setContentHandlerUseDB( $contentHandlerUseDb );
226 $this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD
);
227 $this->assertEquals( $expected, $store->getQueryInfo( $options ) );
230 private function getDefaultArchiveFields() {
251 * @covers \MediaWiki\Storage\RevisionStore::getArchiveQueryInfo
253 public function testGetArchiveQueryInfo_contentHandlerDb() {
254 $store = $this->getRevisionStore();
255 $store->setContentHandlerUseDB( true );
256 $this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD
);
262 'fields' => array_merge(
263 $this->getDefaultArchiveFields(),
265 'ar_comment_text' => 'ar_comment',
266 'ar_comment_data' => 'NULL',
267 'ar_comment_cid' => 'NULL',
274 $store->getArchiveQueryInfo()
279 * @covers \MediaWiki\Storage\RevisionStore::getArchiveQueryInfo
281 public function testGetArchiveQueryInfo_noContentHandlerDb() {
282 $store = $this->getRevisionStore();
283 $store->setContentHandlerUseDB( false );
284 $this->setMwGlobals( 'wgCommentTableSchemaMigrationStage', MIGRATION_OLD
);
290 'fields' => array_merge(
291 $this->getDefaultArchiveFields(),
293 'ar_comment_text' => 'ar_comment',
294 'ar_comment_data' => 'NULL',
295 'ar_comment_cid' => 'NULL',
300 $store->getArchiveQueryInfo()
304 public function testGetTitle_successFromPageId() {
305 $mockLoadBalancer = $this->getMockLoadBalancer();
306 // Title calls wfGetDB() so we have to set the main service
307 $this->setService( 'DBLoadBalancer', $mockLoadBalancer );
309 $db = $this->getMockDatabase();
310 // Title calls wfGetDB() which uses a regular Connection
311 $mockLoadBalancer->expects( $this->atLeastOnce() )
312 ->method( 'getConnection' )
315 // First call to Title::newFromID, faking no result (db lag?)
316 $db->expects( $this->at( 0 ) )
317 ->method( 'selectRow' )
323 ->willReturn( (object)[
324 'page_namespace' => '1',
325 'page_title' => 'Food',
328 $store = $this->getRevisionStore( $mockLoadBalancer );
329 $title = $store->getTitle( 1, 2, RevisionStore
::READ_NORMAL
);
331 $this->assertSame( 1, $title->getNamespace() );
332 $this->assertSame( 'Food', $title->getDBkey() );
335 public function testGetTitle_successFromRevId() {
336 $mockLoadBalancer = $this->getMockLoadBalancer();
337 // Title calls wfGetDB() so we have to set the main service
338 $this->setService( 'DBLoadBalancer', $mockLoadBalancer );
340 $db = $this->getMockDatabase();
341 // Title calls wfGetDB() which uses a regular Connection
342 $mockLoadBalancer->expects( $this->atLeastOnce() )
343 ->method( 'getConnection' )
345 // RevisionStore getTitle uses a ConnectionRef
346 $mockLoadBalancer->expects( $this->atLeastOnce() )
347 ->method( 'getConnectionRef' )
350 // First call to Title::newFromID, faking no result (db lag?)
351 $db->expects( $this->at( 0 ) )
352 ->method( 'selectRow' )
358 ->willReturn( false );
360 // First select using rev_id, faking no result (db lag?)
361 $db->expects( $this->at( 1 ) )
362 ->method( 'selectRow' )
364 [ 'revision', 'page' ],
368 ->willReturn( (object)[
369 'page_namespace' => '1',
370 'page_title' => 'Food2',
373 $store = $this->getRevisionStore( $mockLoadBalancer );
374 $title = $store->getTitle( 1, 2, RevisionStore
::READ_NORMAL
);
376 $this->assertSame( 1, $title->getNamespace() );
377 $this->assertSame( 'Food2', $title->getDBkey() );
381 * @covers \MediaWiki\Storage\RevisionStore::getTitle
383 public function testGetTitle_throwsExceptionAfterFallbacks() {
384 $mockLoadBalancer = $this->getMockLoadBalancer();
385 // Title calls wfGetDB() so we have to set the main service
386 $this->setService( 'DBLoadBalancer', $mockLoadBalancer );
388 $db = $this->getMockDatabase();
389 // Title calls wfGetDB() which uses a regular Connection
390 $mockLoadBalancer->expects( $this->atLeastOnce() )
391 ->method( 'getConnection' )
393 // RevisionStore getTitle uses a ConnectionRef
394 $mockLoadBalancer->expects( $this->atLeastOnce() )
395 ->method( 'getConnectionRef' )
398 // First call to Title::newFromID, faking no result (db lag?)
399 $db->expects( $this->at( 0 ) )
400 ->method( 'selectRow' )
406 ->willReturn( false );
408 // First select using rev_id, faking no result (db lag?)
409 $db->expects( $this->at( 1 ) )
410 ->method( 'selectRow' )
412 [ 'revision', 'page' ],
416 ->willReturn( false );
418 $store = $this->getRevisionStore( $mockLoadBalancer );
420 $this->setExpectedException( RevisionAccessException
::class );
421 $store->getTitle( 1, 2, RevisionStore
::READ_NORMAL
);
424 // FIXME: test getRevisionSizes