Add an explicit check for correct operation to ExifRotationTest
[lhc/web/wiklou.git] / tests / phpunit / includes / media / ExifRotationTest.php
1 <?php
2 /**
3 * Tests related to auto rotation.
4 *
5 * @group Media
6 * @group medium
7 *
8 * @covers BitmapHandler
9 */
10 class ExifRotationTest extends MediaWikiMediaTestCase {
11
12 /** @var BitmapHandler */
13 private $handler;
14
15 protected function setUp() {
16 parent::setUp();
17 $this->checkPHPExtension( 'exif' );
18
19 $this->handler = new BitmapHandler();
20
21 $this->setMwGlobals( [
22 'wgShowEXIF' => true,
23 'wgEnableAutoRotation' => true,
24 ] );
25 }
26
27 /**
28 * Mark this test as creating thumbnail files.
29 */
30 protected function createsThumbnails() {
31 return true;
32 }
33
34 /**
35 * @dataProvider provideFiles
36 */
37 public function testMetadata( $name, $type, $info ) {
38 if ( !$this->handler->canRotate() ) {
39 $this->markTestSkipped( "This test needs a rasterizer that can auto-rotate." );
40 }
41 $file = $this->dataFile( $name, $type );
42 $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
43 $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
44 }
45
46 /**
47 * Same as before, but with auto-rotation set to auto.
48 *
49 * This sets scaler to image magick, which we should detect as
50 * supporting rotation.
51 * @dataProvider provideFiles
52 */
53 public function testMetadataAutoRotate( $name, $type, $info ) {
54 $this->setMwGlobals( 'wgEnableAutoRotation', null );
55 $this->setMwGlobals( 'wgUseImageMagick', true );
56 $this->setMwGlobals( 'wgUseImageResize', true );
57
58 $file = $this->dataFile( $name, $type );
59 $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
60 $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
61 }
62
63 /**
64 *
65 * @dataProvider provideFiles
66 */
67 public function testRotationRendering( $name, $type, $info, $thumbs ) {
68 if ( !$this->handler->canRotate() ) {
69 $this->markTestSkipped( "This test needs a rasterizer that can auto-rotate." );
70 }
71 foreach ( $thumbs as $size => $out ) {
72 if ( preg_match( '/^(\d+)px$/', $size, $matches ) ) {
73 $params = [
74 'width' => $matches[1],
75 ];
76 } elseif ( preg_match( '/^(\d+)x(\d+)px$/', $size, $matches ) ) {
77 $params = [
78 'width' => $matches[1],
79 'height' => $matches[2]
80 ];
81 } else {
82 throw new MWException( 'bogus test data format ' . $size );
83 }
84
85 $file = $this->dataFile( $name, $type );
86 $thumb = $file->transform( $params, File::RENDER_NOW | File::RENDER_FORCE );
87
88 $this->assertEquals(
89 $out[0],
90 $thumb->getWidth(),
91 "$name: thumb reported width check for $size"
92 );
93 $this->assertEquals(
94 $out[1],
95 $thumb->getHeight(),
96 "$name: thumb reported height check for $size"
97 );
98
99 $gis = getimagesize( $thumb->getLocalCopyPath() );
100 if ( $out[0] > $info['width'] ) {
101 // Physical image won't be scaled bigger than the original.
102 $this->assertEquals( $info['width'], $gis[0], "$name: thumb actual width check for $size" );
103 $this->assertEquals( $info['height'], $gis[1], "$name: thumb actual height check for $size" );
104 } else {
105 $this->assertEquals( $out[0], $gis[0], "$name: thumb actual width check for $size" );
106 $this->assertEquals( $out[1], $gis[1], "$name: thumb actual height check for $size" );
107 }
108 }
109 }
110
111 public static function provideFiles() {
112 return [
113 [
114 'landscape-plain.jpg',
115 'image/jpeg',
116 [
117 'width' => 1024,
118 'height' => 768,
119 ],
120 [
121 '800x600px' => [ 800, 600 ],
122 '9999x800px' => [ 1067, 800 ],
123 '800px' => [ 800, 600 ],
124 '600px' => [ 600, 450 ],
125 ]
126 ],
127 [
128 'portrait-rotated.jpg',
129 'image/jpeg',
130 [
131 'width' => 768, // as rotated
132 'height' => 1024, // as rotated
133 ],
134 [
135 '800x600px' => [ 450, 600 ],
136 '9999x800px' => [ 600, 800 ],
137 '800px' => [ 800, 1067 ],
138 '600px' => [ 600, 800 ],
139 ]
140 ]
141 ];
142 }
143
144 /**
145 * Same as before, but with auto-rotation disabled.
146 * @dataProvider provideFilesNoAutoRotate
147 */
148 public function testMetadataNoAutoRotate( $name, $type, $info ) {
149 $this->setMwGlobals( 'wgEnableAutoRotation', false );
150
151 $file = $this->dataFile( $name, $type );
152 $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
153 $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
154 }
155
156 /**
157 * Same as before, but with auto-rotation set to auto and an image scaler that doesn't support it.
158 * @dataProvider provideFilesNoAutoRotate
159 */
160 public function testMetadataAutoRotateUnsupported( $name, $type, $info ) {
161 $this->setMwGlobals( 'wgEnableAutoRotation', null );
162 $this->setMwGlobals( 'wgUseImageResize', false );
163
164 $file = $this->dataFile( $name, $type );
165 $this->assertEquals( $info['width'], $file->getWidth(), "$name: width check" );
166 $this->assertEquals( $info['height'], $file->getHeight(), "$name: height check" );
167 }
168
169 /**
170 *
171 * @dataProvider provideFilesNoAutoRotate
172 */
173 public function testRotationRenderingNoAutoRotate( $name, $type, $info, $thumbs ) {
174 $this->setMwGlobals( 'wgEnableAutoRotation', false );
175
176 foreach ( $thumbs as $size => $out ) {
177 if ( preg_match( '/^(\d+)px$/', $size, $matches ) ) {
178 $params = [
179 'width' => $matches[1],
180 ];
181 } elseif ( preg_match( '/^(\d+)x(\d+)px$/', $size, $matches ) ) {
182 $params = [
183 'width' => $matches[1],
184 'height' => $matches[2]
185 ];
186 } else {
187 throw new MWException( 'bogus test data format ' . $size );
188 }
189
190 $file = $this->dataFile( $name, $type );
191 $thumb = $file->transform( $params, File::RENDER_NOW | File::RENDER_FORCE );
192
193 if ( $thumb->isError() ) {
194 /** @var MediaTransformError $thumb */
195 $this->fail( $thumb->toText() );
196 }
197
198 $this->assertEquals(
199 $out[0],
200 $thumb->getWidth(),
201 "$name: thumb reported width check for $size"
202 );
203 $this->assertEquals(
204 $out[1],
205 $thumb->getHeight(),
206 "$name: thumb reported height check for $size"
207 );
208
209 $gis = getimagesize( $thumb->getLocalCopyPath() );
210 if ( $out[0] > $info['width'] ) {
211 // Physical image won't be scaled bigger than the original.
212 $this->assertEquals( $info['width'], $gis[0], "$name: thumb actual width check for $size" );
213 $this->assertEquals( $info['height'], $gis[1], "$name: thumb actual height check for $size" );
214 } else {
215 $this->assertEquals( $out[0], $gis[0], "$name: thumb actual width check for $size" );
216 $this->assertEquals( $out[1], $gis[1], "$name: thumb actual height check for $size" );
217 }
218 }
219 }
220
221 public static function provideFilesNoAutoRotate() {
222 return [
223 [
224 'landscape-plain.jpg',
225 'image/jpeg',
226 [
227 'width' => 1024,
228 'height' => 768,
229 ],
230 [
231 '800x600px' => [ 800, 600 ],
232 '9999x800px' => [ 1067, 800 ],
233 '800px' => [ 800, 600 ],
234 '600px' => [ 600, 450 ],
235 ]
236 ],
237 [
238 'portrait-rotated.jpg',
239 'image/jpeg',
240 [
241 'width' => 1024, // since not rotated
242 'height' => 768, // since not rotated
243 ],
244 [
245 '800x600px' => [ 800, 600 ],
246 '9999x800px' => [ 1067, 800 ],
247 '800px' => [ 800, 600 ],
248 '600px' => [ 600, 450 ],
249 ]
250 ]
251 ];
252 }
253
254 const TEST_WIDTH = 100;
255 const TEST_HEIGHT = 200;
256
257 /**
258 * @dataProvider provideBitmapExtractPreRotationDimensions
259 */
260 public function testBitmapExtractPreRotationDimensions( $rotation, $expected ) {
261 $result = $this->handler->extractPreRotationDimensions( [
262 'physicalWidth' => self::TEST_WIDTH,
263 'physicalHeight' => self::TEST_HEIGHT,
264 ], $rotation );
265 $this->assertEquals( $expected, $result );
266 }
267
268 public static function provideBitmapExtractPreRotationDimensions() {
269 return [
270 [
271 0,
272 [ self::TEST_WIDTH, self::TEST_HEIGHT ]
273 ],
274 [
275 90,
276 [ self::TEST_HEIGHT, self::TEST_WIDTH ]
277 ],
278 [
279 180,
280 [ self::TEST_WIDTH, self::TEST_HEIGHT ]
281 ],
282 [
283 270,
284 [ self::TEST_HEIGHT, self::TEST_WIDTH ]
285 ],
286 ];
287 }
288 }