Merge "Support for enabling skins in the installer"
[lhc/web/wiklou.git] / tests / phpunit / includes / filerepo / file / FileTest.php
1 <?php
2
3 class FileTest extends MediaWikiMediaTestCase {
4
5 /**
6 * @param $filename String
7 * @param $expected boolean
8 * @dataProvider providerCanAnimate
9 */
10 function testCanAnimateThumbIfAppropriate( $filename, $expected ) {
11 $this->setMwGlobals( 'wgMaxAnimatedGifArea', 9000 );
12 $file = $this->dataFile( $filename );
13 $this->assertEquals( $file->canAnimateThumbIfAppropriate(), $expected );
14 }
15
16 function providerCanAnimate() {
17 return array(
18 array( 'nonanimated.gif', true ),
19 array( 'jpeg-comment-utf.jpg', true ),
20 array( 'test.tiff', true ),
21 array( 'Animated_PNG_example_bouncing_beach_ball.png', false ),
22 array( 'greyscale-png.png', true ),
23 array( 'Toll_Texas_1.svg', true ),
24 array( 'LoremIpsum.djvu', true ),
25 array( '80x60-2layers.xcf', true ),
26 array( 'Soccer_ball_animated.svg', false ),
27 array( 'Bishzilla_blink.gif', false ),
28 array( 'animated.gif', true ),
29 );
30 }
31
32 /**
33 * @dataProvider getThumbnailBucketProvider
34 * @covers File::getThumbnailBucket
35 */
36 public function testGetThumbnailBucket( $data ) {
37 $this->setMwGlobals( 'wgThumbnailBuckets', $data['buckets'] );
38 $this->setMwGlobals( 'wgThumbnailMinimumBucketDistance', $data['minimumBucketDistance'] );
39
40 $fileMock = $this->getMockBuilder( 'File' )
41 ->setConstructorArgs( array( 'fileMock', false ) )
42 ->setMethods( array( 'getWidth' ) )
43 ->getMockForAbstractClass();
44
45 $fileMock->expects( $this->any() )->method( 'getWidth' )->will(
46 $this->returnValue( $data['width'] ) );
47
48 $this->assertEquals(
49 $data['expectedBucket'],
50 $fileMock->getThumbnailBucket( $data['requestedWidth'] ),
51 $data['message'] );
52 }
53
54 public function getThumbnailBucketProvider() {
55 $defaultBuckets = array( 256, 512, 1024, 2048, 4096 );
56
57 return array(
58 array( array(
59 'buckets' => $defaultBuckets,
60 'minimumBucketDistance' => 0,
61 'width' => 3000,
62 'requestedWidth' => 120,
63 'expectedBucket' => 256,
64 'message' => 'Picking bucket bigger than requested size'
65 ) ),
66 array( array(
67 'buckets' => $defaultBuckets,
68 'minimumBucketDistance' => 0,
69 'width' => 3000,
70 'requestedWidth' => 300,
71 'expectedBucket' => 512,
72 'message' => 'Picking bucket bigger than requested size'
73 ) ),
74 array( array(
75 'buckets' => $defaultBuckets,
76 'minimumBucketDistance' => 0,
77 'width' => 3000,
78 'requestedWidth' => 1024,
79 'expectedBucket' => 2048,
80 'message' => 'Picking bucket bigger than requested size'
81 ) ),
82 array( array(
83 'buckets' => $defaultBuckets,
84 'minimumBucketDistance' => 0,
85 'width' => 3000,
86 'requestedWidth' => 2048,
87 'expectedBucket' => false,
88 'message' => 'Picking no bucket because none is bigger than the requested size'
89 ) ),
90 array( array(
91 'buckets' => $defaultBuckets,
92 'minimumBucketDistance' => 0,
93 'width' => 3000,
94 'requestedWidth' => 3500,
95 'expectedBucket' => false,
96 'message' => 'Picking no bucket because requested size is bigger than original'
97 ) ),
98 array( array(
99 'buckets' => array( 1024 ),
100 'minimumBucketDistance' => 0,
101 'width' => 3000,
102 'requestedWidth' => 1024,
103 'expectedBucket' => false,
104 'message' => 'Picking no bucket because requested size equals biggest bucket'
105 ) ),
106 array( array(
107 'buckets' => null,
108 'minimumBucketDistance' => 0,
109 'width' => 3000,
110 'requestedWidth' => 1024,
111 'expectedBucket' => false,
112 'message' => 'Picking no bucket because no buckets have been specified'
113 ) ),
114 array( array(
115 'buckets' => array( 256, 512 ),
116 'minimumBucketDistance' => 10,
117 'width' => 3000,
118 'requestedWidth' => 245,
119 'expectedBucket' => 256,
120 'message' => 'Requested width is distant enough from next bucket for it to be picked'
121 ) ),
122 array( array(
123 'buckets' => array( 256, 512 ),
124 'minimumBucketDistance' => 10,
125 'width' => 3000,
126 'requestedWidth' => 246,
127 'expectedBucket' => 512,
128 'message' => 'Requested width is too close to next bucket, picking next one'
129 ) ),
130 );
131 }
132
133 /**
134 * @dataProvider getThumbnailSourceProvider
135 * @covers File::getThumbnailSource
136 */
137 public function testGetThumbnailSource( $data ) {
138 $backendMock = $this->getMockBuilder( 'FSFileBackend' )
139 ->setConstructorArgs( array( array( 'name' => 'backendMock', 'wikiId' => wfWikiId() ) ) )
140 ->getMock();
141
142 $repoMock = $this->getMockBuilder( 'FileRepo' )
143 ->setConstructorArgs( array( array( 'name' => 'repoMock', 'backend' => $backendMock ) ) )
144 ->setMethods( array( 'fileExists', 'getLocalReference' ) )
145 ->getMock();
146
147 $fsFile = new FSFile( 'fsFilePath' );
148
149 $repoMock->expects( $this->any() )->method( 'fileExists' )->will(
150 $this->returnValue( true ) );
151
152 $repoMock->expects( $this->any() )->method( 'getLocalReference' )->will(
153 $this->returnValue( $fsFile ) );
154
155 $handlerMock = $this->getMock( 'BitmapHandler', array( 'supportsBucketing' ) );
156 $handlerMock->expects( $this->any() )->method( 'supportsBucketing' )->will(
157 $this->returnValue( $data['supportsBucketing'] ) );
158
159 $fileMock = $this->getMockBuilder( 'File' )
160 ->setConstructorArgs( array( 'fileMock', $repoMock ) )
161 ->setMethods( array( 'getThumbnailBucket', 'getLocalRefPath', 'getHandler' ) )
162 ->getMockForAbstractClass();
163
164 $fileMock->expects( $this->any() )->method( 'getThumbnailBucket' )->will(
165 $this->returnValue( $data['thumbnailBucket'] ) );
166
167 $fileMock->expects( $this->any() )->method( 'getLocalRefPath' )->will(
168 $this->returnValue( 'localRefPath' ) );
169
170 $fileMock->expects( $this->any() )->method( 'getHandler' )->will(
171 $this->returnValue( $handlerMock ) );
172
173 $reflection = new ReflectionClass( $fileMock );
174 $reflection_property = $reflection->getProperty( 'handler' );
175 $reflection_property->setAccessible( true );
176 $reflection_property->setValue( $fileMock, $handlerMock );
177
178 if ( !is_null( $data['tmpBucketedThumbCache'] ) ) {
179 $reflection_property = $reflection->getProperty( 'tmpBucketedThumbCache' );
180 $reflection_property->setAccessible( true );
181 $reflection_property->setValue( $fileMock, $data['tmpBucketedThumbCache'] );
182 }
183
184 $result = $fileMock->getThumbnailSource(
185 array( 'physicalWidth' => $data['physicalWidth'] ) );
186
187 $this->assertEquals( $data['expectedPath'], $result['path'], $data['message'] );
188 }
189
190 public function getThumbnailSourceProvider() {
191 return array(
192 array( array(
193 'supportsBucketing' => true,
194 'tmpBucketedThumbCache' => null,
195 'thumbnailBucket' => 1024,
196 'physicalWidth' => 2048,
197 'expectedPath' => 'fsFilePath',
198 'message' => 'Path downloaded from storage'
199 ) ),
200 array( array(
201 'supportsBucketing' => true,
202 'tmpBucketedThumbCache' => array( 1024 => '/tmp/shouldnotexist' + rand() ),
203 'thumbnailBucket' => 1024,
204 'physicalWidth' => 2048,
205 'expectedPath' => 'fsFilePath',
206 'message' => 'Path downloaded from storage because temp file is missing'
207 ) ),
208 array( array(
209 'supportsBucketing' => true,
210 'tmpBucketedThumbCache' => array( 1024 => '/tmp' ),
211 'thumbnailBucket' => 1024,
212 'physicalWidth' => 2048,
213 'expectedPath' => '/tmp',
214 'message' => 'Temporary path because temp file was found'
215 ) ),
216 array( array(
217 'supportsBucketing' => false,
218 'tmpBucketedThumbCache' => null,
219 'thumbnailBucket' => 1024,
220 'physicalWidth' => 2048,
221 'expectedPath' => 'localRefPath',
222 'message' => 'Original file path because bucketing is unsupported by handler'
223 ) ),
224 array( array(
225 'supportsBucketing' => true,
226 'tmpBucketedThumbCache' => null,
227 'thumbnailBucket' => false,
228 'physicalWidth' => 2048,
229 'expectedPath' => 'localRefPath',
230 'message' => 'Original file path because no width provided'
231 ) ),
232 );
233 }
234
235 /**
236 * @dataProvider generateBucketsIfNeededProvider
237 * @covers File::generateBucketsIfNeeded
238 */
239 public function testGenerateBucketsIfNeeded( $data ) {
240 $this->setMwGlobals( 'wgThumbnailBuckets', $data['buckets'] );
241
242 $backendMock = $this->getMockBuilder( 'FSFileBackend' )
243 ->setConstructorArgs( array( array( 'name' => 'backendMock', 'wikiId' => wfWikiId() ) ) )
244 ->getMock();
245
246 $repoMock = $this->getMockBuilder( 'FileRepo' )
247 ->setConstructorArgs( array( array( 'name' => 'repoMock', 'backend' => $backendMock ) ) )
248 ->setMethods( array( 'fileExists', 'getLocalReference' ) )
249 ->getMock();
250
251 $fileMock = $this->getMockBuilder( 'File' )
252 ->setConstructorArgs( array( 'fileMock', $repoMock ) )
253 ->setMethods( array( 'getWidth', 'getBucketThumbPath', 'makeTransformTmpFile', 'generateAndSaveThumb', 'getHandler' ) )
254 ->getMockForAbstractClass();
255
256 $handlerMock = $this->getMock( 'JpegHandler', array( 'supportsBucketing' ) );
257 $handlerMock->expects( $this->any() )->method( 'supportsBucketing' )->will(
258 $this->returnValue( true ) );
259
260 $fileMock->expects( $this->any() )->method( 'getHandler' )->will(
261 $this->returnValue( $handlerMock ) );
262
263 $reflectionMethod = new ReflectionMethod( 'File', 'generateBucketsIfNeeded' );
264 $reflectionMethod->setAccessible( true );
265
266 $fileMock->expects( $this->any() )
267 ->method( 'getWidth' )
268 ->will( $this->returnValue( $data['width'] ) );
269
270 $fileMock->expects( $data['expectedGetBucketThumbPathCalls'] )
271 ->method( 'getBucketThumbPath' );
272
273 $repoMock->expects( $data['expectedFileExistsCalls'] )
274 ->method( 'fileExists' )
275 ->will( $this->returnValue( $data['fileExistsReturn'] ) );
276
277 $fileMock->expects( $data['expectedMakeTransformTmpFile'] )
278 ->method( 'makeTransformTmpFile' )
279 ->will( $this->returnValue( $data['makeTransformTmpFileReturn'] ) );
280
281 $fileMock->expects( $data['expectedGenerateAndSaveThumb'] )
282 ->method( 'generateAndSaveThumb' )
283 ->will( $this->returnValue( $data['generateAndSaveThumbReturn'] ) );
284
285 $this->assertEquals( $data['expectedResult'],
286 $reflectionMethod->invoke(
287 $fileMock,
288 array(
289 'physicalWidth' => $data['physicalWidth'],
290 'physicalHeight' => $data['physicalHeight'] )
291 ),
292 $data['message'] );
293 }
294
295 public function generateBucketsIfNeededProvider() {
296 $defaultBuckets = array( 256, 512, 1024, 2048, 4096 );
297
298 return array(
299 array( array(
300 'buckets' => $defaultBuckets,
301 'width' => 256,
302 'physicalWidth' => 256,
303 'physicalHeight' => 100,
304 'expectedGetBucketThumbPathCalls' => $this->never(),
305 'expectedFileExistsCalls' => $this->never(),
306 'fileExistsReturn' => null,
307 'expectedMakeTransformTmpFile' => $this->never(),
308 'makeTransformTmpFileReturn' => false,
309 'expectedGenerateAndSaveThumb' => $this->never(),
310 'generateAndSaveThumbReturn' => false,
311 'expectedResult' => false,
312 'message' => 'No bucket found, nothing to generate'
313 ) ),
314 array( array(
315 'buckets' => $defaultBuckets,
316 'width' => 5000,
317 'physicalWidth' => 300,
318 'physicalHeight' => 200,
319 'expectedGetBucketThumbPathCalls' => $this->once(),
320 'expectedFileExistsCalls' => $this->once(),
321 'fileExistsReturn' => true,
322 'expectedMakeTransformTmpFile' => $this->never(),
323 'makeTransformTmpFileReturn' => false,
324 'expectedGenerateAndSaveThumb' => $this->never(),
325 'generateAndSaveThumbReturn' => false,
326 'expectedResult' => false,
327 'message' => 'File already exists, no reason to generate buckets'
328 ) ),
329 array( array(
330 'buckets' => $defaultBuckets,
331 'width' => 5000,
332 'physicalWidth' => 300,
333 'physicalHeight' => 200,
334 'expectedGetBucketThumbPathCalls' => $this->once(),
335 'expectedFileExistsCalls' => $this->once(),
336 'fileExistsReturn' => false,
337 'expectedMakeTransformTmpFile' => $this->once(),
338 'makeTransformTmpFileReturn' => false,
339 'expectedGenerateAndSaveThumb' => $this->never(),
340 'generateAndSaveThumbReturn' => false,
341 'expectedResult' => false,
342 'message' => 'Cannot generate temp file for bucket'
343 ) ),
344 array( array(
345 'buckets' => $defaultBuckets,
346 'width' => 5000,
347 'physicalWidth' => 300,
348 'physicalHeight' => 200,
349 'expectedGetBucketThumbPathCalls' => $this->once(),
350 'expectedFileExistsCalls' => $this->once(),
351 'fileExistsReturn' => false,
352 'expectedMakeTransformTmpFile' => $this->once(),
353 'makeTransformTmpFileReturn' => new TempFSFile( '/tmp/foo' ),
354 'expectedGenerateAndSaveThumb' => $this->once(),
355 'generateAndSaveThumbReturn' => false,
356 'expectedResult' => false,
357 'message' => 'Bucket image could not be generated'
358 ) ),
359 array( array(
360 'buckets' => $defaultBuckets,
361 'width' => 5000,
362 'physicalWidth' => 300,
363 'physicalHeight' => 200,
364 'expectedGetBucketThumbPathCalls' => $this->once(),
365 'expectedFileExistsCalls' => $this->once(),
366 'fileExistsReturn' => false,
367 'expectedMakeTransformTmpFile' => $this->once(),
368 'makeTransformTmpFileReturn' => new TempFSFile( '/tmp/foo' ),
369 'expectedGenerateAndSaveThumb' => $this->once(),
370 'generateAndSaveThumbReturn' => new ThumbnailImage( false, 'bar', false, false ),
371 'expectedResult' => true,
372 'message' => 'Bucket image could not be generated'
373 ) ),
374 );
375 }
376 }