diff --git a/src/System/Cache/CacheManager.php b/src/System/Cache/CacheManager.php index 3617643e..acd9a624 100644 --- a/src/System/Cache/CacheManager.php +++ b/src/System/Cache/CacheManager.php @@ -4,6 +4,7 @@ namespace System\Cache; +use System\Cache\Exceptions\UnsupportedCacheDriverException; use System\Cache\Storage\ArrayStorage; class CacheManager implements CacheInterface @@ -44,7 +45,7 @@ private function resolve(string $driver_name): CacheInterface } if (null === $driver) { - throw new \Exception("Can use driver {$driver_name}."); + throw new UnsupportedCacheDriverException("Can use driver {$driver_name}."); } return $this->driver[$driver_name] = $driver; diff --git a/src/System/Cache/Exceptions/CacheException.php b/src/System/Cache/Exceptions/CacheException.php index 1fe1895e..0aac9e01 100644 --- a/src/System/Cache/Exceptions/CacheException.php +++ b/src/System/Cache/Exceptions/CacheException.php @@ -4,6 +4,6 @@ namespace System\Cache\Exceptions; -class CacheException extends \Exception +interface CacheException extends \Throwable { } diff --git a/src/System/Cache/Exceptions/InvalidCacheArgumentException.php b/src/System/Cache/Exceptions/InvalidCacheArgumentException.php new file mode 100644 index 00000000..f3a833b7 --- /dev/null +++ b/src/System/Cache/Exceptions/InvalidCacheArgumentException.php @@ -0,0 +1,9 @@ +has($key) && false === is_int($this->get($key))) { - throw new \InvalidArgumentException('Value increment must be integer.'); + throw new InvalidCacheArgumentException('Value increment must be integer.'); } $result = \apcu_inc($this->prefix . $key, $value, $success); diff --git a/src/System/Cache/Storage/MemcachedStorage.php b/src/System/Cache/Storage/MemcachedStorage.php index 795ef780..4c51645b 100644 --- a/src/System/Cache/Storage/MemcachedStorage.php +++ b/src/System/Cache/Storage/MemcachedStorage.php @@ -6,6 +6,8 @@ use System\Cache\CacheInterface; use System\Cache\Exceptions\CacheException; +use System\Cache\Exceptions\InvalidCacheArgumentException; +use System\Cache\Exceptions\UnsupportedCacheDriverException; class MemcachedStorage implements CacheInterface { @@ -22,7 +24,7 @@ public function __construct( $class = '\Memcached'; if (false === class_exists($class) || false === ($memcached instanceof $class)) { - throw new \InvalidArgumentException('The memcached must be an instance of \Memcached.'); + throw new InvalidCacheArgumentException('The memcached must be an instance of \Memcached.'); } $this->memcached = $memcached; @@ -185,7 +187,7 @@ private function call(callable $operation): mixed try { return $operation(); } catch (\MemcachedException $e) { - throw new CacheException($e->getMessage(), (int) $e->getCode(), $e); + throw new UnsupportedCacheDriverException($e->getMessage(), (int) $e->getCode(), $e); } } diff --git a/src/System/Cache/Storage/PdoStorage.php b/src/System/Cache/Storage/PdoStorage.php index 1fd2a817..70dfd7a7 100644 --- a/src/System/Cache/Storage/PdoStorage.php +++ b/src/System/Cache/Storage/PdoStorage.php @@ -5,6 +5,8 @@ namespace System\Cache\Storage; use System\Cache\CacheInterface; +use System\Cache\Exceptions\InvalidCacheArgumentException; +use System\Cache\Exceptions\UnsupportedCacheDriverException; class PdoStorage implements CacheInterface { @@ -19,11 +21,11 @@ public function __construct( /** @var class-string $class */ $class = '\PDO'; if (false === extension_loaded('pdo') || false === class_exists($class)) { - throw new \RuntimeException('The PDO extension is required to use PdoStorage.'); + throw new UnsupportedCacheDriverException('The PDO extension is required to use PdoStorage.'); } if (false === ($this->pdo instanceof $class)) { - throw new \InvalidArgumentException('The pdo must be an instance of \PDO.'); + throw new InvalidCacheArgumentException('The pdo must be an instance of \PDO.'); } } @@ -158,7 +160,7 @@ public function increment(string $key, int $value): int $expiration = (int) $row['expiration']; if (false === is_int($current)) { - throw new \InvalidArgumentException('Value increment must be integer.'); + throw new InvalidCacheArgumentException('Value increment must be integer.'); } $new = $current + $value; diff --git a/tests/Cache/CacheManagerTest.php b/tests/Cache/CacheManagerTest.php index e2a1af4e..79710b0b 100644 --- a/tests/Cache/CacheManagerTest.php +++ b/tests/Cache/CacheManagerTest.php @@ -7,6 +7,7 @@ use PHPUnit\Framework\TestCase; use System\Cache\CacheInterface; use System\Cache\CacheManager; +use System\Cache\Exceptions\UnsupportedCacheDriverException; use System\Cache\Storage\ArrayStorage; class CacheManagerTest extends TestCase @@ -30,4 +31,20 @@ public function testDriver(): void $this->assertTrue($cache->driver('array2')->set('key1', 'value1')); $this->assertEquals('value1', $cache->driver('array2')->get('key1')); } + + /** + * @test + * + * @testdox It throws UnsupportedCacheDriverException if driver cannot be resolved + * + * @covers \System\Cache\CacheManager::resolve + */ + public function itThrowsUnsupportedCacheDriverExceptionWhenDriverCannotBeResolved(): void + { + $cache = new CacheManager(); + $cache->setDriver('invalid', fn () => null); + + $this->expectException(UnsupportedCacheDriverException::class); + $cache->driver('invalid'); + } } diff --git a/tests/Cache/Storage/ApcuStorageTest.php b/tests/Cache/Storage/ApcuStorageTest.php index c36c29e0..340a7643 100644 --- a/tests/Cache/Storage/ApcuStorageTest.php +++ b/tests/Cache/Storage/ApcuStorageTest.php @@ -5,6 +5,8 @@ namespace System\Text\Cache\Storage; use PHPUnit\Framework\TestCase; +use System\Cache\Exceptions\InvalidCacheArgumentException; +use System\Cache\Exceptions\UnsupportedCacheDriverException; use System\Cache\Storage\ApcuStorage; /** @@ -233,4 +235,35 @@ public function itCanRemember(): void $value = $this->storage->remember('key1', 1, fn (): string => 'value2'); $this->assertEquals('value1', $value); } + + /** + * @test + * + * @testdox It throws UnsupportedCacheDriverException if APCu is not supported + * + * @covers \System\Cache\Storage\ApcuStorage::__construct + */ + public function itThrowsUnsupportedCacheDriverExceptionWhenApcuIsNotSupported(): void + { + if (ApcuStorage::isSupported()) { + $this->markTestSkipped('APCu extension is loaded or enabled for CLI.'); + } + + $this->expectException(UnsupportedCacheDriverException::class); + new ApcuStorage('test_'); + } + + /** + * @test + * + * @testdox It throws InvalidCacheArgumentException if increment value is not integer + * + * @covers \System\Cache\Storage\ApcuStorage::increment + */ + public function itThrowsInvalidCacheArgumentExceptionWhenIncrementValueIsNotInteger(): void + { + $this->storage->set('key', 'not an integer'); + $this->expectException(InvalidCacheArgumentException::class); + $this->storage->increment('key', 1); + } } diff --git a/tests/Cache/Storage/MemcachedStorageTest.php b/tests/Cache/Storage/MemcachedStorageTest.php index 6a09ba54..2f8f0515 100644 --- a/tests/Cache/Storage/MemcachedStorageTest.php +++ b/tests/Cache/Storage/MemcachedStorageTest.php @@ -5,6 +5,8 @@ namespace System\Test\Cache\Storage; use PHPUnit\Framework\TestCase; +use System\Cache\Exceptions\InvalidCacheArgumentException; +use System\Cache\Exceptions\UnsupportedCacheDriverException; use System\Cache\Storage\MemcachedConnector; use System\Cache\Storage\MemcachedStorage; @@ -241,4 +243,35 @@ public function itNormalizesInvalidKeys(): void $this->assertTrue($this->storage->set($longKey, 'value2')); $this->assertEquals('value2', $this->storage->get($longKey)); } + + /** + * @test + * + * @testdox It throws InvalidCacheArgumentException if memcached is not an instance of \Memcached + * + * @covers \System\Cache\Storage\MemcachedStorage::__construct + */ + public function itThrowsInvalidCacheArgumentExceptionWhenMemcachedIsNotInstanceOfMemcached(): void + { + $this->expectException(InvalidCacheArgumentException::class); + new MemcachedStorage(new \stdClass()); + } + + /** + * @test + * + * @testdox It throws UnsupportedCacheDriverException if MemcachedException is thrown + * + * @covers \System\Cache\Storage\MemcachedStorage::get + */ + public function itThrowsUnsupportedCacheDriverExceptionWhenMemcachedExceptionIsThrown(): void + { + $memcachedMock = $this->createMock(\Memcached::class); + $memcachedMock->method('get')->willThrowException(new \MemcachedException('Test exception')); + + $storage = new MemcachedStorage($memcachedMock); + + $this->expectException(UnsupportedCacheDriverException::class); + $storage->get('key'); + } } diff --git a/tests/Cache/Storage/PdoStorageTest.php b/tests/Cache/Storage/PdoStorageTest.php index a7ee8d60..de075499 100644 --- a/tests/Cache/Storage/PdoStorageTest.php +++ b/tests/Cache/Storage/PdoStorageTest.php @@ -5,6 +5,7 @@ namespace System\Test\Cache\Storage; use PHPUnit\Framework\TestCase; +use System\Cache\Exceptions\InvalidCacheArgumentException; use System\Cache\Storage\PdoStorage; /** @@ -167,4 +168,18 @@ public function itCanHandleMultipleCacheOperations() $this->assertNull($this->storage->get('a')); $this->assertNull($this->storage->get('b')); } + + /** + * @test + * + * @testdox It throws InvalidCacheArgumentException if increment value is not integer + * + * @covers \System\Cache\Storage\PdoStorage::increment + */ + public function itThrowsInvalidCacheArgumentExceptionWhenIncrementValueIsNotInteger(): void + { + $this->storage->set('key', 'not an integer'); + $this->expectException(InvalidCacheArgumentException::class); + $this->storage->increment('key', 1); + } }