foundation/tests/Unit/Core/Cache/ArrayCacheTest.php
2025-06-13 18:29:55 +02:00

204 lines
No EOL
6.1 KiB
PHP

<?php
declare(strict_types = 1);
namespace Foundation\Tests\Unit\Core\Cache;
use DateInterval;
use Foundation\Core\Cache\ArrayCache;
use PHPUnit\Framework\TestCase;
use Psr\SimpleCache\InvalidArgumentException;
use stdClass;
class ArrayCacheTest extends TestCase
{
private ArrayCache $cache;
protected function setUp(): void {
$this->cache = new ArrayCache();
}
public function testCanSetAndGetValue(): void {
$setResult = $this->cache->set('key1', 'value1');
self::assertSame('value1', $this->cache->get('key1'));
self::assertTrue($setResult);
}
public function testReturnsDefaultWhenKeyNotExists(): void {
self::assertNull($this->cache->get('nonexistent'));
self::assertSame('default', $this->cache->get('nonexistent', 'default'));
}
public function testReturnsExistsStateForCacheKeys(): void {
$this->cache->set('key1', 'value1');
self::assertTrue($this->cache->has('key1'));
self::assertFalse($this->cache->has('nonexistent'));
}
public function testCanDeleteAKey(): void {
$this->cache->set('key1', 'value1');
self::assertTrue($this->cache->has('key1'));
$deleteResult = $this->cache->delete('key1');
self::assertFalse($this->cache->has('key1'));
self::assertTrue($deleteResult);
}
public function testReturnsTrueForDeletionEvenForNonExistentKey(): void {
$result = $this->cache->delete('nonexistent');
self::assertTrue($result);
}
public function testCanClearAllKeys(): void {
$this->cache->set('key1', 'value1');
$this->cache->set('key2', 'value2');
$this->cache->clear();
self::assertFalse($this->cache->has('key1'));
self::assertFalse($this->cache->has('key2'));
}
public function testConsidersTtlForCacheItemsWithIntegers(): void {
$this->cache->set('key1', 'value1', 1);
self::assertTrue($this->cache->has('key1'));
self::assertSame('value1', $this->cache->get('key1'));
// Sleep to let TTL expire
sleep(2);
self::assertFalse($this->cache->has('key1'));
self::assertNull($this->cache->get('key1'));
}
public function testConsidersTtlForCacheItemsWithDateIntervals(): void {
$interval = new DateInterval('PT1S'); // 1 second
$this->cache->set('key1', 'value1', $interval);
self::assertTrue($this->cache->has('key1'));
self::assertSame('value1', $this->cache->get('key1'));
// Sleep to let TTL expire
sleep(2);
self::assertFalse($this->cache->has('key1'));
self::assertNull($this->cache->get('key1'));
}
public function testReturnsArrayIfMultipleItemsAreRequested(): void {
$this->cache->set('key1', 'value1');
$this->cache->set('key2', 'value2');
$result = $this->cache->getMultiple(['key1', 'key2', 'key3'], 'default');
self::assertSame(
[
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'default',
],
$result,
);
}
public function testCanSetMultipleItems(): void {
$values = [
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3',
];
$result = $this->cache->setMultiple($values);
self::assertTrue($result);
self::assertSame('value1', $this->cache->get('key1'));
self::assertSame('value2', $this->cache->get('key2'));
self::assertSame('value3', $this->cache->get('key3'));
}
public function testCanSetMultipleItemsWithTtl(): void {
$values = [
'key1' => 'value1',
'key2' => 'value2',
];
$this->cache->setMultiple($values, 1);
self::assertTrue($this->cache->has('key1'));
self::assertTrue($this->cache->has('key2'));
sleep(2);
self::assertFalse($this->cache->has('key1'));
self::assertFalse($this->cache->has('key2'));
}
public function testCanDeleteMultipleItemsByKey(): void {
$this->cache->set('key1', 'value1');
$this->cache->set('key2', 'value2');
$this->cache->set('key3', 'value3');
$result = $this->cache->deleteMultiple(['key1', 'key3']);
self::assertTrue($result);
self::assertFalse($this->cache->has('key1'));
self::assertTrue($this->cache->has('key2'));
self::assertFalse($this->cache->has('key3'));
}
public function testCanStoreComplexDataTypes(): void {
$array = ['nested' => ['data' => 'value']];
$object = new stdClass();
$object->property = 'test';
$this->cache->set('array', $array);
$this->cache->set('object', $object);
self::assertSame($array, $this->cache->get('array'));
self::assertEquals($object, $this->cache->get('object'));
}
public function testThrowsExceptionOnInvalidKeys(): void {
$this->expectException(InvalidArgumentException::class);
$this->cache->set('invalid{key}', 'value');
}
public function testThrowsExceptionOnEmptyKeys(): void {
$this->expectException(InvalidArgumentException::class);
$this->cache->set('', 'value');
}
public function testThrowsExceptionOnKeysWithInvalidCharacters(): void {
$invalidKeys = ['key{', 'key}', 'key(', 'key)', 'key/', 'key\\', 'key@', 'key:'];
foreach ($invalidKeys as $key) {
try {
$this->cache->set($key, 'value');
self::fail("Expected InvalidArgumentException for key: $key");
} catch (InvalidArgumentException $e) {
// Expected exception
self::assertTrue(true);
}
}
}
public function testExpiredKeysAreRemovedOnAccess(): void {
$this->cache->set('key1', 'value1', 1);
// Verify it exists initially
self::assertTrue($this->cache->has('key1'));
// Wait for expiry
sleep(2);
// Access should trigger cleanup
self::assertFalse($this->cache->has('key1'));
self::assertNull($this->cache->get('key1'));
}
}