generated from jric11/baseProject
184 lines
5.9 KiB
PHP
184 lines
5.9 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
/**
|
||
|
|
* ImageCacheTest.php
|
||
|
|
*
|
||
|
|
* @since 2026-06-16
|
||
|
|
* @category Library
|
||
|
|
* @package PdfImage
|
||
|
|
* @author Nicola Asuni <info@tecnick.com>
|
||
|
|
* @copyright 2011-2026 Nicola Asuni - Tecnick.com LTD
|
||
|
|
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||
|
|
* @link https://github.com/tecnickcom/tc-lib-pdf-image
|
||
|
|
*
|
||
|
|
* This file is part of tc-lib-pdf-image software library.
|
||
|
|
*/
|
||
|
|
|
||
|
|
namespace Test;
|
||
|
|
|
||
|
|
use Com\Tecnick\Pdf\Image\ImageCacheInterface;
|
||
|
|
use Com\Tecnick\Pdf\Image\Import;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* External image cache test.
|
||
|
|
*
|
||
|
|
* @since 2026-06-16
|
||
|
|
* @category Library
|
||
|
|
* @package PdfImage
|
||
|
|
* @author Nicola Asuni <info@tecnick.com>
|
||
|
|
* @copyright 2011-2026 Nicola Asuni - Tecnick.com LTD
|
||
|
|
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||
|
|
* @link https://github.com/tecnickcom/tc-lib-pdf-image
|
||
|
|
*/
|
||
|
|
class ImageCacheTest extends TestUtil
|
||
|
|
{
|
||
|
|
private function getImport(?ImageCacheInterface $cache): Import
|
||
|
|
{
|
||
|
|
return new Import(0.75, $this->getTestEncrypt(), $this->getTestFileHelper(), imageCache: $cache);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @throws \Com\Tecnick\Pdf\Image\Exception
|
||
|
|
* @throws \Com\Tecnick\File\Exception
|
||
|
|
* @throws \Com\Tecnick\Pdf\Encrypt\Exception
|
||
|
|
*/
|
||
|
|
public function testWriteThroughAndReadThrough(): void
|
||
|
|
{
|
||
|
|
$src = __DIR__ . '/images/200x100_RGB.png';
|
||
|
|
|
||
|
|
$spy = new SpyImageCache();
|
||
|
|
$img1 = $this->getImport($spy);
|
||
|
|
$img1->add($src);
|
||
|
|
|
||
|
|
// one external lookup (miss) + one write-through
|
||
|
|
$this->assertSame(1, $spy->getCount);
|
||
|
|
$this->assertCount(1, $spy->setKeys);
|
||
|
|
|
||
|
|
// doctor the stored entry with a sentinel: a hit must be returned verbatim
|
||
|
|
$key = $spy->setKeys[0] ?? '';
|
||
|
|
$this->assertArrayHasKey($key, $spy->store);
|
||
|
|
if (isset($spy->store[$key])) {
|
||
|
|
$spy->store[$key]['width'] = 4321;
|
||
|
|
}
|
||
|
|
|
||
|
|
// a fresh Import (empty in-process cache) reusing the same backend
|
||
|
|
$img2 = $this->getImport($spy);
|
||
|
|
$img2->add($src);
|
||
|
|
$data = $img2->getImageDataByKey($img2->getKey($src));
|
||
|
|
|
||
|
|
// proves the external entry was used as-is (no recomputation)
|
||
|
|
$this->assertSame(4321, $data['width']);
|
||
|
|
// no additional write-through happened on a hit
|
||
|
|
$this->assertCount(1, $spy->setKeys);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @throws \Com\Tecnick\Pdf\Image\Exception
|
||
|
|
* @throws \Com\Tecnick\File\Exception
|
||
|
|
* @throws \Com\Tecnick\Pdf\Encrypt\Exception
|
||
|
|
*/
|
||
|
|
public function testDisabledByDefault(): void
|
||
|
|
{
|
||
|
|
$src = __DIR__ . '/images/200x100_RGB.png';
|
||
|
|
|
||
|
|
$img = $this->getImport(null);
|
||
|
|
$img->add($src);
|
||
|
|
$data = $img->getImageDataByKey($img->getKey($src));
|
||
|
|
|
||
|
|
// with no external cache, the in-process data keeps the original bytes
|
||
|
|
$this->assertNotEmpty($data['data']);
|
||
|
|
$this->assertNotEmpty($data['raw']);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @throws \Com\Tecnick\Pdf\Image\Exception
|
||
|
|
* @throws \Com\Tecnick\File\Exception
|
||
|
|
* @throws \Com\Tecnick\Pdf\Encrypt\Exception
|
||
|
|
*/
|
||
|
|
public function testPersistedSnapshotIsClean(): void
|
||
|
|
{
|
||
|
|
$spy = new SpyImageCache();
|
||
|
|
$img = $this->getImport($spy);
|
||
|
|
$img->add(__DIR__ . '/images/200x100_RGBALPHA.png');
|
||
|
|
|
||
|
|
$stored = $spy->fetch($spy->setKeys[0] ?? '');
|
||
|
|
|
||
|
|
// original bytes dropped to shrink the payload
|
||
|
|
$this->assertSame('', $stored['raw']);
|
||
|
|
// no PDF object numbers / output flag are persisted
|
||
|
|
$this->assertSame(0, $stored['obj']);
|
||
|
|
$this->assertSame(0, $stored['obj_alt']);
|
||
|
|
$this->assertSame(0, $stored['obj_icc']);
|
||
|
|
$this->assertSame(0, $stored['obj_pal']);
|
||
|
|
$this->assertArrayNotHasKey('out', $stored);
|
||
|
|
|
||
|
|
// alpha image splits into plain + mask: their raw bytes are dropped too
|
||
|
|
$this->assertArrayHasKey('mask', $stored);
|
||
|
|
if (isset($stored['mask'])) {
|
||
|
|
$this->assertSame('', $stored['mask']['raw']);
|
||
|
|
}
|
||
|
|
if (isset($stored['plain'])) {
|
||
|
|
$this->assertSame('', $stored['plain']['raw']);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @throws \Com\Tecnick\Pdf\Image\Exception
|
||
|
|
* @throws \Com\Tecnick\File\Exception
|
||
|
|
* @throws \Com\Tecnick\Pdf\Encrypt\Exception
|
||
|
|
*/
|
||
|
|
public function testStaleFileProducesDifferentKey(): void
|
||
|
|
{
|
||
|
|
$tmp = $this->makeTempFile('.png');
|
||
|
|
\copy(__DIR__ . '/images/200x100_RGB.png', $tmp);
|
||
|
|
\clearstatcache(true, $tmp);
|
||
|
|
|
||
|
|
$spy = new SpyImageCache();
|
||
|
|
$this->getImport($spy)->add($tmp);
|
||
|
|
$this->assertCount(1, $spy->setKeys);
|
||
|
|
$firstKey = $spy->setKeys[0] ?? '';
|
||
|
|
|
||
|
|
// edit the file in place: different content/size and a newer mtime
|
||
|
|
\copy(__DIR__ . '/images/200x100_GRAY.png', $tmp);
|
||
|
|
\touch($tmp, \time() + 5);
|
||
|
|
\clearstatcache(true, $tmp);
|
||
|
|
|
||
|
|
$this->getImport($spy)->add($tmp);
|
||
|
|
$this->assertCount(2, $spy->setKeys);
|
||
|
|
|
||
|
|
// mtime+size folded into the persistent key invalidates the stale entry
|
||
|
|
$this->assertNotSame($firstKey, $spy->setKeys[1] ?? '');
|
||
|
|
|
||
|
|
\unlink($tmp);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @throws \Com\Tecnick\Pdf\Image\Exception
|
||
|
|
* @throws \Com\Tecnick\File\Exception
|
||
|
|
* @throws \Com\Tecnick\Pdf\Encrypt\Exception
|
||
|
|
*/
|
||
|
|
public function testOutputIdenticalWithAndWithoutCache(): void
|
||
|
|
{
|
||
|
|
$src = __DIR__ . '/images/200x100_RGB.png';
|
||
|
|
|
||
|
|
$ref = $this->getImport(null);
|
||
|
|
$ref->add($src);
|
||
|
|
$refOut = $ref->getOutImagesBlock(10);
|
||
|
|
|
||
|
|
$spy = new SpyImageCache();
|
||
|
|
// warm the cache, then import again from a fresh instance (external hit)
|
||
|
|
$this->getImport($spy)->add($src);
|
||
|
|
$cached = $this->getImport($spy);
|
||
|
|
$cached->add($src);
|
||
|
|
$cachedOut = $cached->getOutImagesBlock(10);
|
||
|
|
|
||
|
|
// stripping raw never affects the emitted PDF objects
|
||
|
|
$this->assertSame($refOut, $cachedOut);
|
||
|
|
}
|
||
|
|
|
||
|
|
private function makeTempFile(string $ext): string
|
||
|
|
{
|
||
|
|
return \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'tclpi_' . \uniqid('', true) . $ext;
|
||
|
|
}
|
||
|
|
}
|