silverstripe-framework/tests/filesystem/GDTest.php
Damian Mooyman d52db0ba34 Merge 3 into master
# Conflicts:
#	.travis.yml
#	admin/css/ie7.css
#	admin/css/ie7.css.map
#	admin/css/ie8.css.map
#	admin/css/screen.css
#	admin/css/screen.css.map
#	admin/javascript/LeftAndMain.js
#	admin/scss/_style.scss
#	admin/scss/_uitheme.scss
#	control/HTTPRequest.php
#	core/Object.php
#	css/AssetUploadField.css
#	css/AssetUploadField.css.map
#	css/ConfirmedPasswordField.css.map
#	css/Form.css.map
#	css/GridField.css.map
#	css/TreeDropdownField.css.map
#	css/UploadField.css
#	css/UploadField.css.map
#	css/debug.css.map
#	dev/Debug.php
#	docs/en/00_Getting_Started/00_Server_Requirements.md
#	docs/en/02_Developer_Guides/06_Testing/00_Unit_Testing.md
#	docs/en/02_Developer_Guides/06_Testing/index.md
#	docs/en/02_Developer_Guides/14_Files/02_Images.md
#	docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md
#	filesystem/File.php
#	filesystem/Folder.php
#	filesystem/GD.php
#	filesystem/Upload.php
#	forms/ToggleField.php
#	forms/Validator.php
#	javascript/lang/en_GB.js
#	javascript/lang/fr.js
#	javascript/lang/src/en.js
#	javascript/lang/src/fr.js
#	model/Image.php
#	model/UnsavedRelationList.php
#	model/Versioned.php
#	model/connect/MySQLDatabase.php
#	model/fieldtypes/DBField.php
#	model/fieldtypes/Enum.php
#	scss/AssetUploadField.scss
#	scss/UploadField.scss
#	templates/email/ChangePasswordEmail.ss
#	templates/forms/DropdownField.ss
#	tests/behat/features/bootstrap/SilverStripe/Framework/Test/Behaviour/CmsFormsContext.php
#	tests/behat/features/bootstrap/SilverStripe/Framework/Test/Behaviour/CmsUiContext.php
#	tests/forms/EnumFieldTest.php
#	tests/security/MemberTest.php
#	tests/security/MemberTest.yml
#	tests/security/SecurityTest.php
2016-04-29 17:50:55 +12:00

211 lines
6.0 KiB
PHP

<?php
/**
* Tests for the {@link GD} class.
*
* @package framework
* @subpackage tests
*/
class GDTest extends SapphireTest {
public static $filenames = array(
'gif' => 'test_gif.gif',
'jpg' => 'test_jpg.jpg',
'png8' => 'test_png8.png',
'png32' => 'test_png32.png'
);
public function setUp() {
parent::setUp();
GDBackend::flush();
}
public function tearDown() {
GDBackend::flush();
parent::tearDown();
}
/**
* Loads all images into an associative array of GD objects.
* Optionally applies an operation to each GD
* @param callable $callback Action to perform on each GD
* @return array List of GD
*/
protected function applyToEachImage($callback = null) {
$gds = array();
foreach(self::$filenames as $type => $file) {
$fullPath = realpath(dirname(__FILE__) . '/gdtest/' . $file);
$gd = new GDBackend();
$gd->loadFrom($fullPath);
if($callback) {
$gd = $callback($gd);
}
$gds[$type] = $gd;
}
return $gds;
}
/**
* Takes samples from the given GD at 5 pixel increments
* @param GDBackend $gd The source image
* @param integer $horizontal Number of samples to take horizontally
* @param integer $vertical Number of samples to take vertically
* @return array List of colours for each sample, each given as an associative
* array with red, blue, green, and alpha components
*/
protected function sampleAreas(GDBackend $gd, $horizontal = 4, $vertical = 4) {
$samples = array();
for($y = 0; $y < $vertical; $y++) {
for($x = 0; $x < $horizontal; $x++) {
$colour = imagecolorat($gd->getImageResource(), $x * 5, $y * 5);
$samples[] = ImageColorsforIndex($gd->getImageResource(), $colour);
}
}
return $samples;
}
/**
* Asserts that two colour channels are equivalent within a given tolerance range
* @param integer $expected
* @param integer $actual
* @param integer $tolerance
*/
protected function assertColourEquals($expected, $actual, $tolerance = 0) {
$match =
($expected + $tolerance >= $actual) &&
($expected - $tolerance <= $actual);
$this->assertTrue($match);
}
/**
* Asserts that all samples given correctly correspond to a greyscale version
* of the test image pattern
* @param array $samples List of 16 colour samples representing each of the
* 8 x 8 squares on the image pattern
* @param int $alphaBits Depth of alpha channel in bits
* @param int $tolerance Reasonable tolerance level for colour comparison
*/
protected function assertGreyscale($samples, $alphaBits = 0, $tolerance = 0) {
// Check that all colour samples match
foreach($samples as $sample) {
$matches =
($sample['red'] === $sample['green']) &&
($sample['blue'] === $sample['green']);
$this->assertTrue($matches, 'Assert colour is greyscale');
if(!$matches) return;
}
// check various sample points
$this->assertColourEquals(76, $samples[0]['red'], $tolerance);
$this->assertColourEquals(149, $samples[2]['red'], $tolerance);
$this->assertColourEquals(0, $samples[8]['red'], $tolerance);
$this->assertColourEquals(127, $samples[9]['red'], $tolerance);
// check alpha of various points
switch($alphaBits) {
case 0:
$this->assertColourEquals(0, $samples[2]['alpha'], $tolerance);
$this->assertColourEquals(0, $samples[12]['alpha'], $tolerance);
break;
case 1:
$this->assertColourEquals(0, $samples[2]['alpha'], $tolerance);
$this->assertColourEquals(127, $samples[12]['alpha'], $tolerance);
break;
default:
$this->assertColourEquals(63, $samples[2]['alpha'], $tolerance);
$this->assertColourEquals(127, $samples[12]['alpha'], $tolerance);
break;
}
}
/**
* Tests that images are correctly transformed to greyscale
*/
function testGreyscale() {
// Apply greyscaling to each image
$images = $this->applyToEachImage(function(GDBackend $gd) {
return $gd->greyscale();
});
// Test GIF (256 colour, transparency)
$samplesGIF = $this->sampleAreas($images['gif']);
$this->assertGreyscale($samplesGIF, 1);
// Test JPG
$samplesJPG = $this->sampleAreas($images['jpg']);
$this->assertGreyscale($samplesJPG, 0, 4);
// Test PNG 8 (indexed with alpha transparency)
$samplesPNG8 = $this->sampleAreas($images['png8']);
$this->assertGreyscale($samplesPNG8, 8, 4);
// Test PNG 32 (full alpha transparency)
$samplesPNG32 = $this->sampleAreas($images['png32']);
$this->assertGreyscale($samplesPNG32, 8);
}
/**
* Tests that GD doesn't attempt to load images when they're deemed unavailable
* @return void
*/
public function testImageSkippedWhenUnavailable() {
$fullPath = realpath(dirname(__FILE__) . '/gdtest/test_jpg.jpg');
$gd = new GDBackend_ImageUnavailable();
$gd->loadFrom($fullPath);
/* Ensure no image resource is created if the image is unavailable */
$this->assertNull($gd->getImageResource());
}
/**
* Tests the integrity of the manipulation cache when an error occurs
*/
public function testCacheIntegrity() {
$fullPath = realpath(dirname(__FILE__) . '/gdtest/nonimagedata.jpg');
// Load invalid file
$gd = new GDBackend();
$gd->loadFrom($fullPath);
// Cache should refer to this file
$cache = SS_Cache::factory('GDBackend_Manipulations');
$key = sha1(implode('|', array($fullPath, filemtime($fullPath))));
$data = $cache->load($key);
$this->assertEquals('1', $data);
}
/**
* Test that GD::failedResample() returns true for the current image
* manipulation only if it previously failed
* @return void
*/
public function testFailedResample() {
$fullPath = realpath(dirname(__FILE__) . '/gdtest/nonimagedata.jpg');
$fullPath2 = realpath(dirname(__FILE__) . '/gdtest/test_gif.gif');
// Load invalid file
$gd = new GDBackend();
$gd->loadFrom($fullPath);
// Cache should refre to this file
$this->assertTrue($gd->failedResample($fullPath, filemtime($fullPath)));
$this->assertFalse($gd->failedResample($fullPath2, filemtime($fullPath2)));
}
}
class GDBackend_ImageUnavailable extends GDBackend implements TestOnly {
public function failedResample() {
return true;
}
}
class GDBackend_Failure_Exception extends Exception {
}