From: Kunal Mehta Date: Wed, 30 Jan 2019 05:35:11 +0000 (-0800) Subject: Rename tests/phpunit/includes/media files to match class names X-Git-Tag: 1.34.0-rc.0~2993 X-Git-Url: http://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/pie.php?a=commitdiff_plain;h=951690c02e5e969cf7d40aa284b504ba49118eb7;p=lhc%2Fweb%2Fwiklou.git Rename tests/phpunit/includes/media files to match class names The classes were renamed in 9bf39163, this updates the test cases to match. Also take care of XCF while we're at it too. Change-Id: Iaaeee93e496af6cdd610df5bc75302ecfe273f64 --- diff --git a/.phpcs.xml b/.phpcs.xml index c0154c7543..88a6f8cd70 100644 --- a/.phpcs.xml +++ b/.phpcs.xml @@ -78,7 +78,6 @@ Whitelist existing violations, but enable the sniff to prevent any new occurrences. --> - */includes/media/XCF\.php */includes/Feed\.php */includes/libs/xmp/XMP\.php */includes/jobqueue/JobSpecification\.php diff --git a/autoload.php b/autoload.php index df1c0b2505..0d17916f56 100644 --- a/autoload.php +++ b/autoload.php @@ -1699,7 +1699,7 @@ $wgAutoloadLocalClasses = [ 'WithoutInterwikiPage' => __DIR__ . '/includes/specials/SpecialWithoutinterwiki.php', 'WordLevelDiff' => __DIR__ . '/includes/diff/WordLevelDiff.php', 'WrapOldPasswords' => __DIR__ . '/maintenance/wrapOldPasswords.php', - 'XCFHandler' => __DIR__ . '/includes/media/XCF.php', + 'XCFHandler' => __DIR__ . '/includes/media/XCFHandler.php', 'XMLRCFeedFormatter' => __DIR__ . '/includes/rcfeed/XMLRCFeedFormatter.php', 'XMPInfo' => __DIR__ . '/includes/compat/XMPReader.php', 'XMPReader' => __DIR__ . '/includes/compat/XMPReader.php', diff --git a/includes/media/XCF.php b/includes/media/XCF.php deleted file mode 100644 index 0cb618ffd8..0000000000 --- a/includes/media/XCF.php +++ /dev/null @@ -1,228 +0,0 @@ - $header['width'], - 1 => $header['height'], - 2 => null, # IMAGETYPE constant, none exist for XCF. - 3 => "height=\"{$header['height']}\" width=\"{$header['width']}\"", - 'mime' => 'image/x-xcf', - 'channels' => null, - 'bits' => 8, # Always 8-bits per color - ]; - } - - /** - * Metadata for a given XCF file - * - * Will return false if file magic signature is not recognized - * @author Hexmode - * @author Hashar - * - * @param string $filename Full path to a XCF file - * @return bool|array Metadata Array just like PHP getimagesize() - */ - static function getXCFMetaData( $filename ) { - # Decode master structure - $f = fopen( $filename, 'rb' ); - if ( !$f ) { - return false; - } - # The image structure always starts at offset 0 in the XCF file. - # So we just read it :-) - $binaryHeader = fread( $f, 26 ); - fclose( $f ); - - /** - * Master image structure: - * - * byte[9] "gimp xcf " File type magic - * byte[4] version XCF version - * "file" - version 0 - * "v001" - version 1 - * "v002" - version 2 - * byte 0 Zero-terminator for version tag - * uint32 width With of canvas - * uint32 height Height of canvas - * uint32 base_type Color mode of the image; one of - * 0: RGB color - * 1: Grayscale - * 2: Indexed color - * (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h) - */ - try { - $header = wfUnpack( - "A9magic" . # A: space padded - "/a5version" . # a: zero padded - "/Nwidth" . # \ - "/Nheight" . # N: unsigned long 32bit big endian - "/Nbase_type", # / - $binaryHeader - ); - } catch ( Exception $mwe ) { - return false; - } - - # Check values - if ( $header['magic'] !== 'gimp xcf' ) { - wfDebug( __METHOD__ . " '$filename' has invalid magic signature.\n" ); - - return false; - } - # TODO: we might want to check for sane values of width and height - - wfDebug( __METHOD__ . - ": canvas size of '$filename' is {$header['width']} x {$header['height']} px\n" ); - - return $header; - } - - /** - * Store the channel type - * - * Greyscale files need different command line options. - * - * @param File|FSFile $file The image object, or false if there isn't one. - * Warning, FSFile::getPropsFromPath might pass an (object)array() instead (!) - * @param string $filename - * @return string - */ - public function getMetadata( $file, $filename ) { - $header = self::getXCFMetaData( $filename ); - $metadata = []; - if ( $header ) { - // Try to be consistent with the names used by PNG files. - // Unclear from base media type if it has an alpha layer, - // so just assume that it does since it "potentially" could. - switch ( $header['base_type'] ) { - case 0: - $metadata['colorType'] = 'truecolour-alpha'; - break; - case 1: - $metadata['colorType'] = 'greyscale-alpha'; - break; - case 2: - $metadata['colorType'] = 'index-coloured'; - break; - default: - $metadata['colorType'] = 'unknown'; - } - } else { - // Marker to prevent repeated attempted extraction - $metadata['error'] = true; - } - return serialize( $metadata ); - } - - /** - * Should we refresh the metadata - * - * @param File $file The file object for the file in question - * @param string $metadata Serialized metadata - * @return bool One of the self::METADATA_(BAD|GOOD|COMPATIBLE) constants - */ - public function isMetadataValid( $file, $metadata ) { - if ( !$metadata ) { - // Old metadata when we just put an empty string in there - return self::METADATA_BAD; - } else { - return self::METADATA_GOOD; - } - } - - /** - * Must use "im" for XCF - * - * @param string $dstPath - * @param bool $checkDstPath - * @return string - */ - protected function getScalerType( $dstPath, $checkDstPath = true ) { - return "im"; - } - - /** - * Can we render this file? - * - * Image magick doesn't support indexed xcf files as of current - * writing (as of 6.8.9-3) - * @param File $file - * @return bool - */ - public function canRender( $file ) { - Wikimedia\suppressWarnings(); - $xcfMeta = unserialize( $file->getMetadata() ); - Wikimedia\restoreWarnings(); - if ( isset( $xcfMeta['colorType'] ) && $xcfMeta['colorType'] === 'index-coloured' ) { - return false; - } - return parent::canRender( $file ); - } -} diff --git a/includes/media/XCFHandler.php b/includes/media/XCFHandler.php new file mode 100644 index 0000000000..0cb618ffd8 --- /dev/null +++ b/includes/media/XCFHandler.php @@ -0,0 +1,228 @@ + $header['width'], + 1 => $header['height'], + 2 => null, # IMAGETYPE constant, none exist for XCF. + 3 => "height=\"{$header['height']}\" width=\"{$header['width']}\"", + 'mime' => 'image/x-xcf', + 'channels' => null, + 'bits' => 8, # Always 8-bits per color + ]; + } + + /** + * Metadata for a given XCF file + * + * Will return false if file magic signature is not recognized + * @author Hexmode + * @author Hashar + * + * @param string $filename Full path to a XCF file + * @return bool|array Metadata Array just like PHP getimagesize() + */ + static function getXCFMetaData( $filename ) { + # Decode master structure + $f = fopen( $filename, 'rb' ); + if ( !$f ) { + return false; + } + # The image structure always starts at offset 0 in the XCF file. + # So we just read it :-) + $binaryHeader = fread( $f, 26 ); + fclose( $f ); + + /** + * Master image structure: + * + * byte[9] "gimp xcf " File type magic + * byte[4] version XCF version + * "file" - version 0 + * "v001" - version 1 + * "v002" - version 2 + * byte 0 Zero-terminator for version tag + * uint32 width With of canvas + * uint32 height Height of canvas + * uint32 base_type Color mode of the image; one of + * 0: RGB color + * 1: Grayscale + * 2: Indexed color + * (enum GimpImageBaseType in libgimpbase/gimpbaseenums.h) + */ + try { + $header = wfUnpack( + "A9magic" . # A: space padded + "/a5version" . # a: zero padded + "/Nwidth" . # \ + "/Nheight" . # N: unsigned long 32bit big endian + "/Nbase_type", # / + $binaryHeader + ); + } catch ( Exception $mwe ) { + return false; + } + + # Check values + if ( $header['magic'] !== 'gimp xcf' ) { + wfDebug( __METHOD__ . " '$filename' has invalid magic signature.\n" ); + + return false; + } + # TODO: we might want to check for sane values of width and height + + wfDebug( __METHOD__ . + ": canvas size of '$filename' is {$header['width']} x {$header['height']} px\n" ); + + return $header; + } + + /** + * Store the channel type + * + * Greyscale files need different command line options. + * + * @param File|FSFile $file The image object, or false if there isn't one. + * Warning, FSFile::getPropsFromPath might pass an (object)array() instead (!) + * @param string $filename + * @return string + */ + public function getMetadata( $file, $filename ) { + $header = self::getXCFMetaData( $filename ); + $metadata = []; + if ( $header ) { + // Try to be consistent with the names used by PNG files. + // Unclear from base media type if it has an alpha layer, + // so just assume that it does since it "potentially" could. + switch ( $header['base_type'] ) { + case 0: + $metadata['colorType'] = 'truecolour-alpha'; + break; + case 1: + $metadata['colorType'] = 'greyscale-alpha'; + break; + case 2: + $metadata['colorType'] = 'index-coloured'; + break; + default: + $metadata['colorType'] = 'unknown'; + } + } else { + // Marker to prevent repeated attempted extraction + $metadata['error'] = true; + } + return serialize( $metadata ); + } + + /** + * Should we refresh the metadata + * + * @param File $file The file object for the file in question + * @param string $metadata Serialized metadata + * @return bool One of the self::METADATA_(BAD|GOOD|COMPATIBLE) constants + */ + public function isMetadataValid( $file, $metadata ) { + if ( !$metadata ) { + // Old metadata when we just put an empty string in there + return self::METADATA_BAD; + } else { + return self::METADATA_GOOD; + } + } + + /** + * Must use "im" for XCF + * + * @param string $dstPath + * @param bool $checkDstPath + * @return string + */ + protected function getScalerType( $dstPath, $checkDstPath = true ) { + return "im"; + } + + /** + * Can we render this file? + * + * Image magick doesn't support indexed xcf files as of current + * writing (as of 6.8.9-3) + * @param File $file + * @return bool + */ + public function canRender( $file ) { + Wikimedia\suppressWarnings(); + $xcfMeta = unserialize( $file->getMetadata() ); + Wikimedia\restoreWarnings(); + if ( isset( $xcfMeta['colorType'] ) && $xcfMeta['colorType'] === 'index-coloured' ) { + return false; + } + return parent::canRender( $file ); + } +} diff --git a/tests/phpunit/includes/media/GIFHandlerTest.php b/tests/phpunit/includes/media/GIFHandlerTest.php new file mode 100644 index 0000000000..4dd7443e48 --- /dev/null +++ b/tests/phpunit/includes/media/GIFHandlerTest.php @@ -0,0 +1,172 @@ +handler = new GIFHandler(); + } + + /** + * @covers GIFHandler::getMetadata + */ + public function testInvalidFile() { + $res = $this->handler->getMetadata( null, $this->filePath . '/README' ); + $this->assertEquals( GIFHandler::BROKEN_FILE, $res ); + } + + /** + * @param string $filename Basename of the file to check + * @param bool $expected Expected result. + * @dataProvider provideIsAnimated + * @covers GIFHandler::isAnimatedImage + */ + public function testIsAnimanted( $filename, $expected ) { + $file = $this->dataFile( $filename, 'image/gif' ); + $actual = $this->handler->isAnimatedImage( $file ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideIsAnimated() { + return [ + [ 'animated.gif', true ], + [ 'nonanimated.gif', false ], + ]; + } + + /** + * @param string $filename + * @param int $expected Total image area + * @dataProvider provideGetImageArea + * @covers GIFHandler::getImageArea + */ + public function testGetImageArea( $filename, $expected ) { + $file = $this->dataFile( $filename, 'image/gif' ); + $actual = $this->handler->getImageArea( $file, $file->getWidth(), $file->getHeight() ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideGetImageArea() { + return [ + [ 'animated.gif', 5400 ], + [ 'nonanimated.gif', 1350 ], + ]; + } + + /** + * @param string $metadata Serialized metadata + * @param int $expected One of the class constants of GIFHandler + * @dataProvider provideIsMetadataValid + * @covers GIFHandler::isMetadataValid + */ + public function testIsMetadataValid( $metadata, $expected ) { + $actual = $this->handler->isMetadataValid( null, $metadata ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideIsMetadataValid() { + // phpcs:disable Generic.Files.LineLength + return [ + [ GIFHandler::BROKEN_FILE, GIFHandler::METADATA_GOOD ], + [ '', GIFHandler::METADATA_BAD ], + [ null, GIFHandler::METADATA_BAD ], + [ 'Something invalid!', GIFHandler::METADATA_BAD ], + [ + 'a:4:{s:10:"frameCount";i:1;s:6:"looped";b:0;s:8:"duration";d:0.1000000000000000055511151231257827021181583404541015625;s:8:"metadata";a:2:{s:14:"GIFFileComment";a:1:{i:0;s:35:"GIF test file ⁕ Created with GIMP";}s:15:"_MW_GIF_VERSION";i:1;}}', + GIFHandler::METADATA_GOOD + ], + ]; + // phpcs:enable + } + + /** + * @param string $filename + * @param string $expected Serialized array + * @dataProvider provideGetMetadata + * @covers GIFHandler::getMetadata + */ + public function testGetMetadata( $filename, $expected ) { + $file = $this->dataFile( $filename, 'image/gif' ); + $actual = $this->handler->getMetadata( $file, "$this->filePath/$filename" ); + $this->assertEquals( unserialize( $expected ), unserialize( $actual ) ); + } + + public static function provideGetMetadata() { + // phpcs:disable Generic.Files.LineLength + return [ + [ + 'nonanimated.gif', + 'a:4:{s:10:"frameCount";i:1;s:6:"looped";b:0;s:8:"duration";d:0.1000000000000000055511151231257827021181583404541015625;s:8:"metadata";a:2:{s:14:"GIFFileComment";a:1:{i:0;s:35:"GIF test file ⁕ Created with GIMP";}s:15:"_MW_GIF_VERSION";i:1;}}' + ], + [ + 'animated-xmp.gif', + 'a:4:{s:10:"frameCount";i:4;s:6:"looped";b:1;s:8:"duration";d:2.399999999999999911182158029987476766109466552734375;s:8:"metadata";a:5:{s:6:"Artist";s:7:"Bawolff";s:16:"ImageDescription";a:2:{s:9:"x-default";s:18:"A file to test GIF";s:5:"_type";s:4:"lang";}s:15:"SublocationDest";s:13:"The interwebs";s:14:"GIFFileComment";a:1:{i:0;s:16:"GIƒ·test·file";}s:15:"_MW_GIF_VERSION";i:1;}}' + ], + ]; + // phpcs:enable + } + + /** + * @param string $filename + * @param string $expected Serialized array + * @dataProvider provideGetIndependentMetaArray + * @covers GIFHandler::getCommonMetaArray + */ + public function testGetIndependentMetaArray( $filename, $expected ) { + $file = $this->dataFile( $filename, 'image/gif' ); + $actual = $this->handler->getCommonMetaArray( $file ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideGetIndependentMetaArray() { + return [ + [ 'nonanimated.gif', [ + 'GIFFileComment' => [ + 'GIF test file ⁕ Created with GIMP', + ], + ] ], + [ 'animated-xmp.gif', + [ + 'Artist' => 'Bawolff', + 'ImageDescription' => [ + 'x-default' => 'A file to test GIF', + '_type' => 'lang', + ], + 'SublocationDest' => 'The interwebs', + 'GIFFileComment' => + [ + 'GIƒ·test·file', + ], + ] + ], + ]; + } + + /** + * @param string $filename + * @param float $expectedLength + * @dataProvider provideGetLength + * @covers GIFHandler::getLength + */ + public function testGetLength( $filename, $expectedLength ) { + $file = $this->dataFile( $filename, 'image/gif' ); + $actualLength = $file->getLength(); + $this->assertEquals( $expectedLength, $actualLength, '', 0.00001 ); + } + + public function provideGetLength() { + return [ + [ 'animated.gif', 2.4 ], + [ 'animated-xmp.gif', 2.4 ], + [ 'nonanimated', 0.0 ], + [ 'Bishzilla_blink.gif', 1.4 ], + ]; + } +} diff --git a/tests/phpunit/includes/media/GIFTest.php b/tests/phpunit/includes/media/GIFTest.php deleted file mode 100644 index 4dd7443e48..0000000000 --- a/tests/phpunit/includes/media/GIFTest.php +++ /dev/null @@ -1,172 +0,0 @@ -handler = new GIFHandler(); - } - - /** - * @covers GIFHandler::getMetadata - */ - public function testInvalidFile() { - $res = $this->handler->getMetadata( null, $this->filePath . '/README' ); - $this->assertEquals( GIFHandler::BROKEN_FILE, $res ); - } - - /** - * @param string $filename Basename of the file to check - * @param bool $expected Expected result. - * @dataProvider provideIsAnimated - * @covers GIFHandler::isAnimatedImage - */ - public function testIsAnimanted( $filename, $expected ) { - $file = $this->dataFile( $filename, 'image/gif' ); - $actual = $this->handler->isAnimatedImage( $file ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideIsAnimated() { - return [ - [ 'animated.gif', true ], - [ 'nonanimated.gif', false ], - ]; - } - - /** - * @param string $filename - * @param int $expected Total image area - * @dataProvider provideGetImageArea - * @covers GIFHandler::getImageArea - */ - public function testGetImageArea( $filename, $expected ) { - $file = $this->dataFile( $filename, 'image/gif' ); - $actual = $this->handler->getImageArea( $file, $file->getWidth(), $file->getHeight() ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideGetImageArea() { - return [ - [ 'animated.gif', 5400 ], - [ 'nonanimated.gif', 1350 ], - ]; - } - - /** - * @param string $metadata Serialized metadata - * @param int $expected One of the class constants of GIFHandler - * @dataProvider provideIsMetadataValid - * @covers GIFHandler::isMetadataValid - */ - public function testIsMetadataValid( $metadata, $expected ) { - $actual = $this->handler->isMetadataValid( null, $metadata ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideIsMetadataValid() { - // phpcs:disable Generic.Files.LineLength - return [ - [ GIFHandler::BROKEN_FILE, GIFHandler::METADATA_GOOD ], - [ '', GIFHandler::METADATA_BAD ], - [ null, GIFHandler::METADATA_BAD ], - [ 'Something invalid!', GIFHandler::METADATA_BAD ], - [ - 'a:4:{s:10:"frameCount";i:1;s:6:"looped";b:0;s:8:"duration";d:0.1000000000000000055511151231257827021181583404541015625;s:8:"metadata";a:2:{s:14:"GIFFileComment";a:1:{i:0;s:35:"GIF test file ⁕ Created with GIMP";}s:15:"_MW_GIF_VERSION";i:1;}}', - GIFHandler::METADATA_GOOD - ], - ]; - // phpcs:enable - } - - /** - * @param string $filename - * @param string $expected Serialized array - * @dataProvider provideGetMetadata - * @covers GIFHandler::getMetadata - */ - public function testGetMetadata( $filename, $expected ) { - $file = $this->dataFile( $filename, 'image/gif' ); - $actual = $this->handler->getMetadata( $file, "$this->filePath/$filename" ); - $this->assertEquals( unserialize( $expected ), unserialize( $actual ) ); - } - - public static function provideGetMetadata() { - // phpcs:disable Generic.Files.LineLength - return [ - [ - 'nonanimated.gif', - 'a:4:{s:10:"frameCount";i:1;s:6:"looped";b:0;s:8:"duration";d:0.1000000000000000055511151231257827021181583404541015625;s:8:"metadata";a:2:{s:14:"GIFFileComment";a:1:{i:0;s:35:"GIF test file ⁕ Created with GIMP";}s:15:"_MW_GIF_VERSION";i:1;}}' - ], - [ - 'animated-xmp.gif', - 'a:4:{s:10:"frameCount";i:4;s:6:"looped";b:1;s:8:"duration";d:2.399999999999999911182158029987476766109466552734375;s:8:"metadata";a:5:{s:6:"Artist";s:7:"Bawolff";s:16:"ImageDescription";a:2:{s:9:"x-default";s:18:"A file to test GIF";s:5:"_type";s:4:"lang";}s:15:"SublocationDest";s:13:"The interwebs";s:14:"GIFFileComment";a:1:{i:0;s:16:"GIƒ·test·file";}s:15:"_MW_GIF_VERSION";i:1;}}' - ], - ]; - // phpcs:enable - } - - /** - * @param string $filename - * @param string $expected Serialized array - * @dataProvider provideGetIndependentMetaArray - * @covers GIFHandler::getCommonMetaArray - */ - public function testGetIndependentMetaArray( $filename, $expected ) { - $file = $this->dataFile( $filename, 'image/gif' ); - $actual = $this->handler->getCommonMetaArray( $file ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideGetIndependentMetaArray() { - return [ - [ 'nonanimated.gif', [ - 'GIFFileComment' => [ - 'GIF test file ⁕ Created with GIMP', - ], - ] ], - [ 'animated-xmp.gif', - [ - 'Artist' => 'Bawolff', - 'ImageDescription' => [ - 'x-default' => 'A file to test GIF', - '_type' => 'lang', - ], - 'SublocationDest' => 'The interwebs', - 'GIFFileComment' => - [ - 'GIƒ·test·file', - ], - ] - ], - ]; - } - - /** - * @param string $filename - * @param float $expectedLength - * @dataProvider provideGetLength - * @covers GIFHandler::getLength - */ - public function testGetLength( $filename, $expectedLength ) { - $file = $this->dataFile( $filename, 'image/gif' ); - $actualLength = $file->getLength(); - $this->assertEquals( $expectedLength, $actualLength, '', 0.00001 ); - } - - public function provideGetLength() { - return [ - [ 'animated.gif', 2.4 ], - [ 'animated-xmp.gif', 2.4 ], - [ 'nonanimated', 0.0 ], - [ 'Bishzilla_blink.gif', 1.4 ], - ]; - } -} diff --git a/tests/phpunit/includes/media/PNGHandlerTest.php b/tests/phpunit/includes/media/PNGHandlerTest.php new file mode 100644 index 0000000000..5a66586e25 --- /dev/null +++ b/tests/phpunit/includes/media/PNGHandlerTest.php @@ -0,0 +1,161 @@ +handler = new PNGHandler(); + } + + /** + * @covers PNGHandler::getMetadata + */ + public function testInvalidFile() { + $res = $this->handler->getMetadata( null, $this->filePath . '/README' ); + $this->assertEquals( PNGHandler::BROKEN_FILE, $res ); + } + + /** + * @param string $filename Basename of the file to check + * @param bool $expected Expected result. + * @dataProvider provideIsAnimated + * @covers PNGHandler::isAnimatedImage + */ + public function testIsAnimanted( $filename, $expected ) { + $file = $this->dataFile( $filename, 'image/png' ); + $actual = $this->handler->isAnimatedImage( $file ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideIsAnimated() { + return [ + [ 'Animated_PNG_example_bouncing_beach_ball.png', true ], + [ '1bit-png.png', false ], + ]; + } + + /** + * @param string $filename + * @param int $expected Total image area + * @dataProvider provideGetImageArea + * @covers PNGHandler::getImageArea + */ + public function testGetImageArea( $filename, $expected ) { + $file = $this->dataFile( $filename, 'image/png' ); + $actual = $this->handler->getImageArea( $file, $file->getWidth(), $file->getHeight() ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideGetImageArea() { + return [ + [ '1bit-png.png', 2500 ], + [ 'greyscale-png.png', 2500 ], + [ 'Png-native-test.png', 126000 ], + [ 'Animated_PNG_example_bouncing_beach_ball.png', 10000 ], + ]; + } + + /** + * @param string $metadata Serialized metadata + * @param int $expected One of the class constants of PNGHandler + * @dataProvider provideIsMetadataValid + * @covers PNGHandler::isMetadataValid + */ + public function testIsMetadataValid( $metadata, $expected ) { + $actual = $this->handler->isMetadataValid( null, $metadata ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideIsMetadataValid() { + // phpcs:disable Generic.Files.LineLength + return [ + [ PNGHandler::BROKEN_FILE, PNGHandler::METADATA_GOOD ], + [ '', PNGHandler::METADATA_BAD ], + [ null, PNGHandler::METADATA_BAD ], + [ 'Something invalid!', PNGHandler::METADATA_BAD ], + [ + 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:8;s:9:"colorType";s:10:"truecolour";s:8:"metadata";a:1:{s:15:"_MW_PNG_VERSION";i:1;}}', + PNGHandler::METADATA_GOOD + ], + ]; + // phpcs:enable + } + + /** + * @param string $filename + * @param string $expected Serialized array + * @dataProvider provideGetMetadata + * @covers PNGHandler::getMetadata + */ + public function testGetMetadata( $filename, $expected ) { + $file = $this->dataFile( $filename, 'image/png' ); + $actual = $this->handler->getMetadata( $file, "$this->filePath/$filename" ); +// $this->assertEquals( unserialize( $expected ), unserialize( $actual ) ); + $this->assertEquals( ( $expected ), ( $actual ) ); + } + + public static function provideGetMetadata() { + // phpcs:disable Generic.Files.LineLength + return [ + [ + 'rgb-na-png.png', + 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:8;s:9:"colorType";s:10:"truecolour";s:8:"metadata";a:1:{s:15:"_MW_PNG_VERSION";i:1;}}' + ], + [ + 'xmp.png', + 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:1;s:9:"colorType";s:14:"index-coloured";s:8:"metadata";a:2:{s:12:"SerialNumber";s:9:"123456789";s:15:"_MW_PNG_VERSION";i:1;}}' + ], + ]; + // phpcs:enable + } + + /** + * @param string $filename + * @param array $expected Expected standard metadata + * @dataProvider provideGetIndependentMetaArray + * @covers PNGHandler::getCommonMetaArray + */ + public function testGetIndependentMetaArray( $filename, $expected ) { + $file = $this->dataFile( $filename, 'image/png' ); + $actual = $this->handler->getCommonMetaArray( $file ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideGetIndependentMetaArray() { + return [ + [ 'rgb-na-png.png', [] ], + [ 'xmp.png', + [ + 'SerialNumber' => '123456789', + ] + ], + ]; + } + + /** + * @param string $filename + * @param float $expectedLength + * @dataProvider provideGetLength + * @covers PNGHandler::getLength + */ + public function testGetLength( $filename, $expectedLength ) { + $file = $this->dataFile( $filename, 'image/png' ); + $actualLength = $file->getLength(); + $this->assertEquals( $expectedLength, $actualLength, '', 0.00001 ); + } + + public function provideGetLength() { + return [ + [ 'Animated_PNG_example_bouncing_beach_ball.png', 1.5 ], + [ 'Png-native-test.png', 0.0 ], + [ 'greyscale-png.png', 0.0 ], + [ '1bit-png.png', 0.0 ], + ]; + } +} diff --git a/tests/phpunit/includes/media/PNGTest.php b/tests/phpunit/includes/media/PNGTest.php deleted file mode 100644 index 5a66586e25..0000000000 --- a/tests/phpunit/includes/media/PNGTest.php +++ /dev/null @@ -1,161 +0,0 @@ -handler = new PNGHandler(); - } - - /** - * @covers PNGHandler::getMetadata - */ - public function testInvalidFile() { - $res = $this->handler->getMetadata( null, $this->filePath . '/README' ); - $this->assertEquals( PNGHandler::BROKEN_FILE, $res ); - } - - /** - * @param string $filename Basename of the file to check - * @param bool $expected Expected result. - * @dataProvider provideIsAnimated - * @covers PNGHandler::isAnimatedImage - */ - public function testIsAnimanted( $filename, $expected ) { - $file = $this->dataFile( $filename, 'image/png' ); - $actual = $this->handler->isAnimatedImage( $file ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideIsAnimated() { - return [ - [ 'Animated_PNG_example_bouncing_beach_ball.png', true ], - [ '1bit-png.png', false ], - ]; - } - - /** - * @param string $filename - * @param int $expected Total image area - * @dataProvider provideGetImageArea - * @covers PNGHandler::getImageArea - */ - public function testGetImageArea( $filename, $expected ) { - $file = $this->dataFile( $filename, 'image/png' ); - $actual = $this->handler->getImageArea( $file, $file->getWidth(), $file->getHeight() ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideGetImageArea() { - return [ - [ '1bit-png.png', 2500 ], - [ 'greyscale-png.png', 2500 ], - [ 'Png-native-test.png', 126000 ], - [ 'Animated_PNG_example_bouncing_beach_ball.png', 10000 ], - ]; - } - - /** - * @param string $metadata Serialized metadata - * @param int $expected One of the class constants of PNGHandler - * @dataProvider provideIsMetadataValid - * @covers PNGHandler::isMetadataValid - */ - public function testIsMetadataValid( $metadata, $expected ) { - $actual = $this->handler->isMetadataValid( null, $metadata ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideIsMetadataValid() { - // phpcs:disable Generic.Files.LineLength - return [ - [ PNGHandler::BROKEN_FILE, PNGHandler::METADATA_GOOD ], - [ '', PNGHandler::METADATA_BAD ], - [ null, PNGHandler::METADATA_BAD ], - [ 'Something invalid!', PNGHandler::METADATA_BAD ], - [ - 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:8;s:9:"colorType";s:10:"truecolour";s:8:"metadata";a:1:{s:15:"_MW_PNG_VERSION";i:1;}}', - PNGHandler::METADATA_GOOD - ], - ]; - // phpcs:enable - } - - /** - * @param string $filename - * @param string $expected Serialized array - * @dataProvider provideGetMetadata - * @covers PNGHandler::getMetadata - */ - public function testGetMetadata( $filename, $expected ) { - $file = $this->dataFile( $filename, 'image/png' ); - $actual = $this->handler->getMetadata( $file, "$this->filePath/$filename" ); -// $this->assertEquals( unserialize( $expected ), unserialize( $actual ) ); - $this->assertEquals( ( $expected ), ( $actual ) ); - } - - public static function provideGetMetadata() { - // phpcs:disable Generic.Files.LineLength - return [ - [ - 'rgb-na-png.png', - 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:8;s:9:"colorType";s:10:"truecolour";s:8:"metadata";a:1:{s:15:"_MW_PNG_VERSION";i:1;}}' - ], - [ - 'xmp.png', - 'a:6:{s:10:"frameCount";i:0;s:9:"loopCount";i:1;s:8:"duration";d:0;s:8:"bitDepth";i:1;s:9:"colorType";s:14:"index-coloured";s:8:"metadata";a:2:{s:12:"SerialNumber";s:9:"123456789";s:15:"_MW_PNG_VERSION";i:1;}}' - ], - ]; - // phpcs:enable - } - - /** - * @param string $filename - * @param array $expected Expected standard metadata - * @dataProvider provideGetIndependentMetaArray - * @covers PNGHandler::getCommonMetaArray - */ - public function testGetIndependentMetaArray( $filename, $expected ) { - $file = $this->dataFile( $filename, 'image/png' ); - $actual = $this->handler->getCommonMetaArray( $file ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideGetIndependentMetaArray() { - return [ - [ 'rgb-na-png.png', [] ], - [ 'xmp.png', - [ - 'SerialNumber' => '123456789', - ] - ], - ]; - } - - /** - * @param string $filename - * @param float $expectedLength - * @dataProvider provideGetLength - * @covers PNGHandler::getLength - */ - public function testGetLength( $filename, $expectedLength ) { - $file = $this->dataFile( $filename, 'image/png' ); - $actualLength = $file->getLength(); - $this->assertEquals( $expectedLength, $actualLength, '', 0.00001 ); - } - - public function provideGetLength() { - return [ - [ 'Animated_PNG_example_bouncing_beach_ball.png', 1.5 ], - [ 'Png-native-test.png', 0.0 ], - [ 'greyscale-png.png', 0.0 ], - [ '1bit-png.png', 0.0 ], - ]; - } -} diff --git a/tests/phpunit/includes/media/WebPHandlerTest.php b/tests/phpunit/includes/media/WebPHandlerTest.php new file mode 100644 index 0000000000..ac0ad98edd --- /dev/null +++ b/tests/phpunit/includes/media/WebPHandlerTest.php @@ -0,0 +1,151 @@ +tempFileName = tempnam( wfTempDir(), 'WEBP' ); + } + + public function tearDown() { + parent::tearDown(); + unlink( $this->tempFileName ); + } + + /** + * @dataProvider provideTestExtractMetaData + */ + public function testExtractMetaData( $header, $expectedResult ) { + // Put header into file + file_put_contents( $this->tempFileName, $header ); + + $this->assertEquals( $expectedResult, WebPHandler::extractMetadata( $this->tempFileName ) ); + } + + public function provideTestExtractMetaData() { + // phpcs:disable Generic.Files.LineLength + return [ + // Files from https://developers.google.com/speed/webp/gallery2 + [ "\x52\x49\x46\x46\x90\x68\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x83\x68\x01\x00\x2F\x8F\x01\x4B\x10\x8D\x38\x6C\xDB\x46\x92\xE0\xE0\x82\x7B\x6C", + [ 'compression' => 'lossless', 'width' => 400, 'height' => 301 ] ], + [ "\x52\x49\x46\x46\x64\x5B\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x8F\x01\x00\x2C\x01\x00\x41\x4C\x50\x48\xE5\x0E", + [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 400, 'height' => 301 ] ], + [ "\x52\x49\x46\x46\xA8\x72\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x9B\x72\x00\x00\x2F\x81\x81\x62\x10\x8D\x40\x8C\x24\x39\x6E\x73\x73\x38\x01\x96", + [ 'compression' => 'lossless', 'width' => 386, 'height' => 395 ] ], + [ "\x52\x49\x46\x46\xE0\x42\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x81\x01\x00\x8A\x01\x00\x41\x4C\x50\x48\x56\x10", + [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 386, 'height' => 395 ] ], + [ "\x52\x49\x46\x46\x70\x61\x02\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x63\x61\x02\x00\x2F\x1F\xC3\x95\x10\x8D\xC8\x72\xDB\xC8\x92\x24\xD8\x91\xD9\x91", + [ 'compression' => 'lossless', 'width' => 800, 'height' => 600 ] ], + [ "\x52\x49\x46\x46\x1C\x1D\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x1F\x03\x00\x57\x02\x00\x41\x4C\x50\x48\x25\x8B", + [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 800, 'height' => 600 ] ], + [ "\x52\x49\x46\x46\xFA\xC5\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xEE\xC5\x00\x00\x2F\xA4\x81\x28\x10\x8D\x40\x68\x24\xC9\x91\xA4\xAE\xF3\x97\x75", + [ 'compression' => 'lossless', 'width' => 421, 'height' => 163 ] ], + [ "\x52\x49\x46\x46\xF6\x5D\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\xA4\x01\x00\xA2\x00\x00\x41\x4C\x50\x48\x38\x1A", + [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 421, 'height' => 163 ] ], + [ "\x52\x49\x46\x46\xC4\x96\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xB8\x96\x01\x00\x2F\x2B\xC1\x4A\x10\x11\x87\x6D\xDB\x48\x12\xFC\x60\xB0\x83\x24", + [ 'compression' => 'lossless', 'width' => 300, 'height' => 300 ] ], + [ "\x52\x49\x46\x46\x0A\x11\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x2B\x01\x00\x2B\x01\x00\x41\x4C\x50\x48\x67\x6E", + [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 300, 'height' => 300 ] ], + + // Lossy files from https://developers.google.com/speed/webp/gallery1 + [ "\x52\x49\x46\x46\x68\x76\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\x5C\x76\x00\x00\xD2\xBE\x01\x9D\x01\x2A\x26\x02\x70\x01\x3E\xD5\x4E\x97\x43\xA2", + [ 'compression' => 'lossy', 'width' => 550, 'height' => 368 ] ], + [ "\x52\x49\x46\x46\xB0\xEC\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\xA4\xEC\x00\x00\xB2\x4B\x02\x9D\x01\x2A\x26\x02\x94\x01\x3E\xD1\x50\x96\x46\x26", + [ 'compression' => 'lossy', 'width' => 550, 'height' => 404 ] ], + [ "\x52\x49\x46\x46\x7A\x19\x03\x00\x57\x45\x42\x50\x56\x50\x38\x20\x6E\x19\x03\x00\xB2\xF8\x09\x9D\x01\x2A\x00\x05\xD0\x02\x3E\xAD\x46\x99\x4A\xA5", + [ 'compression' => 'lossy', 'width' => 1280, 'height' => 720 ] ], + [ "\x52\x49\x46\x46\x44\xB3\x02\x00\x57\x45\x42\x50\x56\x50\x38\x20\x38\xB3\x02\x00\x52\x57\x06\x9D\x01\x2A\x00\x04\x04\x03\x3E\xA5\x44\x96\x49\x26", + [ 'compression' => 'lossy', 'width' => 1024, 'height' => 772 ] ], + [ "\x52\x49\x46\x46\x02\x43\x01\x00\x57\x45\x42\x50\x56\x50\x38\x20\xF6\x42\x01\x00\x12\xC0\x05\x9D\x01\x2A\x00\x04\xF0\x02\x3E\x79\x34\x93\x47\xA4", + [ 'compression' => 'lossy', 'width' => 1024, 'height' => 752 ] ], + + // Animated file from https://groups.google.com/a/chromium.org/d/topic/blink-dev/Y8tRC4mdQz8/discussion + [ "\x52\x49\x46\x46\xD0\x0B\x02\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x12\x00\x00\x00\x3F\x01\x00\x3F\x01\x00\x41\x4E", + [ 'compression' => 'unknown', 'animated' => true, 'transparency' => true, 'width' => 320, 'height' => 320 ] ], + + // Error cases + [ '', false ], + [ ' ', false ], + [ 'RIFF ', false ], + [ 'RIFF1234WEBP ', false ], + [ 'RIFF1234WEBPVP8 ', false ], + [ 'RIFF1234WEBPVP8L ', false ], + ]; + // phpcs:enable + } + + /** + * @dataProvider provideTestWithFileExtractMetaData + */ + public function testWithFileExtractMetaData( $filename, $expectedResult ) { + $this->assertEquals( $expectedResult, WebPHandler::extractMetadata( $filename ) ); + } + + public function provideTestWithFileExtractMetaData() { + return [ + [ __DIR__ . '/../../data/media/2_webp_ll.webp', + [ + 'compression' => 'lossless', + 'width' => 386, + 'height' => 395 + ] + ], + [ __DIR__ . '/../../data/media/2_webp_a.webp', + [ + 'compression' => 'lossy', + 'animated' => false, + 'transparency' => true, + 'width' => 386, + 'height' => 395 + ] + ], + ]; + } + + /** + * @dataProvider provideTestGetImageSize + */ + public function testGetImageSize( $path, $expectedResult ) { + $handler = new WebPHandler(); + $this->assertEquals( $expectedResult, $handler->getImageSize( null, $path ) ); + } + + public function provideTestGetImageSize() { + return [ + // Public domain files from https://developers.google.com/speed/webp/gallery2 + [ __DIR__ . '/../../data/media/2_webp_a.webp', [ 386, 395 ] ], + [ __DIR__ . '/../../data/media/2_webp_ll.webp', [ 386, 395 ] ], + [ __DIR__ . '/../../data/media/webp_animated.webp', [ 300, 225 ] ], + + // Error cases + [ __FILE__, false ], + ]; + } + + /** + * Tests the WebP MIME detection. This should really be a separate test, but sticking it + * here for now. + * + * @dataProvider provideTestGetMimeType + */ + public function testGuessMimeType( $path ) { + $mime = MediaWiki\MediaWikiServices::getInstance()->getMimeAnalyzer(); + $this->assertEquals( 'image/webp', $mime->guessMimeType( $path, false ) ); + } + + public function provideTestGetMimeType() { + return [ + // Public domain files from https://developers.google.com/speed/webp/gallery2 + [ __DIR__ . '/../../data/media/2_webp_a.webp' ], + [ __DIR__ . '/../../data/media/2_webp_ll.webp' ], + [ __DIR__ . '/../../data/media/webp_animated.webp' ], + ]; + } +} + +/* Python code to extract a header and convert to PHP format: + * print '"%s"' % ''.implode( '\\x%02X' % ord(c) for c in urllib.urlopen(url).read(36) ) + */ diff --git a/tests/phpunit/includes/media/WebPTest.php b/tests/phpunit/includes/media/WebPTest.php deleted file mode 100644 index ac0ad98edd..0000000000 --- a/tests/phpunit/includes/media/WebPTest.php +++ /dev/null @@ -1,151 +0,0 @@ -tempFileName = tempnam( wfTempDir(), 'WEBP' ); - } - - public function tearDown() { - parent::tearDown(); - unlink( $this->tempFileName ); - } - - /** - * @dataProvider provideTestExtractMetaData - */ - public function testExtractMetaData( $header, $expectedResult ) { - // Put header into file - file_put_contents( $this->tempFileName, $header ); - - $this->assertEquals( $expectedResult, WebPHandler::extractMetadata( $this->tempFileName ) ); - } - - public function provideTestExtractMetaData() { - // phpcs:disable Generic.Files.LineLength - return [ - // Files from https://developers.google.com/speed/webp/gallery2 - [ "\x52\x49\x46\x46\x90\x68\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x83\x68\x01\x00\x2F\x8F\x01\x4B\x10\x8D\x38\x6C\xDB\x46\x92\xE0\xE0\x82\x7B\x6C", - [ 'compression' => 'lossless', 'width' => 400, 'height' => 301 ] ], - [ "\x52\x49\x46\x46\x64\x5B\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x8F\x01\x00\x2C\x01\x00\x41\x4C\x50\x48\xE5\x0E", - [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 400, 'height' => 301 ] ], - [ "\x52\x49\x46\x46\xA8\x72\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x9B\x72\x00\x00\x2F\x81\x81\x62\x10\x8D\x40\x8C\x24\x39\x6E\x73\x73\x38\x01\x96", - [ 'compression' => 'lossless', 'width' => 386, 'height' => 395 ] ], - [ "\x52\x49\x46\x46\xE0\x42\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x81\x01\x00\x8A\x01\x00\x41\x4C\x50\x48\x56\x10", - [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 386, 'height' => 395 ] ], - [ "\x52\x49\x46\x46\x70\x61\x02\x00\x57\x45\x42\x50\x56\x50\x38\x4C\x63\x61\x02\x00\x2F\x1F\xC3\x95\x10\x8D\xC8\x72\xDB\xC8\x92\x24\xD8\x91\xD9\x91", - [ 'compression' => 'lossless', 'width' => 800, 'height' => 600 ] ], - [ "\x52\x49\x46\x46\x1C\x1D\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x1F\x03\x00\x57\x02\x00\x41\x4C\x50\x48\x25\x8B", - [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 800, 'height' => 600 ] ], - [ "\x52\x49\x46\x46\xFA\xC5\x00\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xEE\xC5\x00\x00\x2F\xA4\x81\x28\x10\x8D\x40\x68\x24\xC9\x91\xA4\xAE\xF3\x97\x75", - [ 'compression' => 'lossless', 'width' => 421, 'height' => 163 ] ], - [ "\x52\x49\x46\x46\xF6\x5D\x00\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\xA4\x01\x00\xA2\x00\x00\x41\x4C\x50\x48\x38\x1A", - [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 421, 'height' => 163 ] ], - [ "\x52\x49\x46\x46\xC4\x96\x01\x00\x57\x45\x42\x50\x56\x50\x38\x4C\xB8\x96\x01\x00\x2F\x2B\xC1\x4A\x10\x11\x87\x6D\xDB\x48\x12\xFC\x60\xB0\x83\x24", - [ 'compression' => 'lossless', 'width' => 300, 'height' => 300 ] ], - [ "\x52\x49\x46\x46\x0A\x11\x01\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x10\x00\x00\x00\x2B\x01\x00\x2B\x01\x00\x41\x4C\x50\x48\x67\x6E", - [ 'compression' => 'unknown', 'animated' => false, 'transparency' => true, 'width' => 300, 'height' => 300 ] ], - - // Lossy files from https://developers.google.com/speed/webp/gallery1 - [ "\x52\x49\x46\x46\x68\x76\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\x5C\x76\x00\x00\xD2\xBE\x01\x9D\x01\x2A\x26\x02\x70\x01\x3E\xD5\x4E\x97\x43\xA2", - [ 'compression' => 'lossy', 'width' => 550, 'height' => 368 ] ], - [ "\x52\x49\x46\x46\xB0\xEC\x00\x00\x57\x45\x42\x50\x56\x50\x38\x20\xA4\xEC\x00\x00\xB2\x4B\x02\x9D\x01\x2A\x26\x02\x94\x01\x3E\xD1\x50\x96\x46\x26", - [ 'compression' => 'lossy', 'width' => 550, 'height' => 404 ] ], - [ "\x52\x49\x46\x46\x7A\x19\x03\x00\x57\x45\x42\x50\x56\x50\x38\x20\x6E\x19\x03\x00\xB2\xF8\x09\x9D\x01\x2A\x00\x05\xD0\x02\x3E\xAD\x46\x99\x4A\xA5", - [ 'compression' => 'lossy', 'width' => 1280, 'height' => 720 ] ], - [ "\x52\x49\x46\x46\x44\xB3\x02\x00\x57\x45\x42\x50\x56\x50\x38\x20\x38\xB3\x02\x00\x52\x57\x06\x9D\x01\x2A\x00\x04\x04\x03\x3E\xA5\x44\x96\x49\x26", - [ 'compression' => 'lossy', 'width' => 1024, 'height' => 772 ] ], - [ "\x52\x49\x46\x46\x02\x43\x01\x00\x57\x45\x42\x50\x56\x50\x38\x20\xF6\x42\x01\x00\x12\xC0\x05\x9D\x01\x2A\x00\x04\xF0\x02\x3E\x79\x34\x93\x47\xA4", - [ 'compression' => 'lossy', 'width' => 1024, 'height' => 752 ] ], - - // Animated file from https://groups.google.com/a/chromium.org/d/topic/blink-dev/Y8tRC4mdQz8/discussion - [ "\x52\x49\x46\x46\xD0\x0B\x02\x00\x57\x45\x42\x50\x56\x50\x38\x58\x0A\x00\x00\x00\x12\x00\x00\x00\x3F\x01\x00\x3F\x01\x00\x41\x4E", - [ 'compression' => 'unknown', 'animated' => true, 'transparency' => true, 'width' => 320, 'height' => 320 ] ], - - // Error cases - [ '', false ], - [ ' ', false ], - [ 'RIFF ', false ], - [ 'RIFF1234WEBP ', false ], - [ 'RIFF1234WEBPVP8 ', false ], - [ 'RIFF1234WEBPVP8L ', false ], - ]; - // phpcs:enable - } - - /** - * @dataProvider provideTestWithFileExtractMetaData - */ - public function testWithFileExtractMetaData( $filename, $expectedResult ) { - $this->assertEquals( $expectedResult, WebPHandler::extractMetadata( $filename ) ); - } - - public function provideTestWithFileExtractMetaData() { - return [ - [ __DIR__ . '/../../data/media/2_webp_ll.webp', - [ - 'compression' => 'lossless', - 'width' => 386, - 'height' => 395 - ] - ], - [ __DIR__ . '/../../data/media/2_webp_a.webp', - [ - 'compression' => 'lossy', - 'animated' => false, - 'transparency' => true, - 'width' => 386, - 'height' => 395 - ] - ], - ]; - } - - /** - * @dataProvider provideTestGetImageSize - */ - public function testGetImageSize( $path, $expectedResult ) { - $handler = new WebPHandler(); - $this->assertEquals( $expectedResult, $handler->getImageSize( null, $path ) ); - } - - public function provideTestGetImageSize() { - return [ - // Public domain files from https://developers.google.com/speed/webp/gallery2 - [ __DIR__ . '/../../data/media/2_webp_a.webp', [ 386, 395 ] ], - [ __DIR__ . '/../../data/media/2_webp_ll.webp', [ 386, 395 ] ], - [ __DIR__ . '/../../data/media/webp_animated.webp', [ 300, 225 ] ], - - // Error cases - [ __FILE__, false ], - ]; - } - - /** - * Tests the WebP MIME detection. This should really be a separate test, but sticking it - * here for now. - * - * @dataProvider provideTestGetMimeType - */ - public function testGuessMimeType( $path ) { - $mime = MediaWiki\MediaWikiServices::getInstance()->getMimeAnalyzer(); - $this->assertEquals( 'image/webp', $mime->guessMimeType( $path, false ) ); - } - - public function provideTestGetMimeType() { - return [ - // Public domain files from https://developers.google.com/speed/webp/gallery2 - [ __DIR__ . '/../../data/media/2_webp_a.webp' ], - [ __DIR__ . '/../../data/media/2_webp_ll.webp' ], - [ __DIR__ . '/../../data/media/webp_animated.webp' ], - ]; - } -} - -/* Python code to extract a header and convert to PHP format: - * print '"%s"' % ''.implode( '\\x%02X' % ord(c) for c in urllib.urlopen(url).read(36) ) - */ diff --git a/tests/phpunit/includes/media/XCFHandlerTest.php b/tests/phpunit/includes/media/XCFHandlerTest.php new file mode 100644 index 0000000000..b75335d6c0 --- /dev/null +++ b/tests/phpunit/includes/media/XCFHandlerTest.php @@ -0,0 +1,83 @@ +handler = new XCFHandler(); + } + + /** + * @param string $filename + * @param int $expectedWidth Width + * @param int $expectedHeight Height + * @dataProvider provideGetImageSize + * @covers XCFHandler::getImageSize + */ + public function testGetImageSize( $filename, $expectedWidth, $expectedHeight ) { + $file = $this->dataFile( $filename, 'image/x-xcf' ); + $actual = $this->handler->getImageSize( $file, $file->getLocalRefPath() ); + $this->assertEquals( $expectedWidth, $actual[0] ); + $this->assertEquals( $expectedHeight, $actual[1] ); + } + + public static function provideGetImageSize() { + return [ + [ '80x60-2layers.xcf', 80, 60 ], + [ '80x60-RGB.xcf', 80, 60 ], + [ '80x60-Greyscale.xcf', 80, 60 ], + ]; + } + + /** + * @param string $metadata Serialized metadata + * @param int $expected One of the class constants of XCFHandler + * @dataProvider provideIsMetadataValid + * @covers XCFHandler::isMetadataValid + */ + public function testIsMetadataValid( $metadata, $expected ) { + $actual = $this->handler->isMetadataValid( null, $metadata ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideIsMetadataValid() { + return [ + [ '', XCFHandler::METADATA_BAD ], + [ serialize( [ 'error' => true ] ), XCFHandler::METADATA_GOOD ], + [ false, XCFHandler::METADATA_BAD ], + [ serialize( [ 'colorType' => 'greyscale-alpha' ] ), XCFHandler::METADATA_GOOD ], + ]; + } + + /** + * @param string $filename + * @param string $expected Serialized array + * @dataProvider provideGetMetadata + * @covers XCFHandler::getMetadata + */ + public function testGetMetadata( $filename, $expected ) { + $file = $this->dataFile( $filename, 'image/png' ); + $actual = $this->handler->getMetadata( $file, "$this->filePath/$filename" ); + $this->assertEquals( $expected, $actual ); + } + + public static function provideGetMetadata() { + return [ + [ '80x60-2layers.xcf', + 'a:1:{s:9:"colorType";s:16:"truecolour-alpha";}' + ], + [ '80x60-RGB.xcf', + 'a:1:{s:9:"colorType";s:16:"truecolour-alpha";}' + ], + [ '80x60-Greyscale.xcf', + 'a:1:{s:9:"colorType";s:15:"greyscale-alpha";}' + ], + ]; + } +} diff --git a/tests/phpunit/includes/media/XCFTest.php b/tests/phpunit/includes/media/XCFTest.php deleted file mode 100644 index b75335d6c0..0000000000 --- a/tests/phpunit/includes/media/XCFTest.php +++ /dev/null @@ -1,83 +0,0 @@ -handler = new XCFHandler(); - } - - /** - * @param string $filename - * @param int $expectedWidth Width - * @param int $expectedHeight Height - * @dataProvider provideGetImageSize - * @covers XCFHandler::getImageSize - */ - public function testGetImageSize( $filename, $expectedWidth, $expectedHeight ) { - $file = $this->dataFile( $filename, 'image/x-xcf' ); - $actual = $this->handler->getImageSize( $file, $file->getLocalRefPath() ); - $this->assertEquals( $expectedWidth, $actual[0] ); - $this->assertEquals( $expectedHeight, $actual[1] ); - } - - public static function provideGetImageSize() { - return [ - [ '80x60-2layers.xcf', 80, 60 ], - [ '80x60-RGB.xcf', 80, 60 ], - [ '80x60-Greyscale.xcf', 80, 60 ], - ]; - } - - /** - * @param string $metadata Serialized metadata - * @param int $expected One of the class constants of XCFHandler - * @dataProvider provideIsMetadataValid - * @covers XCFHandler::isMetadataValid - */ - public function testIsMetadataValid( $metadata, $expected ) { - $actual = $this->handler->isMetadataValid( null, $metadata ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideIsMetadataValid() { - return [ - [ '', XCFHandler::METADATA_BAD ], - [ serialize( [ 'error' => true ] ), XCFHandler::METADATA_GOOD ], - [ false, XCFHandler::METADATA_BAD ], - [ serialize( [ 'colorType' => 'greyscale-alpha' ] ), XCFHandler::METADATA_GOOD ], - ]; - } - - /** - * @param string $filename - * @param string $expected Serialized array - * @dataProvider provideGetMetadata - * @covers XCFHandler::getMetadata - */ - public function testGetMetadata( $filename, $expected ) { - $file = $this->dataFile( $filename, 'image/png' ); - $actual = $this->handler->getMetadata( $file, "$this->filePath/$filename" ); - $this->assertEquals( $expected, $actual ); - } - - public static function provideGetMetadata() { - return [ - [ '80x60-2layers.xcf', - 'a:1:{s:9:"colorType";s:16:"truecolour-alpha";}' - ], - [ '80x60-RGB.xcf', - 'a:1:{s:9:"colorType";s:16:"truecolour-alpha";}' - ], - [ '80x60-Greyscale.xcf', - 'a:1:{s:9:"colorType";s:15:"greyscale-alpha";}' - ], - ]; - } -}