2015-11-20 23:58:59 +00:00
|
|
|
<?php
|
|
|
|
|
|
2017-04-19 19:37:35 +00:00
|
|
|
use Wikimedia\TestingAccessWrapper;
|
|
|
|
|
|
2015-11-20 23:58:59 +00:00
|
|
|
/**
|
|
|
|
|
* @group Cache
|
|
|
|
|
* @covers MessageBlobStore
|
|
|
|
|
*/
|
2015-11-13 00:04:12 +00:00
|
|
|
class MessageBlobStoreTest extends PHPUnit_Framework_TestCase {
|
|
|
|
|
|
|
|
|
|
protected function setUp() {
|
|
|
|
|
parent::setUp();
|
|
|
|
|
// MediaWiki tests defaults $wgMainWANCache to CACHE_NONE.
|
|
|
|
|
// Use hash instead so that caching is observed
|
|
|
|
|
$this->wanCache = $this->getMockBuilder( 'WANObjectCache' )
|
2016-02-17 09:09:32 +00:00
|
|
|
->setConstructorArgs( [ [
|
2015-11-13 00:04:12 +00:00
|
|
|
'cache' => new HashBagOStuff(),
|
|
|
|
|
'pool' => 'test',
|
2016-02-17 09:09:32 +00:00
|
|
|
'relayer' => new EventRelayerNull( [] )
|
|
|
|
|
] ] )
|
|
|
|
|
->setMethods( [ 'makePurgeValue' ] )
|
2015-11-13 00:04:12 +00:00
|
|
|
->getMock();
|
|
|
|
|
|
|
|
|
|
$this->wanCache->expects( $this->any() )
|
|
|
|
|
->method( 'makePurgeValue' )
|
|
|
|
|
->will( $this->returnCallback( function ( $timestamp, $holdoff ) {
|
|
|
|
|
// Disable holdoff as it messes with testing
|
|
|
|
|
return WANObjectCache::PURGE_VAL_PREFIX . (float)$timestamp . ':0';
|
|
|
|
|
} ) );
|
|
|
|
|
}
|
2015-11-20 23:58:59 +00:00
|
|
|
|
|
|
|
|
protected function makeBlobStore( $methods = null, $rl = null ) {
|
|
|
|
|
$blobStore = $this->getMockBuilder( 'MessageBlobStore' )
|
2016-02-17 09:09:32 +00:00
|
|
|
->setConstructorArgs( [ $rl ] )
|
2015-11-20 23:58:59 +00:00
|
|
|
->setMethods( $methods )
|
|
|
|
|
->getMock();
|
|
|
|
|
|
2015-11-13 00:04:12 +00:00
|
|
|
$access = TestingAccessWrapper::newFromObject( $blobStore );
|
|
|
|
|
$access->wanCache = $this->wanCache;
|
2015-11-20 23:58:59 +00:00
|
|
|
return $blobStore;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function makeModule( array $messages ) {
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = new ResourceLoaderTestModule( [ 'messages' => $messages ] );
|
2015-11-20 23:58:59 +00:00
|
|
|
$module->setName( 'test.blobstore' );
|
|
|
|
|
return $module;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-01 00:58:43 +00:00
|
|
|
/** @covers MessageBlobStore::setLogger */
|
|
|
|
|
public function testSetLogger() {
|
|
|
|
|
$blobStore = $this->makeBlobStore();
|
|
|
|
|
$this->assertSame( null, $blobStore->setLogger( new Psr\Log\NullLogger() ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @covers MessageBlobStore::getResourceLoader */
|
|
|
|
|
public function testGetResourceLoader() {
|
|
|
|
|
// Call protected method
|
|
|
|
|
$blobStore = TestingAccessWrapper::newFromObject( $this->makeBlobStore() );
|
|
|
|
|
$this->assertInstanceOf(
|
|
|
|
|
ResourceLoader::class,
|
|
|
|
|
$blobStore->getResourceLoader()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @covers MessageBlobStore::fetchMessage */
|
|
|
|
|
public function testFetchMessage() {
|
|
|
|
|
$module = $this->makeModule( [ 'mainpage' ] );
|
|
|
|
|
$rl = new ResourceLoader();
|
|
|
|
|
$rl->register( $module->getName(), $module );
|
|
|
|
|
|
|
|
|
|
$blobStore = $this->makeBlobStore( null, $rl );
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( '{"mainpage":"Main Page"}', $blob, 'Generated blob' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @covers MessageBlobStore::fetchMessage */
|
|
|
|
|
public function testFetchMessageFail() {
|
|
|
|
|
$module = $this->makeModule( [ 'i-dont-exist' ] );
|
|
|
|
|
$rl = new ResourceLoader();
|
|
|
|
|
$rl->register( $module->getName(), $module );
|
|
|
|
|
|
|
|
|
|
$blobStore = $this->makeBlobStore( null, $rl );
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( '{"i-dont-exist":"\u29fci-dont-exist\u29fd"}', $blob, 'Generated blob' );
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-20 23:58:59 +00:00
|
|
|
public function testGetBlob() {
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = $this->makeModule( [ 'foo' ] );
|
2015-11-20 23:58:59 +00:00
|
|
|
$rl = new ResourceLoader();
|
|
|
|
|
$rl->register( $module->getName(), $module );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
|
2015-11-20 23:58:59 +00:00
|
|
|
$blobStore->expects( $this->once() )
|
|
|
|
|
->method( 'fetchMessage' )
|
|
|
|
|
->will( $this->returnValue( 'Example' ) );
|
|
|
|
|
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
|
|
|
|
|
$this->assertEquals( '{"foo":"Example"}', $blob, 'Generated blob' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testGetBlobCached() {
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = $this->makeModule( [ 'example' ] );
|
2015-11-20 23:58:59 +00:00
|
|
|
$rl = new ResourceLoader();
|
|
|
|
|
$rl->register( $module->getName(), $module );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
|
2015-11-20 23:58:59 +00:00
|
|
|
$blobStore->expects( $this->once() )
|
|
|
|
|
->method( 'fetchMessage' )
|
|
|
|
|
->will( $this->returnValue( 'First' ) );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = $this->makeModule( [ 'example' ] );
|
2015-11-20 23:58:59 +00:00
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
$this->assertEquals( '{"example":"First"}', $blob, 'Generated blob' );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
|
2015-11-20 23:58:59 +00:00
|
|
|
$blobStore->expects( $this->never() )
|
|
|
|
|
->method( 'fetchMessage' )
|
|
|
|
|
->will( $this->returnValue( 'Second' ) );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = $this->makeModule( [ 'example' ] );
|
2015-11-20 23:58:59 +00:00
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
$this->assertEquals( '{"example":"First"}', $blob, 'Cache hit' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testUpdateMessage() {
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = $this->makeModule( [ 'example' ] );
|
2015-11-20 23:58:59 +00:00
|
|
|
$rl = new ResourceLoader();
|
|
|
|
|
$rl->register( $module->getName(), $module );
|
2016-02-17 09:09:32 +00:00
|
|
|
$blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
|
2015-11-13 00:04:12 +00:00
|
|
|
$blobStore->expects( $this->once() )
|
2015-11-20 23:58:59 +00:00
|
|
|
->method( 'fetchMessage' )
|
2015-11-13 00:04:12 +00:00
|
|
|
->will( $this->returnValue( 'First' ) );
|
2015-11-20 23:58:59 +00:00
|
|
|
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
$this->assertEquals( '{"example":"First"}', $blob, 'Generated blob' );
|
|
|
|
|
|
|
|
|
|
$blobStore->updateMessage( 'example' );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = $this->makeModule( [ 'example' ] );
|
2015-11-20 23:58:59 +00:00
|
|
|
$rl = new ResourceLoader();
|
|
|
|
|
$rl->register( $module->getName(), $module );
|
2016-02-17 09:09:32 +00:00
|
|
|
$blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
|
2015-11-13 00:04:12 +00:00
|
|
|
$blobStore->expects( $this->once() )
|
2015-11-20 23:58:59 +00:00
|
|
|
->method( 'fetchMessage' )
|
2015-11-13 00:04:12 +00:00
|
|
|
->will( $this->returnValue( 'Second' ) );
|
2015-11-20 23:58:59 +00:00
|
|
|
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
$this->assertEquals( '{"example":"Second"}', $blob, 'Updated blob' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testValidation() {
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = $this->makeModule( [ 'foo' ] );
|
2015-11-20 23:58:59 +00:00
|
|
|
$rl = new ResourceLoader();
|
|
|
|
|
$rl->register( $module->getName(), $module );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
|
2015-11-20 23:58:59 +00:00
|
|
|
$blobStore->expects( $this->once() )
|
|
|
|
|
->method( 'fetchMessage' )
|
2016-02-17 09:09:32 +00:00
|
|
|
->will( $this->returnValueMap( [
|
|
|
|
|
[ 'foo', 'en', 'Hello' ],
|
|
|
|
|
] ) );
|
2015-11-20 23:58:59 +00:00
|
|
|
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
$this->assertEquals( '{"foo":"Hello"}', $blob, 'Generated blob' );
|
|
|
|
|
|
|
|
|
|
// Now, imagine a change to the module is deployed. The module now contains
|
|
|
|
|
// message 'foo' and 'bar'. While updateMessage() was not called (since no
|
|
|
|
|
// message values were changed) it should detect the change in list of
|
|
|
|
|
// message keys.
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = $this->makeModule( [ 'foo', 'bar' ] );
|
2015-11-20 23:58:59 +00:00
|
|
|
$rl = new ResourceLoader();
|
|
|
|
|
$rl->register( $module->getName(), $module );
|
|
|
|
|
|
2016-02-17 09:09:32 +00:00
|
|
|
$blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
|
2015-11-20 23:58:59 +00:00
|
|
|
$blobStore->expects( $this->exactly( 2 ) )
|
|
|
|
|
->method( 'fetchMessage' )
|
2016-02-17 09:09:32 +00:00
|
|
|
->will( $this->returnValueMap( [
|
|
|
|
|
[ 'foo', 'en', 'Hello' ],
|
|
|
|
|
[ 'bar', 'en', 'World' ],
|
|
|
|
|
] ) );
|
2015-11-20 23:58:59 +00:00
|
|
|
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
$this->assertEquals( '{"foo":"Hello","bar":"World"}', $blob, 'Updated blob' );
|
|
|
|
|
}
|
2015-11-13 00:04:12 +00:00
|
|
|
|
|
|
|
|
public function testClear() {
|
2016-02-17 09:09:32 +00:00
|
|
|
$module = $this->makeModule( [ 'example' ] );
|
2015-11-13 00:04:12 +00:00
|
|
|
$rl = new ResourceLoader();
|
|
|
|
|
$rl->register( $module->getName(), $module );
|
2016-02-17 09:09:32 +00:00
|
|
|
$blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
|
2015-11-13 00:04:12 +00:00
|
|
|
$blobStore->expects( $this->exactly( 2 ) )
|
|
|
|
|
->method( 'fetchMessage' )
|
|
|
|
|
->will( $this->onConsecutiveCalls( 'First', 'Second' ) );
|
|
|
|
|
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
$this->assertEquals( '{"example":"First"}', $blob, 'Generated blob' );
|
|
|
|
|
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
$this->assertEquals( '{"example":"First"}', $blob, 'Cache-hit' );
|
|
|
|
|
|
|
|
|
|
$blobStore->clear();
|
|
|
|
|
|
|
|
|
|
$blob = $blobStore->getBlob( $module, 'en' );
|
|
|
|
|
$this->assertEquals( '{"example":"Second"}', $blob, 'Updated blob' );
|
|
|
|
|
}
|
2015-11-20 23:58:59 +00:00
|
|
|
}
|