PageRenderTime 65ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/phpunit/includes/filerepo/file/FileTest.php

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