wiki.techinc.nl/tests/phpunit/includes/resourceloader/ResourceLoaderWikiModuleTest.php
Timo Tijhof 6b2a7fd4b1 resourceloader: Refactor ResourceLoaderWikiModule to reduce database queries
Wiki modules are special due to their isKnownEmpty implementation and support
for foreign databases. MediaWiki doesn't have convenient ways of making
Revision objects for remote wikis. As such, wiki modules will keep using meta
data to generate the hash.

However minimise needless cache invalidation by refining the implementation.

Impact:
* Remove use of getMsgBlobMtime(). This module doesn't support getMessages().
* In the title info, use the revision content sha1 and size for tracking.
  The page_touched previously used updates too often. It's updated both on edits
  for various types of purges. Using the rev_sha1 means old versions return
  when the content is the same. Regardless of how the content changed via
  revert or actual edits resulting in the same contnet.
* Change in-process cache to be keyed by page list instead of entire
  ResourceLoaderContext.
  Because of this, getTitleInfo() was previously performing its batch query
  twice on the same page. Once for only=styles (top) and only=scripts (bottom).
  Both operate on the full getPages() set but had different context keys.

Clean up:
* Better document the support for foreign databases.
* Move Title construction to getContent to reduce duplication.
* Remove use of getDefinitionMtime(). That method is a no-op since the switch
  to version hashing.
* Remove remaining use of mtime in getModifiedTime(). This is now covered by
  hashing the title info in getDefinitionSummary().

Also refactor the code to be more readable. No intended change in behaviour.

Bug: T98087
Change-Id: Id46740db04c0c42bc5ca87d1487230a32feb34df
2015-06-05 00:43:46 +01:00

136 lines
3.9 KiB
PHP

<?php
class ResourceLoaderWikiModuleTest extends ResourceLoaderTestCase {
/**
* @covers ResourceLoaderWikiModule::__construct
* @dataProvider provideConstructor
*/
public function testConstructor( $params ) {
$module = new ResourceLoaderWikiModule( $params );
$this->assertInstanceOf( 'ResourceLoaderWikiModule', $module );
}
public static function provideConstructor() {
return array(
// Nothing
array( null ),
array( array() ),
// Unrecognized settings
array( array( 'foo' => 'baz' ) ),
// Real settings
array( array( 'scripts' => array( 'MediaWiki:Common.js' ) ) ),
);
}
/**
* @dataProvider provideGetPages
* @covers ResourceLoaderWikiModule::getPages
*/
public function testGetPages( $params, Config $config, $expected ) {
$module = new ResourceLoaderWikiModule( $params );
$module->setConfig( $config );
// Because getPages is protected..
$getPages = new ReflectionMethod( $module, 'getPages' );
$getPages->setAccessible( true );
$out = $getPages->invoke( $module, ResourceLoaderContext::newDummyContext() );
$this->assertEquals( $expected, $out );
}
public static function provideGetPages() {
$settings = self::getSettings() + array(
'UseSiteJs' => true,
'UseSiteCss' => true,
);
$params = array(
'styles' => array( 'MediaWiki:Common.css' ),
'scripts' => array( 'MediaWiki:Common.js' ),
);
return array(
array( array(), new HashConfig( $settings ), array() ),
array( $params, new HashConfig( $settings ), array(
'MediaWiki:Common.js' => array( 'type' => 'script' ),
'MediaWiki:Common.css' => array( 'type' => 'style' )
) ),
array( $params, new HashConfig( array( 'UseSiteCss' => false ) + $settings ), array(
'MediaWiki:Common.js' => array( 'type' => 'script' ),
) ),
array( $params, new HashConfig( array( 'UseSiteJs' => false ) + $settings ), array(
'MediaWiki:Common.css' => array( 'type' => 'style' ),
) ),
array( $params, new HashConfig( array( 'UseSiteJs' => false, 'UseSiteCss' => false ) ), array() ),
);
}
/**
* @covers ResourceLoaderWikiModule::getGroup
* @dataProvider provideGetGroup
*/
public function testGetGroup( $params, $expected ) {
$module = new ResourceLoaderWikiModule( $params );
$this->assertEquals( $expected, $module->getGroup() );
}
public static function provideGetGroup() {
return array(
// No group specified
array( array(), null ),
// A random group
array( array( 'group' => 'foobar' ), 'foobar' ),
);
}
/**
* @covers ResourceLoaderWikiModule::isKnownEmpty
* @dataProvider provideIsKnownEmpty
*/
public function testIsKnownEmpty( $titleInfo, $group, $expected ) {
$module = $this->getMockBuilder( 'ResourceLoaderWikiModule' )
->setMethods( array( 'getTitleInfo', 'getGroup' ) )
->getMock();
$module->expects( $this->any() )
->method( 'getTitleInfo' )
->will( $this->returnValue( $titleInfo ) );
$module->expects( $this->any() )
->method( 'getGroup' )
->will( $this->returnValue( $group ) );
$context = $this->getMockBuilder( 'ResourceLoaderContext' )
->disableOriginalConstructor()
->getMock();
$this->assertEquals( $expected, $module->isKnownEmpty( $context ) );
}
public static function provideIsKnownEmpty() {
return array(
// No valid pages
array( array(), 'test1', true ),
// 'site' module with a non-empty page
array(
array( 'MediaWiki:Common.js' => array( 'rev_sha1' => 'dmh6qn', 'rev_len' => 1234 ) ),
'site',
false,
),
// 'site' module with an empty page
array(
array( 'MediaWiki:Foo.js' => array( 'rev_sha1' => 'phoi', 'rev_len' => 0 ) ),
'site',
false,
),
// 'user' module with a non-empty page
array(
array( 'User:Example/common.js' => array( 'rev_sha1' => 'j7ssba', 'rev_len' => 25 ) ),
'user',
false,
),
// 'user' module with an empty page
array(
array( 'User:Example/foo.js' => array( 'rev_sha1' => 'phoi', 'rev_len' => 0 ) ),
'user',
true,
),
);
}
}