first commit

This commit is contained in:
2024-11-10 21:08:49 +01:00
commit 0d932ce5ee
14455 changed files with 2567501 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
<?php
namespace WebPConvert\Tests\Serve;
use WebPConvert\Serve\Header;
use WebPConvert\Serve\MockedHeader;
use WebPConvert\Loggers\BufferLogger;
use PHPUnit\Framework\TestCase;
class HeaderTest extends TestCase
{
public function testAddHeader()
{
MockedHeader::reset();
Header::addHeader('X-test: testing');
$header0 = MockedHeader::getHeaders()[0];
$this->assertEquals('X-test: testing', $header0[0]);
$this->assertFalse($header0[1]);
Header::addHeader('X-test: testing2');
$header1 = MockedHeader::getHeaders()[1];
$this->assertEquals('X-test: testing2', $header1[0]);
$this->assertFalse($header1[1]);
}
public function testSetHeader()
{
MockedHeader::reset();
Header::setHeader('X-test: testing set header');
$header0 = MockedHeader::getHeaders()[0];
$this->assertEquals('X-test: testing set header', $header0[0]);
$this->assertTrue($header0[1]);
}
public function testAddLogHeader()
{
MockedHeader::reset();
Header::addLogHeader('test', new BufferLogger());
$header0 = MockedHeader::getHeaders()[0];
$this->assertEquals('X-WebP-Convert-Log: test', $header0[0]);
$this->assertFalse($header0[1]);
}
}
require_once('mock-header.inc');

View File

@@ -0,0 +1,25 @@
<?php
namespace WebPConvert\Tests\Convert\Exposers;
use WebPConvert\Serve\ServeConvertedWebP;
use WebPConvert\Tests\BaseExposer;
/**
* Class for exposing otherwise unaccessible methods of AbstractConverter,
* - so they can be tested
*
* TODO: expose and test more methods! (and make more methods private/protected in AbstractConverter)
*/
class ServeConvertedWebPExposer extends BaseExposer {
public function __construct($instance)
{
parent::__construct($instance);
}
/*
public function serveDestination($destination, $options)
{
return $this->callPrivateFunction('serveDestination', null, $destination, $options);
}*/
}

View File

@@ -0,0 +1,464 @@
<?php
namespace WebPConvert\Tests\Serve;
use ImageMimeTypeGuesser\ImageMimeTypeGuesser;
use WebPConvert\Exceptions\InvalidInputException;
use WebPConvert\Exceptions\InvalidInput\InvalidImageTypeException;
use WebPConvert\Exceptions\InvalidInput\TargetNotFoundException;
use WebPConvert\Serve\ServeConvertedWebP;
use WebPConvert\Serve\MockedHeader;
use WebPConvert\Serve\Exceptions\ServeFailedException;
use WebPConvert\Tests\CompatibleTestCase;
use ServeConvertedWebPExposer;
use PHPUnit\Framework\TestCase;
/**
* @coversDefaultClass WebPConvert\Serve\ServeConvertedWebP
* @covers WebPConvert\Serve\ServeConvertedWebP
*/
class ServeConvertedWebPTest extends CompatibleTestCase
{
public function getImageFolder()
{
return realpath(__DIR__ . '/../images');
}
public function getImagePath($image)
{
return $this->getImageFolder() . '/' . $image;
}
/**
* Call to serve and return result or exception
*
* The method takes care of closing output buffer in case of exception
*
* @return array First item: the output, second item: Exception, if thrown
*/
public static function callServe($filename, $destination, $options)
{
ob_start();
try {
ServeConvertedWebP::serve($filename, $destination, $options);
} catch (\Exception $e) {
return [ob_get_clean(), $e];
} catch (\Throwable $e) {
return [ob_get_clean(), $e];
}
return [ob_get_clean(), null];
}
/**
* Call to serve and return result or exception
*
* The method takes care of closing output buffer in case of exception
*
* @return string the output
*/
public static function callServeWithThrow($filename, $destination, $options)
{
ob_start();
try {
ServeConvertedWebP::serve($filename, $destination, $options);
} catch (\Exception $e) {
ob_get_clean();
throw($e);
} catch (\Throwable $e) {
ob_get_clean();
throw($e);
}
return ob_get_clean();
}
/**
* Call to serve and return result or exception
*
* The method takes care of closing output buffer in case of exception
*
* @return string the output
*/
public static function callServeOriginalWithThrow($filename, $options)
{
ob_start();
try {
ServeConvertedWebP::serveOriginal($filename, $options);
} catch (\Exception $e) {
ob_get_clean();
throw($e);
} catch (\Throwable $e) {
ob_get_clean();
throw($e);
}
return ob_get_clean();
}
/**
* @covers ::serveOriginal
*/
public function testServeOriginal()
{
$source = $this->getImagePath('test.png');
$this->assertTrue(file_exists($source), 'source file does not exist:' . $source);
$destination = $source . '.webp';
$options = [
//'serve-original' => true,
//'reconvert' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeOriginalWithThrow($source, $options);
// Test that headers were set as expected
//$this->assertTrue(MockedHeader::hasHeaderContaining('X-WebP-Convert-Action:'));
$this->assertTrue(MockedHeader::hasHeader('Content-Type: image/png'));
$this->assertFalse(MockedHeader::hasHeader('Vary: Accept'));
$this->assertTrue(MockedHeader::hasHeaderContaining('Last-Modified:'));
$this->assertFalse(MockedHeader::hasHeaderContaining('Cache-Control:'));
}
/**
* @covers ::serveOriginal
*/
public function testServeOriginalNotAnImage()
{
//$this->expectException(InvalidImageTypeException::class);
$this->expectException(ServeFailedException::class);
$source =$this->getImagePath('text.txt');
$this->assertTrue(file_exists($source), 'source file does not exist');
$contentType = ImageMimeTypeGuesser::lenientGuess($source);
$this->assertSame(false, $contentType);
$options = [
//'serve-original' => true,
//'reconvert' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeOriginalWithThrow($source, []);
$this->assertEquals('', $result);
}
/**
* @covers ::serveOriginal
*/
public function testServeOriginalNotAnImage2()
{
//$this->expectException(InvalidImageTypeException::class);
$this->expectException(ServeFailedException::class);
$source = $this->getImagePath('text');
$this->assertTrue(file_exists($source), 'source file does not exist');
$contentType = ImageMimeTypeGuesser::lenientGuess($source);
$this->assertSame(null, $contentType);
$options = [
//'serve-original' => true,
//'reconvert' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeOriginalWithThrow($source, $options);
$this->assertEquals('', $result);
}
/**
* @covers ::serve
*/
public function testServeReconvert()
{
$source = $this->getImagePath('test.png');
$this->assertTrue(file_exists($source));
$destination = $source . '.webp';
$options = [
//'serve-original' => true,
'reconvert' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeWithThrow($source, $destination, $options);
// Test that headers were set as expected
//$this->assertTrue(MockedHeader::hasHeaderContaining('X-WebP-Convert-Action:'));
$this->assertTrue(MockedHeader::hasHeader('Content-Type: image/webp'));
$this->assertFalse(MockedHeader::hasHeader('Vary: Accept'));
$this->assertTrue(MockedHeader::hasHeaderContaining('Last-Modified:'));
$this->assertFalse(MockedHeader::hasHeaderContaining('Cache-Control:'));
}
/**
* @covers ::serve
*/
public function testServeServeOriginal()
{
$source = $this->getImagePath('test.png');
$this->assertTrue(file_exists($source));
$destination = $source . '.webp';
$options = [
'serve-original' => true,
//'reconvert' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeWithThrow($source, $destination, $options);
// Test that headers were set as expected
//$this->assertTrue(MockedHeader::hasHeaderContaining('X-WebP-Convert-Action:'));
$this->assertTrue(MockedHeader::hasHeader('Content-Type: image/png'));
$this->assertFalse(MockedHeader::hasHeader('Vary: Accept'));
$this->assertTrue(MockedHeader::hasHeaderContaining('Last-Modified:'));
$this->assertFalse(MockedHeader::hasHeaderContaining('Cache-Control:'));
}
/**
* Testing when the "cached" image can be served
* @covers ::serve
*/
public function testServeDestination()
{
$source = $this->getImagePath('/test.png');
$this->assertTrue(file_exists($source));
// create fake webp at destination
$destination = $source . '.webp';
file_put_contents($destination, '1234');
$this->assertTrue(file_exists($destination));
$options = [
//'serve-original' => true,
//'reconvert' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeWithThrow($source, $destination, $options);
// Check that destination is output (it has the content "1234")
$this->assertEquals('1234', $result);
// Test that headers were set as expected
//$this->assertTrue(MockedHeader::hasHeaderContaining('X-WebP-Convert-Action:'));
$this->assertTrue(MockedHeader::hasHeader('Content-Type: image/webp'));
}
/**
* @covers ::serve
*/
public function testEmptySourceArg()
{
$this->expectException(InvalidInputException::class);
$options = [
//'serve-original' => true,
//'reconvert' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$source = '';
$this->assertEmpty($source);
$result = self::callServeWithThrow($source, $this->getImagePath('test.png.webp'), $options);
}
/**
* @covers ::serve
*/
public function testEmptyDestinationArg()
{
$this->expectException(InvalidInputException::class);
$source = $this->getImagePath('test.png');
$this->assertTrue(file_exists($source));
$destination = '';
$options = [
//'serve-original' => true,
//'reconvert' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeWithThrow($source, $destination, $options);
}
/**
* @covers ::serve
*/
public function testNoFileAtSource()
{
$this->expectException(TargetNotFoundException::class);
$source = $this->getImagePath('i-do-not-exist.png');
$this->assertFalse(file_exists($source));
$destination = '';
$options = [
//'serve-original' => true,
//'reconvert' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeWithThrow($source, $destination, $options);
}
/**
* @covers ::serve
*/
public function testServeReport()
{
$source = $this->getImagePath('test.png');
$this->assertTrue(file_exists($source));
$destination = $source . '.webp';
$options = [
//'serve-original' => true,
//'reconvert' => true,
'show-report' => true,
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeWithThrow($source, $destination, $options);
// Check that output looks like a report
$this->assertTrue(strpos($result, 'source:') !== false, 'The following does not contain "source:":' . $result);
// Test that headers were set as expected
//$this->assertTrue(MockedHeader::hasHeaderContaining('X-WebP-Convert-Action:'));
$this->assertTrue(MockedHeader::hasHeader('Content-Type: image/webp'));
}
public function testSourceIsLighter()
{
$source = $this->getImagePath('plaintext-with-jpg-extension.jpg');
// create fake webp at destination, which is larger than the fake jpg
file_put_contents($source . '.webp', 'aotehu aotnehuatnoehutaoehu atonse uaoehu');
$this->assertTrue(file_exists($source));
$this->assertTrue(file_exists($source . '.webp'));
$options = [
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeWithThrow($source, $source . '.webp', $options);
// the source file contains "text", so the next assert asserts that source was served
$this->assertMatchesRegularExpression2('#text#', $result);
}
public function testExistingOutDated()
{
$source = $this->getImagePath('test.jpg');
$this->assertTrue(file_exists($source));
$destination = $source . '.webp';
@unlink($destination);
copy($this->getImagePath('pre-converted/test.webp'), $destination);
// set modification date earlier than source
touch($destination, filemtime($source) - 1000);
// check that it worked
$this->assertLessThan(filemtime($source), filemtime($destination));
$options = [
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeWithThrow($source, $source . '.webp', $options);
unlink($destination);
// Our success-converter always creates fake webps with the content:
// "we-pretend-this-is-a-valid-webp!".
// So testing that we got this back is the same as testing that a "conversion" was
// done and the converted file was served. It is btw smaller than the source.
$this->assertMatchesRegularExpression2('#we-pretend-this-is-a-valid-webp!#', $result);
}
public function testNoFileAtDestination()
{
$source = $this->getImagePath('test.jpg');
$this->assertTrue(file_exists($source));
$destination = $source . '.webp';
@unlink($destination);
$options = [
'convert' => [
'converters' => [
'\\WebPConvert\\Tests\\Convert\\TestConverters\\SuccessGuaranteedConverter'
]
]
];
$result = self::callServeWithThrow($source, $source . '.webp', $options);
// Our success-converter always creates fake webps with the content:
// "we-pretend-this-is-a-valid-webp!".
// So testing that we got this back is the same as testing that a "convert" was
// done and the converted file was served. It is btw smaller than the source.
$this->assertMatchesRegularExpression2('#we-pretend-this-is-a-valid-webp!#', $result);
}
}
require_once('mock-header.inc');

View File

@@ -0,0 +1,236 @@
<?php
namespace WebPConvert\Tests\Serve;
use WebPConvert\Serve\ServeFile;
use WebPConvert\Serve\MockedHeader;
use WebPConvert\Exceptions\InvalidInpuException;
use WebPConvert\Exceptions\InvalidInput\InvalidImageTypeException;
use WebPConvert\Exceptions\InvalidInput\TargetNotFoundException;
//use WebPConvert\Serve\Exceptions\ServeFailedException;
use PHPUnit\Framework\TestCase;
class ServeFileTest extends TestCase
{
public function getImageFolder()
{
return realpath(__DIR__ . '/../images');
}
public function getImagePath($image)
{
return $this->getImageFolder() . '/' . $image;
}
/**
* Call to serve and return result or exception
*
* The method takes care of closing output buffer in case of exception
*
* @return array First item: the output, second item: Exception, if thrown
*/
public static function callServe($filename, $mime, $options)
{
ob_start();
try {
ServeFile::serve($filename, $mime, $options);
} catch (\Exception $e) {
return [ob_get_clean(), $e];
} catch (\Throwable $e) {
return [ob_get_clean(), $e];
}
return [ob_get_clean(), null];
}
/**
* Call to serve and return result or exception
*
* The method takes care of closing output buffer in case of exception
*
* @return string the output
*/
public static function callServeWithThrow($filename, $mime, $options)
{
ob_start();
try {
ServeFile::serve($filename, $mime, $options);
} catch (\Exception $e) {
ob_get_clean();
throw($e);
} catch (\Throwable $e) {
ob_get_clean();
throw($e);
}
return ob_get_clean();
}
public function testServeDefaultOptions()
{
MockedHeader::reset();
$filename = self::getImagePath('plaintext-with-jpg-extension.jpg');
$this->assertTrue(file_exists($filename));
$result = self::callServeWithThrow($filename, 'image/webp', []);
// Test that content of file was send to output
$isWindows = preg_match('/^win/i', PHP_OS);
if ($isWindows) {
$this->assertEquals("text\r\n", $result);
} else {
$this->assertEquals("text\n", $result);
}
$headers = MockedHeader::getHeaders();
$this->assertGreaterThanOrEqual(1, MockedHeader::getNumHeaders());
// Test that headers were set as expected
$this->assertTrue(MockedHeader::hasHeader('Content-Type: image/webp'));
$this->assertFalse(MockedHeader::hasHeader('Vary: Accept'));
$this->assertTrue(MockedHeader::hasHeaderContaining('Content-Length:'));
//$this->assertTrue(MockedHeader::hasHeader('Last-Modified: Mon, 29 Apr 2019 12:54:37 GMT'));
// TODO:The following fails on travis. WHY???
//$this->assertTrue(MockedHeader::hasHeaderContaining('Last-Modified:'));
//$this->assertTrue(MockedHeader::hasHeader('Cache-Control: public, max-age=86400'));
//$this->assertTrue(MockedHeader::hasHeaderContaining('Expires:'));
}
public function testServeVaryHeader()
{
MockedHeader::reset();
$this->assertEquals(0, MockedHeader::getNumHeaders());
$filename = self::getImagePath('plaintext-with-jpg-extension.jpg');
$this->assertTrue(file_exists($filename));
$options = [
'headers' => [
'vary-accept' => true
]
];
$result = self::callServeWithThrow($filename, 'image/webp', $options);
$this->assertTrue(MockedHeader::hasHeader('Vary: Accept'));
}
public function testServeNoHeaders()
{
MockedHeader::reset();
$this->assertEquals(0, MockedHeader::getNumHeaders());
$filename = self::getImagePath('plaintext-with-jpg-extension.jpg');
$this->assertTrue(file_exists($filename));
$options = [
'headers' => [
'cache-control' => false,
'content-length' => false,
'content-type' => false,
'expires' => false,
'last-modified' => false,
'vary-accept' => false
],
'cache-control-header' => 'private, max-age=100',
];
$result = self::callServeWithThrow($filename, 'image/webp', $options);
// Test that content of file was send to output
$isWindows = preg_match('/^win/i', PHP_OS);
if ($isWindows) {
$this->assertEquals("text\r\n", $result);
} else {
$this->assertEquals("text\n", $result);
}
// Test that headers were set as expected
// We actually expect that none are added.
$headers = MockedHeader::getHeaders();
$this->assertEquals(0, MockedHeader::getNumHeaders());
// TODO:The following fails on travis. WHY???
//$this->assertFalse(MockedHeader::hasHeader('Content-Type: image/webp'));
//$this->assertTrue(MockedHeader::hasHeader('Vary: Accept'));
//$this->assertFalse(MockedHeader::hasHeader('Last-Modified: Mon, 29 Apr 2019 12:54:37 GMT'));
// TODO:The following fails on travis. WHY???
//$this->assertTrue(MockedHeader::hasHeaderContaining('Last-Modified:'));
$this->assertFalse(MockedHeader::hasHeader('Cache-Control: public, max-age=86400'));
$this->assertFalse(MockedHeader::hasHeaderContaining('Expires:'));
}
public function testServeCustomCacheControl()
{
MockedHeader::reset();
$filename = self::getImagePath('plaintext-with-jpg-extension.jpg');
$this->assertTrue(file_exists($filename));
$options = [
'headers' => [
'cache-control' => true,
'expires' => true,
],
'cache-control-header' => 'private, max-age=100',
];
$result = self::callServeWithThrow($filename, 'image/webp', $options);
$this->assertTrue(MockedHeader::hasHeader('Cache-Control: private, max-age=100'));
$this->assertTrue(MockedHeader::hasHeaderContaining('Expires:'));
}
public function testServeCustomCacheControlNoMaxAge()
{
MockedHeader::reset();
$filename = self::getImagePath('plaintext-with-jpg-extension.jpg');
$this->assertTrue(file_exists($filename));
$options = [
'headers' => [
'cache-control' => true,
],
'cache-control-header' => 'private',
];
$result = self::callServeWithThrow($filename, 'image/webp', $options);
$this->assertTrue(MockedHeader::hasHeader('Cache-Control: private'));
// When there is no max-age, there should neither be any Expires
$this->assertFalse(MockedHeader::hasHeaderContaining('Expires:'));
}
public function testServeNonexistantFile()
{
//MockedHeader::reset();
$filename = __DIR__ . '/i-dont-exist-no';
$this->assertFalse(file_exists($filename));
//$this->expectException(TargetNotFoundException::class);
list($result, $e) = self::callServe($filename, 'image/webp', []);
$this->assertSame(
'WebPConvert\Exceptions\InvalidInput\TargetNotFoundException',
get_class($e)
);
$this->assertSame('', $result);
//$this->assertTrue(MockedHeader::hasHeader('X-WebP-Convert-Error: Could not read file'));
}
}
require_once('mock-header.inc');

View File

@@ -0,0 +1,52 @@
<?php
namespace WebPConvert\Serve {
class MockedHeader {
private static $headers = [];
public static function header($header, $replace) {
self::$headers[] = [$header, $replace];
//echo $header;
}
public static function getHeaders() {
return self::$headers;
}
public static function reset() {
self::$headers = [];
}
public static function hasHeader($header)
{
$headerValues = array_column(self::$headers, 0);
return in_array($header, $headerValues);
}
public static function hasHeaderContaining($headerText)
{
$headerValues = array_column(self::$headers, 0);
foreach ($headerValues as $header) {
if (false !== strpos($header, $headerText)) {
return true;
}
}
return false;
}
public static function getNumHeaders() {
return count(self::$headers);
}
}
//use WebPConvert\Tests\Serve\MockedHeader;
function header($h, $replace)
{
MockedHeader::header($h, $replace);
}
}