diff --git a/.travis.yml b/.travis.yml index 857485eed..af8cf0081 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ php: - nightly services: - mysql + - redis + - memcached before_script: - pecl install ast - composer install diff --git a/DataStorage/Cache/CacheStatus.php b/DataStorage/Cache/CacheStatus.php index 5596ee0ad..942080ce2 100644 --- a/DataStorage/Cache/CacheStatus.php +++ b/DataStorage/Cache/CacheStatus.php @@ -28,8 +28,8 @@ use phpOMS\Stdlib\Base\Enum; */ abstract class CacheStatus extends Enum { - public const ACTIVE = 0; - public const INACTIVE = 1; - public const ERROR = 2; - public const UNDEFINED = 3; + public const OK = 0; + public const FAILURE = 1; + public const READONLY = 2; + public const CLOSED = 3; } diff --git a/DataStorage/Cache/CacheType.php b/DataStorage/Cache/CacheType.php index afb2f7689..5e79ca398 100644 --- a/DataStorage/Cache/CacheType.php +++ b/DataStorage/Cache/CacheType.php @@ -31,6 +31,5 @@ abstract class CacheType extends Enum public const FILE = 'file'; public const MEMCACHED = 'mem'; public const REDIS = 'redis'; - public const WINCACHE = 'win'; public const UNDEFINED = 'na'; } diff --git a/DataStorage/Cache/Connection/ConnectionAbstract.php b/DataStorage/Cache/Connection/ConnectionAbstract.php index 8baac3b3b..5b77f3394 100644 --- a/DataStorage/Cache/Connection/ConnectionAbstract.php +++ b/DataStorage/Cache/Connection/ConnectionAbstract.php @@ -73,7 +73,7 @@ abstract class ConnectionAbstract implements ConnectionInterface * @var int * @since 1.0.0 */ - protected $status = CacheStatus::INACTIVE; + protected $status = CacheStatus::CLOSED; /** * {@inheritdoc} @@ -100,7 +100,7 @@ abstract class ConnectionAbstract implements ConnectionInterface */ public function getCache() : string { - return $this->dbdata['database'] ?? ''; + return (string) ($this->dbdata['db'] ?? ''); } /** @@ -157,6 +157,24 @@ abstract class ConnectionAbstract implements ConnectionInterface public function close() : void { $this->con = null; - $this->status = CacheStatus::INACTIVE; + $this->status = CacheStatus::CLOSED; + } + + /** + * Parse values for cache storage + * + * @param mixed $value Value to parse + * + * @return mixed + * + * @since 1.0.0 + */ + protected function parseValue($value) + { + if (\is_array($value)) { + return \json_encode($value); + } + + return $value; } } diff --git a/DataStorage/Cache/Connection/ConnectionFactory.php b/DataStorage/Cache/Connection/ConnectionFactory.php index 8f70c6a04..b31d35909 100644 --- a/DataStorage/Cache/Connection/ConnectionFactory.php +++ b/DataStorage/Cache/Connection/ConnectionFactory.php @@ -52,17 +52,15 @@ class ConnectionFactory */ public static function create(array $cacheData) : ConnectionInterface { - switch ($cacheData['type']) { + switch ($cacheData['type'] ?? '') { case CacheType::FILE: - return new FileCache($cacheData['path']); + return new FileCache($cacheData['path'] ?? ''); case CacheType::REDIS: - return new RedisCache($cacheData); + return new RedisCache($cacheData['data'] ?? []); case CacheType::MEMCACHED: - return new MemCached($cacheData); - case CacheType::WINCACHE: - return new WinCache($cacheData); + return new MemCached($cacheData['data'] ?? []); default: - throw new \InvalidArgumentException('Cache "' . $cacheData['type'] . '" is not supported.'); + throw new \InvalidArgumentException('Cache "' . ($cacheData['type'] ?? '') . '" is not supported.'); } } } diff --git a/DataStorage/Cache/Connection/FileCache.php b/DataStorage/Cache/Connection/FileCache.php index 2ba18837d..7b4672a9f 100644 --- a/DataStorage/Cache/Connection/FileCache.php +++ b/DataStorage/Cache/Connection/FileCache.php @@ -15,9 +15,11 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Cache\Connection; use phpOMS\DataStorage\Cache\CacheStatus; +use phpOMS\DataStorage\Cache\CacheType; use phpOMS\Stdlib\Base\Exception\InvalidEnumValue; use phpOMS\System\File\Local\Directory; use phpOMS\System\File\Local\File; +use phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException; /** * MemCache class. @@ -31,6 +33,10 @@ use phpOMS\System\File\Local\File; */ class FileCache extends ConnectionAbstract { + /** + * {@inheritdoc} + */ + protected $type = CacheType::FILE; /** * Delimiter for cache meta data @@ -65,12 +71,7 @@ class FileCache extends ConnectionAbstract */ public function __construct(string $path) { - if (!Directory::exists($path)) { - Directory::create($path, 0766, true); - } - - $this->status = CacheStatus::ACTIVE; - $this->con = \realpath($path); + $this->connect([$path]); } /** @@ -78,7 +79,19 @@ class FileCache extends ConnectionAbstract */ public function connect(array $data) : void { - $this->status = CacheStatus::ACTIVE; + $this->dbdata = $data; + + if (!Directory::exists($data[0])) { + Directory::create($data[0], 0766, true); + } + + if (\realpath($data[0]) === false) { + $this->status = CacheStatus::FAILURE; + throw new InvalidConnectionConfigException((string) \json_encode($this->dbdata)); + } + + $this->status = CacheStatus::OK; + $this->con = \realpath($data[0]); } /** @@ -86,7 +99,7 @@ class FileCache extends ConnectionAbstract */ public function flushAll() : bool { - if ($this->status !== CacheStatus::ACTIVE) { + if ($this->status !== CacheStatus::OK) { return false; } @@ -100,11 +113,14 @@ class FileCache extends ConnectionAbstract */ public function stats() : array { - $stats = []; - $stats['status'] = $this->status; - $stats['count'] = Directory::count($this->con); - $stats['size'] = Directory::size($this->con); - $stats['changed'] = Directory::changed($this->con); + if ($this->status !== CacheStatus::OK) { + return []; + } + + $stats = []; + $stats['status'] = $this->status; + $stats['count'] = Directory::count($this->con); + $stats['size'] = Directory::size($this->con); return $stats; } @@ -122,7 +138,7 @@ class FileCache extends ConnectionAbstract */ public function set($key, $value, int $expire = -1) : void { - if ($this->status !== CacheStatus::ACTIVE) { + if ($this->status !== CacheStatus::OK) { return; } @@ -136,7 +152,7 @@ class FileCache extends ConnectionAbstract */ public function add($key, $value, int $expire = -1) : bool { - if ($this->status !== CacheStatus::ACTIVE) { + if ($this->status !== CacheStatus::OK) { return false; } @@ -252,7 +268,7 @@ class FileCache extends ConnectionAbstract */ public function get($key, int $expire = -1) { - if ($this->status !== CacheStatus::ACTIVE) { + if ($this->status !== CacheStatus::OK) { return null; } @@ -290,7 +306,7 @@ class FileCache extends ConnectionAbstract return null; } - return $this->parseValue($type, $raw, $expireEnd); + return $this->reverseValue($type, $raw, $expireEnd); } /** @@ -304,7 +320,7 @@ class FileCache extends ConnectionAbstract * * @since 1.0.0 */ - private function parseValue(int $type, string $raw, int $expireEnd) + private function reverseValue(int $type, string $raw, int $expireEnd) { $value = null; @@ -350,7 +366,7 @@ class FileCache extends ConnectionAbstract */ public function delete($key, int $expire = -1) : bool { - if ($this->status !== CacheStatus::ACTIVE) { + if ($this->status !== CacheStatus::OK) { return false; } @@ -401,7 +417,7 @@ class FileCache extends ConnectionAbstract */ public function flush(int $expire = 0) : bool { - if ($this->status !== CacheStatus::ACTIVE) { + if ($this->status !== CacheStatus::OK) { return false; } @@ -427,7 +443,7 @@ class FileCache extends ConnectionAbstract */ public function replace($key, $value, int $expire = -1) : bool { - if ($this->status !== CacheStatus::ACTIVE) { + if ($this->status !== CacheStatus::OK) { return false; } diff --git a/DataStorage/Cache/Connection/MemCached.php b/DataStorage/Cache/Connection/MemCached.php index b5bf80927..9076b3d46 100644 --- a/DataStorage/Cache/Connection/MemCached.php +++ b/DataStorage/Cache/Connection/MemCached.php @@ -14,6 +14,10 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Cache\Connection; +use phpOMS\DataStorage\Cache\CacheStatus; +use phpOMS\DataStorage\Cache\CacheType; +use phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException; + /** * Memcache class. * @@ -24,14 +28,10 @@ namespace phpOMS\DataStorage\Cache\Connection; */ class MemCached extends ConnectionAbstract { - /** - * Memcache instance. - * - * @var \Memcache - * @since 1.0.0 + * {@inheritdoc} */ - private $memc = null; + protected $type = CacheType::MEMCACHED; /** * Only cache if data is larger than threshold (0-100). @@ -39,7 +39,7 @@ class MemCached extends ConnectionAbstract * @var int * @since 1.0.0 */ - private $threshold = 10; + private $threshold = 0; /** * Constructor. @@ -50,7 +50,8 @@ class MemCached extends ConnectionAbstract */ public function __construct(array $data) { - $this->memc = null; + $this->con = new \Memcached(); + $this->connect($data); } /** @@ -58,21 +59,16 @@ class MemCached extends ConnectionAbstract */ public function connect(array $data) : void { - $this->status = CacheStatus::ACTIVE; - } + $this->dbdata = isset($data) ? $data : $this->dbdata; - /** - * Adding server to server pool. - * - * @param mixed $data Server data array - * - * @return void - * - * @since 1.0.0 - */ - public function addServer($data) - { - $this->memc->addServer($data['host'], $data['port'], $data['timeout']); + if (!isset($this->dbdata['host'], $this->dbdata['port'])) { + $this->status = CacheStatus::FAILURE; + throw new InvalidConnectionConfigException((string) \json_encode($this->dbdata)); + } + + $this->con->addServer($this->dbdata['host'], $this->dbdata['port']); + + $this->status = CacheStatus::OK; } /** @@ -80,7 +76,9 @@ class MemCached extends ConnectionAbstract */ public function set($key, $value, int $expire = -1) : void { - $this->memc->set($key, $value, false, $expire); + $value = $this->parseValue($value); + + $this->con->set($key, $value, \max($expire, 0)); } /** @@ -88,7 +86,13 @@ class MemCached extends ConnectionAbstract */ public function add($key, $value, int $expire = -1) : bool { - return $this->memc->add($key, $value, false, $expire); + if ($this->status !== CacheStatus::OK) { + return false; + } + + $value = $this->parseValue($value); + + return $this->con->add($key, $value, \max($expire, 0)); } /** @@ -96,7 +100,13 @@ class MemCached extends ConnectionAbstract */ public function get($key, int $expire = -1) { - return $this->memc->get($key); + if ($this->status !== CacheStatus::OK) { + return null; + } + + $result = $this->con->get($key); + + return $result === false ? null : $result; } /** @@ -104,7 +114,11 @@ class MemCached extends ConnectionAbstract */ public function delete($key, int $expire = -1) : bool { - $this->memc->delete($key); + if ($this->status !== CacheStatus::OK) { + return false; + } + + return $this->con->delete($key); } /** @@ -112,7 +126,11 @@ class MemCached extends ConnectionAbstract */ public function flush(int $expire = 0) : bool { - $this->memc->flush(); + if ($this->status !== CacheStatus::OK) { + return false; + } + + $this->con->flush(); return true; } @@ -122,7 +140,11 @@ class MemCached extends ConnectionAbstract */ public function flushAll() : bool { - $this->memc->flush(); + if ($this->status !== CacheStatus::OK) { + return false; + } + + $this->con->flush(); return true; } @@ -132,7 +154,13 @@ class MemCached extends ConnectionAbstract */ public function replace($key, $value, int $expire = -1) : bool { - $this->memc->replace($key, $value, false, $expire); + if ($this->status !== CacheStatus::OK) { + return false; + } + + $value = $this->parseValue($value); + + return $this->con->replace($key, $value, \max($expire, 0)); } /** @@ -140,8 +168,19 @@ class MemCached extends ConnectionAbstract */ public function stats() : array { - /** @noinspection PhpMethodOrClassCallIsNotCaseSensitiveInspection */ - return $this->memc->getExtendedStats(); + if ($this->status !== CacheStatus::OK) { + return []; + } + + $stat = $this->con->getStats(); + $temp = \reset($stat); + + $stats = []; + $stats['status'] = $this->status; + $stats['count'] = $temp['curr_items']; + $stats['size'] = $temp['bytes']; + + return $stats; } /** @@ -152,14 +191,6 @@ class MemCached extends ConnectionAbstract return $this->threshold; } - /** - * {@inheritdoc} - */ - public function setStatus(int $status) /* : void */ - { - $this->status = $status; - } - /** * Destructor. * @@ -179,9 +210,10 @@ class MemCached extends ConnectionAbstract */ public function close() : void { - if ($this->memc !== null) { - $this->memc->close(); - $this->memc = null; + if ($this->con !== null) { + $this->con->quit(); } + + parent::close(); } } diff --git a/DataStorage/Cache/Connection/NullCache.php b/DataStorage/Cache/Connection/NullCache.php index 88b76c380..5767c1ba4 100644 --- a/DataStorage/Cache/Connection/NullCache.php +++ b/DataStorage/Cache/Connection/NullCache.php @@ -102,11 +102,4 @@ class NullCache extends ConnectionAbstract { return 0; } - - /** - * {@inheritdoc} - */ - public function setStatus(int $status) : void - { - } } diff --git a/DataStorage/Cache/Connection/RedisCache.php b/DataStorage/Cache/Connection/RedisCache.php index 51e0ab748..232c6bdeb 100644 --- a/DataStorage/Cache/Connection/RedisCache.php +++ b/DataStorage/Cache/Connection/RedisCache.php @@ -15,6 +15,8 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Cache\Connection; use phpOMS\DataStorage\Cache\CacheStatus; +use phpOMS\DataStorage\Cache\CacheType; +use phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException; /** * RedisCache class. @@ -28,6 +30,10 @@ use phpOMS\DataStorage\Cache\CacheStatus; */ class RedisCache extends ConnectionAbstract { + /** + * {@inheritdoc} + */ + protected $type = CacheType::REDIS; /** * Constructor @@ -38,6 +44,8 @@ class RedisCache extends ConnectionAbstract */ public function __construct(array $data) { + $this->con = new \Redis(); + $this->connect($data); } /** @@ -45,7 +53,37 @@ class RedisCache extends ConnectionAbstract */ public function connect(array $data) : void { - $this->status = CacheStatus::ACTIVE; + $this->dbdata = isset($data) ? $data : $this->dbdata; + + if (!isset($this->dbdata['host'], $this->dbdata['port'], $this->dbdata['db'])) { + $this->status = CacheStatus::FAILURE; + throw new InvalidConnectionConfigException((string) \json_encode($this->dbdata)); + } + + $this->con->connect($this->dbdata['host'], $this->dbdata['port']); + + try { + $this->con->ping(); + } catch (\Throwable $e) { + $this->status = CacheStatus::FAILURE; + return; + } + + $this->con->setOption(\Redis::OPT_SERIALIZER, (string) \Redis::SERIALIZER_NONE); + $this->con->setOption(\Redis::OPT_SCAN, (string) \Redis::SCAN_NORETRY); + $this->con->select($this->dbdata['db']); + + $this->status = CacheStatus::OK; + } + + + public function close() : void + { + if ($this->con !== null) { + $this->con->close(); + } + + parent::close(); } /** @@ -53,7 +91,13 @@ class RedisCache extends ConnectionAbstract */ public function set($key, $value, int $expire = -1) : void { - // TODO: Implement set() method. + $value = $this->parseValue($value); + + if ($expire > 0) { + $this->con->set($key, $value, $expire); + } + + $this->con->set($key, $value); } /** @@ -61,7 +105,17 @@ class RedisCache extends ConnectionAbstract */ public function add($key, $value, int $expire = -1) : bool { - // TODO: Implement add() method. + if ($this->status !== CacheStatus::OK) { + return false; + } + + $value = $this->parseValue($value); + + if ($expire > 0) { + return $this->con->setNx($key, $value, $expire); + } + + return $this->con->setNx($key, $value); } /** @@ -69,7 +123,13 @@ class RedisCache extends ConnectionAbstract */ public function get($key, int $expire = -1) { - // TODO: Implement get() method. + if ($this->status !== CacheStatus::OK) { + return null; + } + + $result = $this->con->get($key); + + return $result === false ? null : $result; } /** @@ -77,7 +137,11 @@ class RedisCache extends ConnectionAbstract */ public function delete($key, int $expire = -1) : bool { - // TODO: Implement delete() method. + if ($this->status !== CacheStatus::OK) { + return false; + } + + return $this->con->delete($key) > 0; } /** @@ -85,7 +149,11 @@ class RedisCache extends ConnectionAbstract */ public function flush(int $expire = 0) : bool { - // TODO: Implement flush() method. + if ($this->status !== CacheStatus::OK) { + return false; + } + + $this->con->flushDb(); return true; } @@ -95,7 +163,11 @@ class RedisCache extends ConnectionAbstract */ public function flushAll() : bool { - // TODO: Implement flush() method. + if ($this->status !== CacheStatus::OK) { + return false; + } + + $this->con->flushDb(); return true; } @@ -105,7 +177,19 @@ class RedisCache extends ConnectionAbstract */ public function replace($key, $value, int $expire = -1) : bool { - // TODO: Implement replace() method. + if ($this->status !== CacheStatus::OK) { + return false; + } + + $value = $this->parseValue($value); + + if ($this->con->exists($key) > 0) { + $this->set($key, $value, $expire); + + return true; + } + + return false; } /** @@ -113,7 +197,18 @@ class RedisCache extends ConnectionAbstract */ public function stats() : array { - // TODO: Implement stats() method. + if ($this->status !== CacheStatus::OK) { + return []; + } + + $info = $this->con->info(); + + $stats = []; + $stats['status'] = $this->status; + $stats['count'] = $this->con->dbSize(); + $stats['size'] = $info['used_memory']; + + return $stats; } /** @@ -121,14 +216,16 @@ class RedisCache extends ConnectionAbstract */ public function getThreshold() : int { - // TODO: Implement getThreshold() method. + return 0; } /** - * {@inheritdoc} + * Destructor. + * + * @since 1.0.0 */ - public function setStatus(int $status) : void + public function __destruct() { - // TODO: Implement setStatus() method. + $this->close(); } } diff --git a/DataStorage/Cache/Connection/WinCache.php b/DataStorage/Cache/Connection/WinCache.php deleted file mode 100644 index b0ba86d90..000000000 --- a/DataStorage/Cache/Connection/WinCache.php +++ /dev/null @@ -1,133 +0,0 @@ -status = CacheStatus::ACTIVE; - } - - /** - * {@inheritdoc} - */ - public function set($key, $value, int $expire = -1) : void - { - // TODO: Implement set() method. - } - - /** - * {@inheritdoc} - */ - public function add($key, $value, int $expire = -1) : bool - { - // TODO: Implement add() method. - } - - /** - * {@inheritdoc} - */ - public function get($key, int $expire = -1) - { - // TODO: Implement get() method. - } - - /** - * {@inheritdoc} - */ - public function delete($key, int $expire = -1) : bool - { - // TODO: Implement delete() method. - } - - /** - * {@inheritdoc} - */ - public function flush(int $expire = 0) : bool - { - // TODO: Implement flush() method. - - return true; - } - - /** - * {@inheritdoc} - */ - public function flushAll() : bool - { - // TODO: Implement flush() method. - - return true; - } - - /** - * {@inheritdoc} - */ - public function replace($key, $value, int $expire = -1) : bool - { - // TODO: Implement replace() method. - } - - /** - * {@inheritdoc} - */ - public function stats() : array - { - // TODO: Implement stats() method. - } - - /** - * {@inheritdoc} - */ - public function getThreshold() : int - { - // TODO: Implement getThreshold() method. - } - - /** - * {@inheritdoc} - */ - public function setStatus(int $status) : void - { - // TODO: Implement setStatus() method. - } -} diff --git a/DataStorage/Cache/Exception/InvalidConnectionConfigException.php b/DataStorage/Cache/Exception/InvalidConnectionConfigException.php new file mode 100644 index 000000000..e5a1b0c85 --- /dev/null +++ b/DataStorage/Cache/Exception/InvalidConnectionConfigException.php @@ -0,0 +1,40 @@ + [ + 'redis' => [ + 'db' => 1, + 'host' => '127.0.0.1', + 'port' => 6379, + ], + 'memcached' => [ + 'host' => '127.0.0.1', + 'port' => 11211, + ], + ], 'log' => [ 'file' => [ 'path' => __DIR__ . '/Logs', diff --git a/tests/DataStorage/Cache/CacheStatusTest.php b/tests/DataStorage/Cache/CacheStatusTest.php index 9c667c5fb..e910aa8ef 100644 --- a/tests/DataStorage/Cache/CacheStatusTest.php +++ b/tests/DataStorage/Cache/CacheStatusTest.php @@ -20,9 +20,9 @@ class CacheStatusTest extends \PHPUnit\Framework\TestCase public function testEnums() { self::assertEquals(4, \count(CacheStatus::getConstants())); - self::assertEquals(0, CacheStatus::ACTIVE); - self::assertEquals(1, CacheStatus::INACTIVE); - self::assertEquals(2, CacheStatus::ERROR); - self::assertEquals(3, CacheStatus::UNDEFINED); + self::assertEquals(0, CacheStatus::OK); + self::assertEquals(1, CacheStatus::FAILURE); + self::assertEquals(2, CacheStatus::READONLY); + self::assertEquals(3, CacheStatus::CLOSED); } } diff --git a/tests/DataStorage/Cache/CacheTypeTest.php b/tests/DataStorage/Cache/CacheTypeTest.php index 85392bc6e..219c9bd46 100644 --- a/tests/DataStorage/Cache/CacheTypeTest.php +++ b/tests/DataStorage/Cache/CacheTypeTest.php @@ -19,11 +19,10 @@ class CacheTypeTest extends \PHPUnit\Framework\TestCase { public function testEnums() { - self::assertEquals(5, \count(CacheType::getConstants())); + self::assertEquals(4, \count(CacheType::getConstants())); self::assertEquals('file', CacheType::FILE); self::assertEquals('mem', CacheType::MEMCACHED); self::assertEquals('redis', CacheType::REDIS); - self::assertEquals('win', CacheType::WINCACHE); self::assertEquals('na', CacheType::UNDEFINED); } } diff --git a/tests/DataStorage/Cache/Connection/ConnectionFactoryTest.php b/tests/DataStorage/Cache/Connection/ConnectionFactoryTest.php index 111a3060b..e206e3c30 100644 --- a/tests/DataStorage/Cache/Connection/ConnectionFactoryTest.php +++ b/tests/DataStorage/Cache/Connection/ConnectionFactoryTest.php @@ -14,6 +14,7 @@ namespace phpOMS\tests\DataStorage\Cache\Connection; use phpOMS\DataStorage\Cache\Connection\ConnectionFactory; +use phpOMS\DataStorage\Cache\CacheType; class ConnectionFactoryTest extends \PHPUnit\Framework\TestCase { @@ -21,7 +22,17 @@ class ConnectionFactoryTest extends \PHPUnit\Framework\TestCase { self::assertInstanceOf( \phpOMS\DataStorage\Cache\Connection\FileCache::class, - ConnectionFactory::create(['type' => 'file', 'path' => 'Cache']) + ConnectionFactory::create(['type' => CacheType::FILE, 'path' => 'Cache']) + ); + + self::assertInstanceOf( + \phpOMS\DataStorage\Cache\Connection\MemCached::class, + ConnectionFactory::create(['type' => CacheType::MEMCACHED, 'data' => $GLOBALS['CONFIG']['cache']['memcached']]) + ); + + self::assertInstanceOf( + \phpOMS\DataStorage\Cache\Connection\RedisCache::class, + ConnectionFactory::create(['type' => CacheType::REDIS, 'data' => $GLOBALS['CONFIG']['cache']['redis']]) ); } diff --git a/tests/DataStorage/Cache/Connection/FileCacheTest.php b/tests/DataStorage/Cache/Connection/FileCacheTest.php index 90554b92c..5941cb522 100644 --- a/tests/DataStorage/Cache/Connection/FileCacheTest.php +++ b/tests/DataStorage/Cache/Connection/FileCacheTest.php @@ -14,6 +14,9 @@ namespace phpOMS\tests\DataStorage\Cache\Connection; use phpOMS\DataStorage\Cache\Connection\FileCache; +use phpOMS\DataStorage\Cache\CacheStatus; +use phpOMS\DataStorage\Cache\CacheType; +use phpOMS\Utils\TestUtils; class FileCacheTest extends \PHPUnit\Framework\TestCase { @@ -25,6 +28,8 @@ class FileCacheTest extends \PHPUnit\Framework\TestCase $cache = new FileCache(__DIR__ . '/Cache'); + self::assertEquals('', $cache->getPrefix()); + self::assertEquals(CacheType::FILE, $cache->getType()); self::assertTrue(\is_dir(__DIR__ . '/Cache')); self::assertTrue($cache->flushAll()); self::assertEquals(50, $cache->getThreshold()); @@ -35,6 +40,21 @@ class FileCacheTest extends \PHPUnit\Framework\TestCase } } + public function testConnect() + { + if (\file_exists(__DIR__ . '/Cache')) { + \rmdir(__DIR__ . '/Cache'); + } + + $cache = new FileCache(__DIR__ . '/Cache'); + + self::assertEquals(CacheStatus::OK, $cache->getStatus()); + + if (\file_exists(__DIR__ . '/Cache')) { + \rmdir(__DIR__ . '/Cache'); + } + } + public function testGetSet() { if (\file_exists(__DIR__ . '/Cache')) { @@ -43,35 +63,95 @@ class FileCacheTest extends \PHPUnit\Framework\TestCase $cache = new FileCache(__DIR__ . '/Cache'); - $cache->set('key1', 'testVal'); + $cache->flushAll(); + + $cache->set('key1', 'testVal'); // 1 self::assertEquals('testVal', $cache->get('key1')); - $cache->set('key2', false); + self::assertTrue($cache->add('addKey', 'testValAdd')); // 2 + self::assertFalse($cache->add('addKey', 'testValAdd2')); + self::assertEquals('testValAdd', $cache->get('addKey')); + + $cache->set('key2', false); // 3 self::assertEquals(false, $cache->get('key2')); - $cache->set('key3', null); + $cache->set('key3', null); // 4 self::assertEquals(null, $cache->get('key3')); - $cache->set('key4', 4); + $cache->set('key4', 4); // 5 self::assertEquals(4, $cache->get('key4')); - $cache->set('key5', 5.12); + $cache->set('key5', 5.12); // 6 self::assertEquals(5.12, $cache->get('key5')); - $cache->set('key6', ['asdf', 1, true, 2.3]); + $cache->set('key6', ['asdf', 1, true, 2.3]); // 7 self::assertEquals(['asdf', 1, true, 2.3], $cache->get('key6')); - $cache->replace('key4', 5); + self::assertTrue($cache->replace('key4', 5)); + self::assertFalse($cache->replace('keyInvalid', 5)); self::assertEquals(5, $cache->get('key4')); - $cache->delete('key4'); + self::assertTrue($cache->delete('key4')); // 6 + self::assertFalse($cache->delete('keyInvalid')); self::assertEquals(null, $cache->get('key4')); - $cache->flushAll(); + self::assertEquals( + [ + 'status' => CacheStatus::OK, + 'count' => 6, + 'size' => 70, + ], + $cache->stats() + ); + + self::assertTrue($cache->flushAll()); self::assertEquals(null, $cache->get('key5')); + $cache->flushAll(); + + self::assertEquals( + [ + 'status' => CacheStatus::OK, + 'count' => 0, + 'size' => 0, + ], + $cache->stats() + ); + if (\file_exists(__DIR__ . '/Cache')) { \rmdir(__DIR__ . '/Cache'); } } + + public function testBadCacheStatus() + { + if (\file_exists(__DIR__ . '/Cache')) { + \rmdir(__DIR__ . '/Cache'); + } + + $cache = new FileCache(__DIR__ . '/Cache'); + $cache->flushAll(); + + TestUtils::setMember($cache, 'status', CacheStatus::FAILURE); + + $cache->set('key1', 'testVal'); + self::assertFalse($cache->add('key2', 'testVal2')); + self::assertEquals(null, $cache->get('key1')); + self::assertFalse($cache->replace('key1', 5)); + self::assertFalse($cache->delete('key1')); + self::assertFalse($cache->flushAll()); + self::assertEquals([], $cache->stats()); + + if (\file_exists(__DIR__ . '/Cache')) { + \rmdir(__DIR__ . '/Cache'); + } + } + + /** + * @expectedException \phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException + */ + public function testInvalidCachePath() + { + $cache = new FileCache('/etc/invalidPathOrPermission^$:?><'); + } } diff --git a/tests/DataStorage/Cache/Connection/MemCacheTest.php b/tests/DataStorage/Cache/Connection/MemCacheTest.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/DataStorage/Cache/Connection/MemCachedTest.php b/tests/DataStorage/Cache/Connection/MemCachedTest.php new file mode 100644 index 000000000..7ba3a0eaa --- /dev/null +++ b/tests/DataStorage/Cache/Connection/MemCachedTest.php @@ -0,0 +1,140 @@ +getPrefix()); + self::assertEquals(CacheType::MEMCACHED, $cache->getType()); + self::assertTrue($cache->flushAll()); + self::assertEquals(0, $cache->getThreshold()); + self::assertEquals(null, $cache->get('test')); + } + + public function testConnect() + { + $cache = new MemCached($GLOBALS['CONFIG']['cache']['memcached']); + + self::assertEquals(CacheStatus::OK, $cache->getStatus()); + self::assertEquals($GLOBALS['CONFIG']['cache']['memcached']['host'], $cache->getHost()); + self::assertEquals((int) $GLOBALS['CONFIG']['cache']['memcached']['port'], $cache->getPort()); + } + + public function testGetSet() + { + $cache = new MemCached($GLOBALS['CONFIG']['cache']['memcached']); + + $cache->flushAll(); + + $cache->set('key1', 'testVal'); // 1 + self::assertEquals('testVal', $cache->get('key1')); + + self::assertTrue($cache->add('addKey', 'testValAdd')); // 2 + self::assertFalse($cache->add('addKey', 'testValAdd2')); + self::assertEquals('testValAdd', $cache->get('addKey')); + + $cache->set('key2', false); // 3 + self::assertEquals(false, $cache->get('key2')); + + $cache->set('key3', null); // 4 + self::assertEquals(null, $cache->get('key3')); + + $cache->set('key4', 4); // 5 + self::assertEquals(4, $cache->get('key4')); + + $cache->set('key5', 5.12); // 6 + self::assertEquals(5.12, $cache->get('key5')); + + $cache->set('key6', ['asdf', 1, true, 2.3]); // 7 + self::assertEquals(json_encode(['asdf', 1, true, 2.3]), $cache->get('key6')); + + self::assertTrue($cache->replace('key4', 5)); + self::assertFalse($cache->replace('keyInvalid', 5)); + self::assertEquals(5, $cache->get('key4')); + + self::assertTrue($cache->delete('key4')); // 6 + self::assertFalse($cache->delete('keyInvalid')); + self::assertEquals(null, $cache->get('key4')); + + self::assertArraySubset( + [ + 'status' => CacheStatus::OK, + 'count' => 6, + ], + $cache->stats() + ); + + self::assertTrue($cache->flushAll()); + self::assertTrue($cache->flush()); + self::assertEquals(null, $cache->get('key5')); // This reduces the stat count by one see stat comment. Stupid memcached! + + $cache->flushAll(); + + self::assertArraySubset( + [ + 'status' => CacheStatus::OK, + 'count' => 5, // Carefull memcached is dumb and keeps expired elements which were not acessed after flushing in stats + ], + $cache->stats() + ); + } + + public function testBadCacheStatus() + { + $cache = new MemCached($GLOBALS['CONFIG']['cache']['memcached']); + $cache->flushAll(); + + TestUtils::setMember($cache, 'status', CacheStatus::FAILURE); + + $cache->set('key1', 'testVal'); + self::assertFalse($cache->add('key2', 'testVal2')); + self::assertEquals(null, $cache->get('key1')); + self::assertFalse($cache->replace('key1', 5)); + self::assertFalse($cache->delete('key1')); + self::assertFalse($cache->flushAll()); + self::assertFalse($cache->flush()); + self::assertEquals([], $cache->stats()); + } + + /** + * @expectedException \phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException + */ + public function testInvalidCacheHost() + { + $db = $GLOBALS['CONFIG']['cache']['memcached']; + unset($db['host']); + + $cache = new MemCached($db); + } + + /** + * @expectedException \phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException + */ + public function testInvalidCachePort() + { + $db = $GLOBALS['CONFIG']['cache']['memcached']; + unset($db['port']); + + $cache = new MemCached($db); + } +} diff --git a/tests/DataStorage/Cache/Connection/NullCacheTest.php b/tests/DataStorage/Cache/Connection/NullCacheTest.php index 7b2851615..c0509337b 100644 --- a/tests/DataStorage/Cache/Connection/NullCacheTest.php +++ b/tests/DataStorage/Cache/Connection/NullCacheTest.php @@ -14,14 +14,22 @@ namespace phpOMS\tests\DataStorage\Cache\Connection; use phpOMS\DataStorage\Cache\Connection\NullCache; +use phpOMS\DataStorage\Cache\CacheType; class NullCacheTest extends \PHPUnit\Framework\TestCase { public function testCache() { $cache = new NullCache(); + $cache->connect([]); + + self::assertEquals('', $cache->getPrefix()); + self::assertEquals(CacheType::UNDEFINED, $cache->getType()); self::assertTrue($cache->add(1, 1)); + + $cache->set(1, 1); self::assertEquals(null, $cache->get(1)); + self::assertTrue($cache->delete(1)); self::assertTrue($cache->flush(1)); self::assertTrue($cache->flushAll()); diff --git a/tests/DataStorage/Cache/Connection/RedisCacheTest.php b/tests/DataStorage/Cache/Connection/RedisCacheTest.php index e69de29bb..aa30e3275 100644 --- a/tests/DataStorage/Cache/Connection/RedisCacheTest.php +++ b/tests/DataStorage/Cache/Connection/RedisCacheTest.php @@ -0,0 +1,153 @@ +getPrefix()); + self::assertEquals(CacheType::REDIS, $cache->getType()); + self::assertTrue($cache->flushAll()); + self::assertTrue($cache->flush()); + self::assertEquals(0, $cache->getThreshold()); + self::assertEquals(null, $cache->get('test')); + } + + public function testConnect() + { + $cache = new RedisCache($GLOBALS['CONFIG']['cache']['redis']); + + self::assertEquals(CacheStatus::OK, $cache->getStatus()); + self::assertEquals($GLOBALS['CONFIG']['cache']['redis']['db'], $cache->getCache()); + self::assertEquals($GLOBALS['CONFIG']['cache']['redis']['host'], $cache->getHost()); + self::assertEquals((int) $GLOBALS['CONFIG']['cache']['redis']['port'], $cache->getPort()); + } + + public function testGetSet() + { + $cache = new RedisCache($GLOBALS['CONFIG']['cache']['redis']); + + $cache->flushAll(); + + $cache->set('key1', 'testVal'); // 1 + self::assertEquals('testVal', $cache->get('key1')); + + self::assertTrue($cache->add('addKey', 'testValAdd')); // 2 + self::assertFalse($cache->add('addKey', 'testValAdd2')); + self::assertEquals('testValAdd', $cache->get('addKey')); + + $cache->set('key2', false); // 3 + self::assertEquals(false, $cache->get('key2')); + + $cache->set('key3', null); // 4 + self::assertEquals(null, $cache->get('key3')); + + $cache->set('key4', 4); // 5 + self::assertEquals(4, $cache->get('key4')); + + $cache->set('key5', 5.12); // 6 + self::assertEquals(5.12, $cache->get('key5')); + + $cache->set('key6', ['asdf', 1, true, 2.3]); // 7 + self::assertEquals(json_encode(['asdf', 1, true, 2.3]), $cache->get('key6')); + + self::assertTrue($cache->replace('key4', 5)); + self::assertFalse($cache->replace('keyInvalid', 5)); + self::assertEquals(5, $cache->get('key4')); + + self::assertTrue($cache->delete('key4')); // 6 + self::assertFalse($cache->delete('keyInvalid')); + self::assertEquals(null, $cache->get('key4')); + + self::assertArraySubset( + [ + 'status' => CacheStatus::OK, + 'count' => 6, + ], + $cache->stats() + ); + + self::assertTrue($cache->flushAll()); + self::assertTrue($cache->flush()); + self::assertEquals(null, $cache->get('key5')); + + $cache->flushAll(); + + self::assertArraySubset( + [ + 'status' => CacheStatus::OK, + 'count' => 0, + ], + $cache->stats() + ); + } + + public function testBadCacheStatus() + { + $cache = new RedisCache($GLOBALS['CONFIG']['cache']['redis']); + $cache->flushAll(); + + TestUtils::setMember($cache, 'status', CacheStatus::FAILURE); + + $cache->set('key1', 'testVal'); + self::assertFalse($cache->add('key2', 'testVal2')); + self::assertEquals(null, $cache->get('key1')); + self::assertFalse($cache->replace('key1', 5)); + self::assertFalse($cache->delete('key1')); + self::assertFalse($cache->flushAll()); + self::assertFalse($cache->flush()); + self::assertEquals([], $cache->stats()); + } + + /** + * @expectedException \phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException + */ + public function testInvalidCacheHost() + { + $db = $GLOBALS['CONFIG']['cache']['redis']; + unset($db['host']); + + $cache = new RedisCache($db); + } + + /** + * @expectedException \phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException + */ + public function testInvalidCachePort() + { + $db = $GLOBALS['CONFIG']['cache']['redis']; + unset($db['port']); + + $cache = new RedisCache($db); + } + + /** + * @expectedException \phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException + */ + public function testInvalidCacheDatabase() + { + $db = $GLOBALS['CONFIG']['cache']['redis']; + unset($db['db']); + + $cache = new RedisCache($db); + } +} diff --git a/tests/DataStorage/Cache/Connection/WinCacheTest.php b/tests/DataStorage/Cache/Connection/WinCacheTest.php deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/DataStorage/Cache/Exception/InvalidConnectionConfigExceptionTest.php b/tests/DataStorage/Cache/Exception/InvalidConnectionConfigExceptionTest.php new file mode 100644 index 000000000..36ead6da9 --- /dev/null +++ b/tests/DataStorage/Cache/Exception/InvalidConnectionConfigExceptionTest.php @@ -0,0 +1,24 @@ +getHost()); self::assertEquals((int) $GLOBALS['CONFIG']['db']['core']['masters']['admin']['port'], $mysql->getPort()); self::assertInstanceOf('\phpOMS\DataStorage\Database\Query\Grammar\MysqlGrammar', $mysql->getGrammar()); - } /** diff --git a/tests/Utils/RnG/FileTest.php b/tests/Utils/RnG/FileTest.php index e4842be3a..444839ff7 100644 --- a/tests/Utils/RnG/FileTest.php +++ b/tests/Utils/RnG/FileTest.php @@ -19,6 +19,6 @@ class FileTest extends \PHPUnit\Framework\TestCase { public function testRnGExtension() { - self::assertRegExp('/^[a-z]{2,5}$/', File::generateExtension()); + self::assertRegExp('/^[a-z0-9]{1,5}$/', File::generateExtension()); } } diff --git a/tests/Utils/RnG/LinearCongruentialGeneratorTest.php b/tests/Utils/RnG/LinearCongruentialGeneratorTest.php index b7eb9d724..067d74d1b 100644 --- a/tests/Utils/RnG/LinearCongruentialGeneratorTest.php +++ b/tests/Utils/RnG/LinearCongruentialGeneratorTest.php @@ -26,6 +26,9 @@ class LinearCongruentialGeneratorTest extends \PHPUnit\Framework\TestCase self::assertEquals(654583775, LinearCongruentialGenerator::bsd()); self::assertEquals(1449466924, LinearCongruentialGenerator::bsd()); } + + self::assertEquals(LinearCongruentialGenerator::bsd(1), LinearCongruentialGenerator::bsd(1)); + self::assertNotEquals(LinearCongruentialGenerator::bsd(0), LinearCongruentialGenerator::bsd(1)); } public function testMsRng() @@ -37,5 +40,8 @@ class LinearCongruentialGeneratorTest extends \PHPUnit\Framework\TestCase self::assertEquals(21238, LinearCongruentialGenerator::msvcrt()); self::assertEquals(2437, LinearCongruentialGenerator::msvcrt()); } + + self::assertEquals(LinearCongruentialGenerator::msvcrt(1), LinearCongruentialGenerator::msvcrt(1)); + self::assertNotEquals(LinearCongruentialGenerator::msvcrt(0), LinearCongruentialGenerator::msvcrt(1)); } }