Implement cache and unit tests for cache

This commit is contained in:
Dennis Eichhorn 2018-10-05 20:49:02 +02:00
parent 527d6521ac
commit 9eecd70088
26 changed files with 747 additions and 250 deletions

View File

@ -4,6 +4,8 @@ php:
- nightly - nightly
services: services:
- mysql - mysql
- redis
- memcached
before_script: before_script:
- pecl install ast - pecl install ast
- composer install - composer install

View File

@ -28,8 +28,8 @@ use phpOMS\Stdlib\Base\Enum;
*/ */
abstract class CacheStatus extends Enum abstract class CacheStatus extends Enum
{ {
public const ACTIVE = 0; public const OK = 0;
public const INACTIVE = 1; public const FAILURE = 1;
public const ERROR = 2; public const READONLY = 2;
public const UNDEFINED = 3; public const CLOSED = 3;
} }

View File

@ -31,6 +31,5 @@ abstract class CacheType extends Enum
public const FILE = 'file'; public const FILE = 'file';
public const MEMCACHED = 'mem'; public const MEMCACHED = 'mem';
public const REDIS = 'redis'; public const REDIS = 'redis';
public const WINCACHE = 'win';
public const UNDEFINED = 'na'; public const UNDEFINED = 'na';
} }

View File

@ -73,7 +73,7 @@ abstract class ConnectionAbstract implements ConnectionInterface
* @var int * @var int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $status = CacheStatus::INACTIVE; protected $status = CacheStatus::CLOSED;
/** /**
* {@inheritdoc} * {@inheritdoc}
@ -100,7 +100,7 @@ abstract class ConnectionAbstract implements ConnectionInterface
*/ */
public function getCache() : string 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 public function close() : void
{ {
$this->con = null; $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;
} }
} }

View File

@ -52,17 +52,15 @@ class ConnectionFactory
*/ */
public static function create(array $cacheData) : ConnectionInterface public static function create(array $cacheData) : ConnectionInterface
{ {
switch ($cacheData['type']) { switch ($cacheData['type'] ?? '') {
case CacheType::FILE: case CacheType::FILE:
return new FileCache($cacheData['path']); return new FileCache($cacheData['path'] ?? '');
case CacheType::REDIS: case CacheType::REDIS:
return new RedisCache($cacheData); return new RedisCache($cacheData['data'] ?? []);
case CacheType::MEMCACHED: case CacheType::MEMCACHED:
return new MemCached($cacheData); return new MemCached($cacheData['data'] ?? []);
case CacheType::WINCACHE:
return new WinCache($cacheData);
default: default:
throw new \InvalidArgumentException('Cache "' . $cacheData['type'] . '" is not supported.'); throw new \InvalidArgumentException('Cache "' . ($cacheData['type'] ?? '') . '" is not supported.');
} }
} }
} }

View File

@ -15,9 +15,11 @@ declare(strict_types=1);
namespace phpOMS\DataStorage\Cache\Connection; namespace phpOMS\DataStorage\Cache\Connection;
use phpOMS\DataStorage\Cache\CacheStatus; use phpOMS\DataStorage\Cache\CacheStatus;
use phpOMS\DataStorage\Cache\CacheType;
use phpOMS\Stdlib\Base\Exception\InvalidEnumValue; use phpOMS\Stdlib\Base\Exception\InvalidEnumValue;
use phpOMS\System\File\Local\Directory; use phpOMS\System\File\Local\Directory;
use phpOMS\System\File\Local\File; use phpOMS\System\File\Local\File;
use phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException;
/** /**
* MemCache class. * MemCache class.
@ -31,6 +33,10 @@ use phpOMS\System\File\Local\File;
*/ */
class FileCache extends ConnectionAbstract class FileCache extends ConnectionAbstract
{ {
/**
* {@inheritdoc}
*/
protected $type = CacheType::FILE;
/** /**
* Delimiter for cache meta data * Delimiter for cache meta data
@ -65,12 +71,7 @@ class FileCache extends ConnectionAbstract
*/ */
public function __construct(string $path) public function __construct(string $path)
{ {
if (!Directory::exists($path)) { $this->connect([$path]);
Directory::create($path, 0766, true);
}
$this->status = CacheStatus::ACTIVE;
$this->con = \realpath($path);
} }
/** /**
@ -78,7 +79,19 @@ class FileCache extends ConnectionAbstract
*/ */
public function connect(array $data) : void 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 public function flushAll() : bool
{ {
if ($this->status !== CacheStatus::ACTIVE) { if ($this->status !== CacheStatus::OK) {
return false; return false;
} }
@ -100,11 +113,14 @@ class FileCache extends ConnectionAbstract
*/ */
public function stats() : array public function stats() : array
{ {
$stats = []; if ($this->status !== CacheStatus::OK) {
$stats['status'] = $this->status; return [];
$stats['count'] = Directory::count($this->con); }
$stats['size'] = Directory::size($this->con);
$stats['changed'] = Directory::changed($this->con); $stats = [];
$stats['status'] = $this->status;
$stats['count'] = Directory::count($this->con);
$stats['size'] = Directory::size($this->con);
return $stats; return $stats;
} }
@ -122,7 +138,7 @@ class FileCache extends ConnectionAbstract
*/ */
public function set($key, $value, int $expire = -1) : void public function set($key, $value, int $expire = -1) : void
{ {
if ($this->status !== CacheStatus::ACTIVE) { if ($this->status !== CacheStatus::OK) {
return; return;
} }
@ -136,7 +152,7 @@ class FileCache extends ConnectionAbstract
*/ */
public function add($key, $value, int $expire = -1) : bool public function add($key, $value, int $expire = -1) : bool
{ {
if ($this->status !== CacheStatus::ACTIVE) { if ($this->status !== CacheStatus::OK) {
return false; return false;
} }
@ -252,7 +268,7 @@ class FileCache extends ConnectionAbstract
*/ */
public function get($key, int $expire = -1) public function get($key, int $expire = -1)
{ {
if ($this->status !== CacheStatus::ACTIVE) { if ($this->status !== CacheStatus::OK) {
return null; return null;
} }
@ -290,7 +306,7 @@ class FileCache extends ConnectionAbstract
return null; 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 * @since 1.0.0
*/ */
private function parseValue(int $type, string $raw, int $expireEnd) private function reverseValue(int $type, string $raw, int $expireEnd)
{ {
$value = null; $value = null;
@ -350,7 +366,7 @@ class FileCache extends ConnectionAbstract
*/ */
public function delete($key, int $expire = -1) : bool public function delete($key, int $expire = -1) : bool
{ {
if ($this->status !== CacheStatus::ACTIVE) { if ($this->status !== CacheStatus::OK) {
return false; return false;
} }
@ -401,7 +417,7 @@ class FileCache extends ConnectionAbstract
*/ */
public function flush(int $expire = 0) : bool public function flush(int $expire = 0) : bool
{ {
if ($this->status !== CacheStatus::ACTIVE) { if ($this->status !== CacheStatus::OK) {
return false; return false;
} }
@ -427,7 +443,7 @@ class FileCache extends ConnectionAbstract
*/ */
public function replace($key, $value, int $expire = -1) : bool public function replace($key, $value, int $expire = -1) : bool
{ {
if ($this->status !== CacheStatus::ACTIVE) { if ($this->status !== CacheStatus::OK) {
return false; return false;
} }

View File

@ -14,6 +14,10 @@ declare(strict_types=1);
namespace phpOMS\DataStorage\Cache\Connection; namespace phpOMS\DataStorage\Cache\Connection;
use phpOMS\DataStorage\Cache\CacheStatus;
use phpOMS\DataStorage\Cache\CacheType;
use phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException;
/** /**
* Memcache class. * Memcache class.
* *
@ -24,14 +28,10 @@ namespace phpOMS\DataStorage\Cache\Connection;
*/ */
class MemCached extends ConnectionAbstract class MemCached extends ConnectionAbstract
{ {
/** /**
* Memcache instance. * {@inheritdoc}
*
* @var \Memcache
* @since 1.0.0
*/ */
private $memc = null; protected $type = CacheType::MEMCACHED;
/** /**
* Only cache if data is larger than threshold (0-100). * Only cache if data is larger than threshold (0-100).
@ -39,7 +39,7 @@ class MemCached extends ConnectionAbstract
* @var int * @var int
* @since 1.0.0 * @since 1.0.0
*/ */
private $threshold = 10; private $threshold = 0;
/** /**
* Constructor. * Constructor.
@ -50,7 +50,8 @@ class MemCached extends ConnectionAbstract
*/ */
public function __construct(array $data) 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 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'])) {
* Adding server to server pool. $this->status = CacheStatus::FAILURE;
* throw new InvalidConnectionConfigException((string) \json_encode($this->dbdata));
* @param mixed $data Server data array }
*
* @return void $this->con->addServer($this->dbdata['host'], $this->dbdata['port']);
*
* @since 1.0.0 $this->status = CacheStatus::OK;
*/
public function addServer($data)
{
$this->memc->addServer($data['host'], $data['port'], $data['timeout']);
} }
/** /**
@ -80,7 +76,9 @@ class MemCached extends ConnectionAbstract
*/ */
public function set($key, $value, int $expire = -1) : void 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 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) 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 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 public function flush(int $expire = 0) : bool
{ {
$this->memc->flush(); if ($this->status !== CacheStatus::OK) {
return false;
}
$this->con->flush();
return true; return true;
} }
@ -122,7 +140,11 @@ class MemCached extends ConnectionAbstract
*/ */
public function flushAll() : bool public function flushAll() : bool
{ {
$this->memc->flush(); if ($this->status !== CacheStatus::OK) {
return false;
}
$this->con->flush();
return true; return true;
} }
@ -132,7 +154,13 @@ class MemCached extends ConnectionAbstract
*/ */
public function replace($key, $value, int $expire = -1) : bool 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 public function stats() : array
{ {
/** @noinspection PhpMethodOrClassCallIsNotCaseSensitiveInspection */ if ($this->status !== CacheStatus::OK) {
return $this->memc->getExtendedStats(); 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; return $this->threshold;
} }
/**
* {@inheritdoc}
*/
public function setStatus(int $status) /* : void */
{
$this->status = $status;
}
/** /**
* Destructor. * Destructor.
* *
@ -179,9 +210,10 @@ class MemCached extends ConnectionAbstract
*/ */
public function close() : void public function close() : void
{ {
if ($this->memc !== null) { if ($this->con !== null) {
$this->memc->close(); $this->con->quit();
$this->memc = null;
} }
parent::close();
} }
} }

View File

@ -102,11 +102,4 @@ class NullCache extends ConnectionAbstract
{ {
return 0; return 0;
} }
/**
* {@inheritdoc}
*/
public function setStatus(int $status) : void
{
}
} }

View File

@ -15,6 +15,8 @@ declare(strict_types=1);
namespace phpOMS\DataStorage\Cache\Connection; namespace phpOMS\DataStorage\Cache\Connection;
use phpOMS\DataStorage\Cache\CacheStatus; use phpOMS\DataStorage\Cache\CacheStatus;
use phpOMS\DataStorage\Cache\CacheType;
use phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException;
/** /**
* RedisCache class. * RedisCache class.
@ -28,6 +30,10 @@ use phpOMS\DataStorage\Cache\CacheStatus;
*/ */
class RedisCache extends ConnectionAbstract class RedisCache extends ConnectionAbstract
{ {
/**
* {@inheritdoc}
*/
protected $type = CacheType::REDIS;
/** /**
* Constructor * Constructor
@ -38,6 +44,8 @@ class RedisCache extends ConnectionAbstract
*/ */
public function __construct(array $data) 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 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 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 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) 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 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 public function flush(int $expire = 0) : bool
{ {
// TODO: Implement flush() method. if ($this->status !== CacheStatus::OK) {
return false;
}
$this->con->flushDb();
return true; return true;
} }
@ -95,7 +163,11 @@ class RedisCache extends ConnectionAbstract
*/ */
public function flushAll() : bool public function flushAll() : bool
{ {
// TODO: Implement flush() method. if ($this->status !== CacheStatus::OK) {
return false;
}
$this->con->flushDb();
return true; return true;
} }
@ -105,7 +177,19 @@ class RedisCache extends ConnectionAbstract
*/ */
public function replace($key, $value, int $expire = -1) : bool 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 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 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();
} }
} }

View File

@ -1,133 +0,0 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package phpOMS\DataStorage\Cache\Connection
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace phpOMS\DataStorage\Cache\Connection;
use phpOMS\DataStorage\Cache\CacheStatus;
/**
* WinCache class.
*
* PHP Version 5.6
*
* @package phpOMS\DataStorage\Cache\Connection
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
class WinCache extends ConnectionAbstract
{
/**
* Constructor
*
* @param array $data Cache data
*
* @since 1.0.0
*/
public function __construct(array $data)
{
}
/**
* {@inheritdoc}
*/
public function connect(array $data) : void
{
$this->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.
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package phpOMS\DataStorage\Cache\Exception
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace phpOMS\DataStorage\Cache\Exception;
/**
* Permission exception class.
*
* @package phpOMS\DataStorage\Cache\Exception
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
final class InvalidConnectionConfigException extends \InvalidArgumentException
{
/**
* Constructor.
*
* @param string $message Exception message
* @param int $code Exception code
* @param \Exception $previous Previous exception
*
* @since 1.0.0
*/
public function __construct(string $message = '', int $code = 0, \Exception $previous = null)
{
parent::__construct('Missing config value for "' . $message . '".', $code, $previous);
}
}

View File

@ -419,7 +419,11 @@ final class Directory extends FileAbstract implements DirectoryInterface
return false; return false;
} }
\mkdir($path, $permission, $recursive); try {
\mkdir($path, $permission, $recursive);
} catch (\Throwable $t) {
return false;
}
return true; return true;
} }

View File

@ -81,6 +81,17 @@ $CONFIG = [
], ],
], ],
], ],
'cache' => [
'redis' => [
'db' => 1,
'host' => '127.0.0.1',
'port' => 6379,
],
'memcached' => [
'host' => '127.0.0.1',
'port' => 11211,
],
],
'log' => [ 'log' => [
'file' => [ 'file' => [
'path' => __DIR__ . '/Logs', 'path' => __DIR__ . '/Logs',

View File

@ -20,9 +20,9 @@ class CacheStatusTest extends \PHPUnit\Framework\TestCase
public function testEnums() public function testEnums()
{ {
self::assertEquals(4, \count(CacheStatus::getConstants())); self::assertEquals(4, \count(CacheStatus::getConstants()));
self::assertEquals(0, CacheStatus::ACTIVE); self::assertEquals(0, CacheStatus::OK);
self::assertEquals(1, CacheStatus::INACTIVE); self::assertEquals(1, CacheStatus::FAILURE);
self::assertEquals(2, CacheStatus::ERROR); self::assertEquals(2, CacheStatus::READONLY);
self::assertEquals(3, CacheStatus::UNDEFINED); self::assertEquals(3, CacheStatus::CLOSED);
} }
} }

View File

@ -19,11 +19,10 @@ class CacheTypeTest extends \PHPUnit\Framework\TestCase
{ {
public function testEnums() public function testEnums()
{ {
self::assertEquals(5, \count(CacheType::getConstants())); self::assertEquals(4, \count(CacheType::getConstants()));
self::assertEquals('file', CacheType::FILE); self::assertEquals('file', CacheType::FILE);
self::assertEquals('mem', CacheType::MEMCACHED); self::assertEquals('mem', CacheType::MEMCACHED);
self::assertEquals('redis', CacheType::REDIS); self::assertEquals('redis', CacheType::REDIS);
self::assertEquals('win', CacheType::WINCACHE);
self::assertEquals('na', CacheType::UNDEFINED); self::assertEquals('na', CacheType::UNDEFINED);
} }
} }

View File

@ -14,6 +14,7 @@
namespace phpOMS\tests\DataStorage\Cache\Connection; namespace phpOMS\tests\DataStorage\Cache\Connection;
use phpOMS\DataStorage\Cache\Connection\ConnectionFactory; use phpOMS\DataStorage\Cache\Connection\ConnectionFactory;
use phpOMS\DataStorage\Cache\CacheType;
class ConnectionFactoryTest extends \PHPUnit\Framework\TestCase class ConnectionFactoryTest extends \PHPUnit\Framework\TestCase
{ {
@ -21,7 +22,17 @@ class ConnectionFactoryTest extends \PHPUnit\Framework\TestCase
{ {
self::assertInstanceOf( self::assertInstanceOf(
\phpOMS\DataStorage\Cache\Connection\FileCache::class, \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']])
); );
} }

View File

@ -14,6 +14,9 @@
namespace phpOMS\tests\DataStorage\Cache\Connection; namespace phpOMS\tests\DataStorage\Cache\Connection;
use phpOMS\DataStorage\Cache\Connection\FileCache; 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 class FileCacheTest extends \PHPUnit\Framework\TestCase
{ {
@ -25,6 +28,8 @@ class FileCacheTest extends \PHPUnit\Framework\TestCase
$cache = new FileCache(__DIR__ . '/Cache'); $cache = new FileCache(__DIR__ . '/Cache');
self::assertEquals('', $cache->getPrefix());
self::assertEquals(CacheType::FILE, $cache->getType());
self::assertTrue(\is_dir(__DIR__ . '/Cache')); self::assertTrue(\is_dir(__DIR__ . '/Cache'));
self::assertTrue($cache->flushAll()); self::assertTrue($cache->flushAll());
self::assertEquals(50, $cache->getThreshold()); 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() public function testGetSet()
{ {
if (\file_exists(__DIR__ . '/Cache')) { if (\file_exists(__DIR__ . '/Cache')) {
@ -43,35 +63,95 @@ class FileCacheTest extends \PHPUnit\Framework\TestCase
$cache = new FileCache(__DIR__ . '/Cache'); $cache = new FileCache(__DIR__ . '/Cache');
$cache->set('key1', 'testVal'); $cache->flushAll();
$cache->set('key1', 'testVal'); // 1
self::assertEquals('testVal', $cache->get('key1')); 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')); self::assertEquals(false, $cache->get('key2'));
$cache->set('key3', null); $cache->set('key3', null); // 4
self::assertEquals(null, $cache->get('key3')); self::assertEquals(null, $cache->get('key3'));
$cache->set('key4', 4); $cache->set('key4', 4); // 5
self::assertEquals(4, $cache->get('key4')); self::assertEquals(4, $cache->get('key4'));
$cache->set('key5', 5.12); $cache->set('key5', 5.12); // 6
self::assertEquals(5.12, $cache->get('key5')); 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')); 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')); 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')); 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')); self::assertEquals(null, $cache->get('key5'));
$cache->flushAll();
self::assertEquals(
[
'status' => CacheStatus::OK,
'count' => 0,
'size' => 0,
],
$cache->stats()
);
if (\file_exists(__DIR__ . '/Cache')) { if (\file_exists(__DIR__ . '/Cache')) {
\rmdir(__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^$:?><');
}
} }

View File

@ -0,0 +1,140 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package tests
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
namespace phpOMS\tests\DataStorage\Cache\Connection;
use phpOMS\DataStorage\Cache\Connection\MemCached;
use phpOMS\DataStorage\Cache\CacheStatus;
use phpOMS\DataStorage\Cache\CacheType;
use phpOMS\Utils\TestUtils;
class MemCachedTest extends \PHPUnit\Framework\TestCase
{
public function testDefault()
{
$cache = new MemCached($GLOBALS['CONFIG']['cache']['memcached']);
self::assertEquals('', $cache->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);
}
}

View File

@ -14,14 +14,22 @@
namespace phpOMS\tests\DataStorage\Cache\Connection; namespace phpOMS\tests\DataStorage\Cache\Connection;
use phpOMS\DataStorage\Cache\Connection\NullCache; use phpOMS\DataStorage\Cache\Connection\NullCache;
use phpOMS\DataStorage\Cache\CacheType;
class NullCacheTest extends \PHPUnit\Framework\TestCase class NullCacheTest extends \PHPUnit\Framework\TestCase
{ {
public function testCache() public function testCache()
{ {
$cache = new NullCache(); $cache = new NullCache();
$cache->connect([]);
self::assertEquals('', $cache->getPrefix());
self::assertEquals(CacheType::UNDEFINED, $cache->getType());
self::assertTrue($cache->add(1, 1)); self::assertTrue($cache->add(1, 1));
$cache->set(1, 1);
self::assertEquals(null, $cache->get(1)); self::assertEquals(null, $cache->get(1));
self::assertTrue($cache->delete(1)); self::assertTrue($cache->delete(1));
self::assertTrue($cache->flush(1)); self::assertTrue($cache->flush(1));
self::assertTrue($cache->flushAll()); self::assertTrue($cache->flushAll());

View File

@ -0,0 +1,153 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package tests
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
namespace phpOMS\tests\DataStorage\Cache\Connection;
use phpOMS\DataStorage\Cache\Connection\RedisCache;
use phpOMS\DataStorage\Cache\CacheStatus;
use phpOMS\DataStorage\Cache\CacheType;
use phpOMS\Utils\TestUtils;
class RedisCacheTest extends \PHPUnit\Framework\TestCase
{
public function testDefault()
{
$cache = new RedisCache($GLOBALS['CONFIG']['cache']['redis']);
self::assertEquals('', $cache->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);
}
}

View File

@ -0,0 +1,24 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package tests
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
namespace phpOMS\tests\DataStorage\Cache\Exception;
use phpOMS\DataStorage\Cache\Exception\InvalidConnectionConfigException;
class InvalidConnectionConfigExceptionTest extends \PHPUnit\Framework\TestCase
{
public function testException()
{
self::assertInstanceOf(\InvalidArgumentException::class, new InvalidConnectionConfigException(''));
}
}

View File

@ -27,7 +27,6 @@ class MysqlConnectionTest extends \PHPUnit\Framework\TestCase
self::assertEquals($GLOBALS['CONFIG']['db']['core']['masters']['admin']['host'], $mysql->getHost()); self::assertEquals($GLOBALS['CONFIG']['db']['core']['masters']['admin']['host'], $mysql->getHost());
self::assertEquals((int) $GLOBALS['CONFIG']['db']['core']['masters']['admin']['port'], $mysql->getPort()); self::assertEquals((int) $GLOBALS['CONFIG']['db']['core']['masters']['admin']['port'], $mysql->getPort());
self::assertInstanceOf('\phpOMS\DataStorage\Database\Query\Grammar\MysqlGrammar', $mysql->getGrammar()); self::assertInstanceOf('\phpOMS\DataStorage\Database\Query\Grammar\MysqlGrammar', $mysql->getGrammar());
} }
/** /**

View File

@ -19,6 +19,6 @@ class FileTest extends \PHPUnit\Framework\TestCase
{ {
public function testRnGExtension() public function testRnGExtension()
{ {
self::assertRegExp('/^[a-z]{2,5}$/', File::generateExtension()); self::assertRegExp('/^[a-z0-9]{1,5}$/', File::generateExtension());
} }
} }

View File

@ -26,6 +26,9 @@ class LinearCongruentialGeneratorTest extends \PHPUnit\Framework\TestCase
self::assertEquals(654583775, LinearCongruentialGenerator::bsd()); self::assertEquals(654583775, LinearCongruentialGenerator::bsd());
self::assertEquals(1449466924, 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() public function testMsRng()
@ -37,5 +40,8 @@ class LinearCongruentialGeneratorTest extends \PHPUnit\Framework\TestCase
self::assertEquals(21238, LinearCongruentialGenerator::msvcrt()); self::assertEquals(21238, LinearCongruentialGenerator::msvcrt());
self::assertEquals(2437, LinearCongruentialGenerator::msvcrt()); self::assertEquals(2437, LinearCongruentialGenerator::msvcrt());
} }
self::assertEquals(LinearCongruentialGenerator::msvcrt(1), LinearCongruentialGenerator::msvcrt(1));
self::assertNotEquals(LinearCongruentialGenerator::msvcrt(0), LinearCongruentialGenerator::msvcrt(1));
} }
} }