3 use Wikimedia\TestingAccessWrapper;
7 * @covers MessageBlobStore
9 class MessageBlobStoreTest extends PHPUnit_Framework_TestCase {
11 protected function setUp() {
13 // MediaWiki tests defaults $wgMainWANCache to CACHE_NONE.
14 // Use hash instead so that caching is observed
15 $this->wanCache = $this->getMockBuilder( 'WANObjectCache' )
16 ->setConstructorArgs( [ [
17 'cache' => new HashBagOStuff(),
19 'relayer' => new EventRelayerNull( [] )
21 ->setMethods( [ 'makePurgeValue' ] )
24 $this->wanCache->expects( $this->any() )
25 ->method( 'makePurgeValue' )
26 ->will( $this->returnCallback( function ( $timestamp, $holdoff ) {
27 // Disable holdoff as it messes with testing
28 return WANObjectCache::PURGE_VAL_PREFIX . (float)$timestamp . ':0';
32 protected function makeBlobStore( $methods = null, $rl = null ) {
33 $blobStore = $this->getMockBuilder( 'MessageBlobStore' )
34 ->setConstructorArgs( [ $rl ] )
35 ->setMethods( $methods )
38 $access = TestingAccessWrapper::newFromObject( $blobStore );
39 $access->wanCache = $this->wanCache;
43 protected function makeModule( array $messages ) {
44 $module = new ResourceLoaderTestModule( [ 'messages' => $messages ] );
45 $module->setName( 'test.blobstore' );
49 /** @covers MessageBlobStore::setLogger */
50 public function testSetLogger() {
51 $blobStore = $this->makeBlobStore();
52 $this->assertSame( null, $blobStore->setLogger( new Psr\Log\NullLogger() ) );
55 /** @covers MessageBlobStore::getResourceLoader */
56 public function testGetResourceLoader() {
57 // Call protected method
58 $blobStore = TestingAccessWrapper::newFromObject( $this->makeBlobStore() );
59 $this->assertInstanceOf(
60 ResourceLoader::class,
61 $blobStore->getResourceLoader()
65 /** @covers MessageBlobStore::fetchMessage */
66 public function testFetchMessage() {
67 $module = $this->makeModule( [ 'mainpage' ] );
68 $rl = new ResourceLoader();
69 $rl->register( $module->getName(), $module );
71 $blobStore = $this->makeBlobStore( null, $rl );
72 $blob = $blobStore->getBlob( $module, 'en' );
74 $this->assertEquals( '{"mainpage":"Main Page"}', $blob, 'Generated blob' );
77 /** @covers MessageBlobStore::fetchMessage */
78 public function testFetchMessageFail() {
79 $module = $this->makeModule( [ 'i-dont-exist' ] );
80 $rl = new ResourceLoader();
81 $rl->register( $module->getName(), $module );
83 $blobStore = $this->makeBlobStore( null, $rl );
84 $blob = $blobStore->getBlob( $module, 'en' );
86 $this->assertEquals( '{"i-dont-exist":"\u29fci-dont-exist\u29fd"}', $blob, 'Generated blob' );
89 public function testGetBlob() {
90 $module = $this->makeModule( [ 'foo' ] );
91 $rl = new ResourceLoader();
92 $rl->register( $module->getName(), $module );
94 $blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
95 $blobStore->expects( $this->once() )
96 ->method( 'fetchMessage' )
97 ->will( $this->returnValue( 'Example' ) );
99 $blob = $blobStore->getBlob( $module, 'en' );
101 $this->assertEquals( '{"foo":"Example"}', $blob, 'Generated blob' );
105 * Seems to fail sometimes (T176097).
109 public function testGetBlobCached() {
110 $module = $this->makeModule( [ 'example' ] );
111 $rl = new ResourceLoader();
112 $rl->register( $module->getName(), $module );
114 $blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
115 $blobStore->expects( $this->once() )
116 ->method( 'fetchMessage' )
117 ->will( $this->returnValue( 'First' ) );
119 $module = $this->makeModule( [ 'example' ] );
120 $blob = $blobStore->getBlob( $module, 'en' );
121 $this->assertEquals( '{"example":"First"}', $blob, 'Generated blob' );
123 $blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
124 $blobStore->expects( $this->never() )
125 ->method( 'fetchMessage' )
126 ->will( $this->returnValue( 'Second' ) );
128 $module = $this->makeModule( [ 'example' ] );
129 $blob = $blobStore->getBlob( $module, 'en' );
130 $this->assertEquals( '{"example":"First"}', $blob, 'Cache hit' );
133 public function testUpdateMessage() {
134 $module = $this->makeModule( [ 'example' ] );
135 $rl = new ResourceLoader();
136 $rl->register( $module->getName(), $module );
137 $blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
138 $blobStore->expects( $this->once() )
139 ->method( 'fetchMessage' )
140 ->will( $this->returnValue( 'First' ) );
142 $blob = $blobStore->getBlob( $module, 'en' );
143 $this->assertEquals( '{"example":"First"}', $blob, 'Generated blob' );
145 $blobStore->updateMessage( 'example' );
147 $module = $this->makeModule( [ 'example' ] );
148 $rl = new ResourceLoader();
149 $rl->register( $module->getName(), $module );
150 $blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
151 $blobStore->expects( $this->once() )
152 ->method( 'fetchMessage' )
153 ->will( $this->returnValue( 'Second' ) );
155 $blob = $blobStore->getBlob( $module, 'en' );
156 $this->assertEquals( '{"example":"Second"}', $blob, 'Updated blob' );
159 public function testValidation() {
160 $module = $this->makeModule( [ 'foo' ] );
161 $rl = new ResourceLoader();
162 $rl->register( $module->getName(), $module );
164 $blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
165 $blobStore->expects( $this->once() )
166 ->method( 'fetchMessage' )
167 ->will( $this->returnValueMap( [
168 [ 'foo', 'en', 'Hello' ],
171 $blob = $blobStore->getBlob( $module, 'en' );
172 $this->assertEquals( '{"foo":"Hello"}', $blob, 'Generated blob' );
174 // Now, imagine a change to the module is deployed. The module now contains
175 // message 'foo' and 'bar'. While updateMessage() was not called (since no
176 // message values were changed) it should detect the change in list of
178 $module = $this->makeModule( [ 'foo', 'bar' ] );
179 $rl = new ResourceLoader();
180 $rl->register( $module->getName(), $module );
182 $blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
183 $blobStore->expects( $this->exactly( 2 ) )
184 ->method( 'fetchMessage' )
185 ->will( $this->returnValueMap( [
186 [ 'foo', 'en', 'Hello' ],
187 [ 'bar', 'en', 'World' ],
190 $blob = $blobStore->getBlob( $module, 'en' );
191 $this->assertEquals( '{"foo":"Hello","bar":"World"}', $blob, 'Updated blob' );
194 public function testClear() {
195 $module = $this->makeModule( [ 'example' ] );
196 $rl = new ResourceLoader();
197 $rl->register( $module->getName(), $module );
198 $blobStore = $this->makeBlobStore( [ 'fetchMessage' ], $rl );
199 $blobStore->expects( $this->exactly( 2 ) )
200 ->method( 'fetchMessage' )
201 ->will( $this->onConsecutiveCalls( 'First', 'Second' ) );
203 $blob = $blobStore->getBlob( $module, 'en' );
204 $this->assertEquals( '{"example":"First"}', $blob, 'Generated blob' );
206 $blob = $blobStore->getBlob( $module, 'en' );
207 $this->assertEquals( '{"example":"First"}', $blob, 'Cache-hit' );
211 $blob = $blobStore->getBlob( $module, 'en' );
212 $this->assertEquals( '{"example":"Second"}', $blob, 'Updated blob' );