Remove Memcache, improve test coverage, fix bugs
Gitea - aviat/banker/master There was a failure building this commit Details

This commit is contained in:
Timothy Warren 2018-11-15 16:37:50 -05:00
parent edea686f4c
commit 65fd726e2c
18 changed files with 274 additions and 424 deletions

5
CHANGELOG.md Normal file
View File

@ -0,0 +1,5 @@
# Changelog
## 2.0.0
* Removed `Memcache` integration, as the extension does not seem to be maintained
* Increased required PHP version to 7.1

View File

@ -8,7 +8,6 @@ backends
## Cache Backends
* Apcu
* Memcache
* Memcached
* Redis
* Null - no persistence
@ -46,7 +45,7 @@ structure is like so:
```php
<?php
$config = [
'driver' => 'null', // null, apcu, redis, memcache, memcached
'driver' => 'null', // null, apcu, redis, memcached
'connection' => [
// Optional (For some drivers):
// driver setup, see below for the structure for each
@ -62,7 +61,7 @@ $config = [
Below are the connection arrays for each backend:
Memcache / Memcached:
Memcached:
```php
<?php
$config['connection'] = [

View File

@ -3,12 +3,12 @@
*
* A Caching library implementing psr/cache
*
* PHP version 7.0
* PHP version 7.1
*
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 - 2017 Timothy J. Warren
* @copyright 2016 - 2018 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.1
* @version 2.0.0
* @link https://git.timshomepage.net/timw4mail/banker
*/

View File

@ -5,7 +5,6 @@
"keywords": [
"cache",
"redis",
"memcache",
"memcached",
"psr-6",
"psr6"
@ -24,6 +23,8 @@
}
},
"require": {
"php": "^7.1",
"ext-json": "*",
"predis/predis": "^1.1",
"psr/log": "^1.0",
"psr/cache": "^1.0.1"
@ -42,7 +43,7 @@
},
"suggest": {
"monolog/monolog": "A good standard logging library",
"ext-memcache": "Required for Memcache backend",
"ext-apcu": "Required for apcu driver",
"ext-memcached": "Required for Memcached backend",
"ext-phpiredis": "Improves speed of Redis driver"
},

View File

@ -25,13 +25,6 @@ abstract class AbstractDriver implements DriverInterface, LoggerAwareInterface {
use LoggerTrait;
/**
* The object encapsulating the connection to the cache backend
*
* @var mixed
*/
protected $conn;
/**
* Data to be stored later
*
@ -51,4 +44,25 @@ abstract class AbstractDriver implements DriverInterface, LoggerAwareInterface {
* Common destructor
*/
abstract public function __destruct();
/**
* Retrieve a set of values by their cache key
*
* @param string[] $keys
* @return array
*/
public function getMultiple(array $keys = []): array
{
$output = [];
foreach ($keys as $key)
{
if ($this->exists($key))
{
$output[$key] = $this->get($key);
}
}
return $output;
}
}

View File

@ -29,7 +29,7 @@ use Aviat\Banker\Exception\CacheException;
* Memcached cache backend
*/
class ApcuDriver extends AbstractDriver {
/**
* Constructor
*
@ -40,7 +40,7 @@ class ApcuDriver extends AbstractDriver {
{
// noop
}
/**
* Destructor
*/
@ -80,14 +80,7 @@ class ApcuDriver extends AbstractDriver {
public function getMultiple(array $keys = []): array
{
$status = FALSE;
$output = apcu_fetch($keys, $status);
if ($status === FALSE || !is_array($output))
{
return [];
}
return $output;
return apcu_fetch($keys, $status);
}
/**
@ -120,7 +113,7 @@ class ApcuDriver extends AbstractDriver {
*/
public function delete(string $key): bool
{
return apcu_delete($key);
return (bool) apcu_delete($key);
}
/**
@ -131,7 +124,7 @@ class ApcuDriver extends AbstractDriver {
*/
public function deleteMultiple(array $keys = []): bool
{
return apcu_delete($keys);
return (bool) apcu_delete($keys);
}
/**
@ -159,7 +152,7 @@ class ApcuDriver extends AbstractDriver {
return apcu_store($key, $value, $expires);
}
$this->getLogger()->warn("Tried to set expiration on a key that does not exist");
$this->getLogger()->log('warning', 'Tried to set expiration on a key that does not exist');
return FALSE;
}

View File

@ -1,162 +0,0 @@
<?php declare(strict_types=1);
/**
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 7.0
*
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.1
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Driver;
use Aviat\Banker\Exception\CacheException;
use Memcache;
/**
* Redis cache backend
*/
class MemcacheDriver extends AbstractDriver {
/**
* Driver for PHP Memcache extension
*
* @param array $config
* @param array $options
* @throws CacheException
*/
public function __construct(array $config = [], array $options = [])
{
if ( ! class_exists('Memcache'))
{
throw new CacheException('Memcache driver requires the PHP memcache extension');
}
$this->conn = new Memcache();
$method = ($config['persistent'] === TRUE) ? 'pconnect' : 'connect';
$this->conn->$method($config['host'], (int) $config['port']);
}
/**
* Disconnect from memcached server
*/
public function __destruct()
{
$this->conn->close();
}
/**
* See if a key currently exists in the cache
*
* @param string $key
* @return bool
*/
public function exists(string $key): bool
{
return $this->conn->get($key) !== FALSE;
}
/**
* Get the value for the selected cache key
*
* @param string $key
* @return mixed
*/
public function get(string $key)
{
return $this->conn->get($key);
}
/**
* Retrieve a set of values by their cache key
*
* @param string[] $keys
* @return array
*/
public function getMultiple(array $keys = []): array
{
return $this->conn->get($keys);
}
/**
* Set a cached value
*
* @param string $key
* @param mixed $value
* @param int $expires
* @return DriverInterface
*/
public function set(string $key, $value, int $expires = 0): DriverInterface
{
if ($this->exists($key))
{
$this->conn->replace($key, $value, 0, $expires);
}
else
{
$this->conn->set($key, $value, 0, $expires);
}
return $this;
}
/**
* Remove an item from the cache
*
* @param string $key
* @return boolean
*/
public function delete(string $key): bool
{
return $this->conn->delete($key);
}
/**
* Remove multiple items from the cache
*
* @param string[] $keys
* @return boolean
*/
public function deleteMultiple(array $keys = []): bool
{
// Iteratively delete each item, using a boolean
// 'and' operation to return false if any deletion fails
return \array_reduce($keys, function($prev, $key) {
return $prev && $this->conn->delete($key);
}, TRUE);
}
/**
* Empty the cache
*
* @return boolean
*/
public function flush(): bool
{
return $this->conn->flush();
}
/**
* Set the specified key to expire at the given time
*
* @param string $key
* @param int $expires
* @return boolean
*/
public function expiresAt(string $key, int $expires): bool
{
$value = $this->get($key);
$timediff = $expires - time();
$this->set($key, $value, $timediff);
return TRUE;
}
}

View File

@ -28,18 +28,19 @@ class MemcachedDriver extends AbstractDriver {
/**
* Driver for PHP Memcache extension
*
* @codeCoverageIgnore
* @param array $config
* @param array $options
* @throws CacheException
*/
public function __construct(
array $config = ['host' => '127.0.0.1', 'port' => '11211'],
array $config = ['host' => '127.0.0.1', 'port' => '11211'],
array $options = []
)
{
if ( ! class_exists('Memcached'))
{
throw new CacheException("Memcached driver requires memcached extensions");
throw new CacheException('Memcached driver requires memcached extension');
}
try
@ -133,7 +134,7 @@ class MemcachedDriver extends AbstractDriver {
*/
public function delete(string $key): bool
{
return $this->conn->delete($key);
return (bool) $this->conn->delete($key);
}
/**
@ -144,7 +145,8 @@ class MemcachedDriver extends AbstractDriver {
*/
public function deleteMultiple(array $keys = []): bool
{
return $this->conn->deleteMulti($keys);
$deleted = $this->conn->deleteMulti($keys);
return ($keys <=> $deleted) === 0;
}
/**
@ -171,7 +173,7 @@ class MemcachedDriver extends AbstractDriver {
return $this->conn->touch($key, $expires);
}
$this->getLogger()->warn("Tried to set expiration on a key that does not exist");
$this->getLogger()->log('warning','Tried to set expiration on a key that does not exist');
return FALSE;
}

View File

@ -67,29 +67,11 @@ class NullDriver extends AbstractDriver {
*/
public function get(string $key)
{
return ($this->exists($key))
return $this->exists($key)
? $this->store[$key]
: NULL;
}
/**
* Retrieve a set of values by their cache key
*
* @param string[] $keys
* @return array
*/
public function getMultiple(array $keys = []): array
{
$output = [];
foreach($keys as $key)
{
$output[$key] = $this->get($key);
}
return $output;
}
/**
* Set a cached value
*
@ -155,6 +137,6 @@ class NullDriver extends AbstractDriver {
public function expiresAt(string $key, int $expires): bool
{
//noop
return TRUE;
return array_key_exists($key, $this->store);
}
}

View File

@ -15,7 +15,6 @@
*/
namespace Aviat\Banker\Driver;
use Aviat\Banker\Exception\CacheException;
use Predis\Client;
/**
@ -33,6 +32,7 @@ class RedisDriver extends AbstractDriver {
/**
* RedisDriver constructor.
*
* @codeCoverageIgnore
* @param array $config
* @param array $options - Predis library connection options
* @throws CacheException
@ -78,24 +78,6 @@ class RedisDriver extends AbstractDriver {
return unserialize($raw);
}
/**
* Retrieve a set of values by their cache key
*
* @param string[] $keys
* @return array
*/
public function getMultiple(array $keys = []): array
{
$output = [];
foreach($keys as $key)
{
$output[$key] = $this->get($key);
}
return $output;
}
/**
* Set a cached value
*
@ -110,7 +92,7 @@ class RedisDriver extends AbstractDriver {
if ($expires !== 0)
{
$this->conn->set($key, $value, "EX", $expires);
$this->conn->set($key, $value, 'EX', $expires);
}
else
{
@ -140,7 +122,7 @@ class RedisDriver extends AbstractDriver {
public function deleteMultiple(array $keys = []): bool
{
$res = $this->conn->del(...$keys);
return $res === count($keys);
return $res === \count($keys);
}
/**

View File

@ -101,7 +101,7 @@ class Item implements CacheItemInterface {
{
if ($this->isHit())
{
return $this->driver->get($this->key);
return $this->value ?? $this->driver->get($this->key);
}
return NULL;
@ -118,7 +118,7 @@ class Item implements CacheItemInterface {
*/
public function isHit(): bool
{
return $this->driver->exists($this->key);
return isset($this->value) || $this->driver->exists($this->key);
}
/**
@ -202,7 +202,8 @@ class Item implements CacheItemInterface {
return $setResult && $expResult;
}
else if ($this->ttl !== NULL && $this->ttl !== 0)
if ($this->ttl !== NULL && $this->ttl !== 0)
{
return (bool) $this->driver->set($this->key, $this->value, $this->ttl);
}

View File

@ -17,13 +17,16 @@ namespace Aviat\Banker;
use Psr\Cache\CacheItemInterface;
use ArrayIterator;
use JsonSerializable;
/**
* Collection of Psr\Cache\CacheItemIterface objects to be returned by getItems
* Collection of Psr\Cache\CacheItemInterface objects to be returned by getItems
*
* @see http://php.net/manual/en/class.arrayiterator.php
* @see http://php.net/manual/en/class.jsonserializable.php
*/
class ItemCollection extends \ArrayIterator implements \JsonSerializable {
class ItemCollection extends ArrayIterator implements JsonSerializable {
/**
* The raw CacheItemInterface objects

View File

@ -35,7 +35,7 @@ trait LoggerTrait {
*
* @return LoggerInterface
*/
protected function getLogger()
protected function getLogger(): LoggerInterface
{
if ($this->logger === NULL)
{
@ -50,7 +50,7 @@ trait LoggerTrait {
* @param LoggerInterface $logger
* @return self
*/
public function setLogger(LoggerInterface $logger)
public function setLogger(LoggerInterface $logger): self
{
$this->logger = $logger;

View File

@ -24,7 +24,7 @@ use Psr\Log\{LoggerAwareInterface, LoggerInterface};
/**
* The main cache manager
*/
class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
final class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
use LoggerTrait;
@ -46,12 +46,13 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
* Set up the cache backend
*
* @param array $config
* @param LoggerInterface $logger
*/
public function __construct(array $config, LoggerInterface $logger = NULL)
public function __construct(array $config, ?LoggerInterface $logger = NULL)
{
$this->driver = $this->loadDriver($config);
if ( ! is_null($logger))
if ($logger !== NULL)
{
$this->setLogger($logger);
}
@ -75,7 +76,7 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
*/
public function getItem($key): CacheItemInterface
{
if ( ! is_string($key))
if ( ! \is_string($key))
{
throw new InvalidArgumentException();
}
@ -86,8 +87,7 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
return $this->deferred[$key];
}
$item = new Item($this->driver, $key);
return $item;
return new Item($this->driver, $key);
}
/**
@ -113,27 +113,18 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
return new ItemCollection([]);
}
// Get the set of items selected
$items = [];
foreach($keys as $key)
{
if ( ! is_string($key))
if ( ! \is_string($key))
{
throw new InvalidArgumentException();
}
}
// Get the set of items selected
$items = [];
$rawItems = $this->driver->getMultiple($keys);
foreach($rawItems as $key => $val)
{
if (array_key_exists($key, $this->deferred))
{
$items[$key] = $this->deferred[$key];
}
else
{
$items[$key] = new Item($this->driver, $key);
}
$items[$key] = array_key_exists($key, $this->deferred)
? $this->deferred[$key]
: new Item($this->driver, $key);
}
return new ItemCollection($items);
@ -156,9 +147,9 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
* @return bool
* True if item exists in the cache, false otherwise.
*/
public function hasItem($key)
public function hasItem($key): bool
{
if ( ! is_string($key))
if ( ! \is_string($key))
{
throw new InvalidArgumentException();
}
@ -198,7 +189,7 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
*/
public function deleteItem($key): bool
{
if ( ! is_string($key))
if ( ! \is_string($key))
{
throw new InvalidArgumentException();
}
@ -207,10 +198,8 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
{
return FALSE;
}
else
{
return $this->driver->delete($key);
}
return $this->driver->delete($key);
}
/**
@ -230,7 +219,7 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
{
foreach ($keys as $key)
{
if ( ! is_string($key))
if ( ! \is_string($key))
{
throw new InvalidArgumentException();
}
@ -264,7 +253,9 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
*/
public function saveDeferred(CacheItemInterface $item): bool
{
$this->deferred[$item->getKey()] = $item;
$key = $item->getKey();
$this->deferred[$key] = $item;
return TRUE;
}
@ -302,11 +293,11 @@ class Pool implements CacheItemPoolInterface, LoggerAwareInterface {
* @param array $driverConfig
* @return DriverInterface
*/
protected function loadDriver(array $driverConfig): DriverInterface
protected function loadDriver(array $driverConfig = []): DriverInterface
{
$driver = ucfirst(strtolower($driverConfig['driver']));
$driver = ucfirst(strtolower($driverConfig['driver'] ?? 'null'));
$class = __NAMESPACE__ . "\\Driver\\${driver}Driver";
$driverConfig['connection'] = $driverConfig['connection'] ?? [];
$driverConfig['options'] = $driverConfig['options'] ?? [];

View File

@ -21,14 +21,15 @@ class DriverTestBase extends TestCase {
protected $driver;
public function tearDown()
public function tearDown(): void
{
$this->driver->__destruct();
}
public function testGetSet()
public function testGetSet(): void
{
$this->driver->set('foo', 'bar');
$this->assertTrue($this->driver->exists('foo'));
$this->assertEquals('bar', $this->driver->get('foo'));
$bar = [
@ -42,7 +43,13 @@ class DriverTestBase extends TestCase {
$this->assertEquals($bar, $this->driver->get('bar'));
}
public function testGetMultiple()
public function testGetMultipleOnBadKey(): void
{
$actual = $this->driver->getMultiple(['x','y']);
$this->assertEquals([], $actual);
}
public function testGetMultiple(): void
{
$this->driver->set('foo', ['bar']);
$this->driver->set('bar', (object) [
@ -69,9 +76,46 @@ class DriverTestBase extends TestCase {
$this->assertEquals($expected, $actual);
}
public function testSetWithExpires()
public function testSetWithExpires(): void
{
$this->driver->set('foo', 'bar', 30);
$this->assertEquals('bar', $this->driver->get('foo'));
}
public function testDelete(): void
{
$this->driver->set('a1', 'b2');
$this->assertTrue($this->driver->exists('a1'));
$this->assertTrue($this->driver->delete('a1'));
$this->assertFalse($this->driver->exists('a1'));
}
public function testDeleteMultiple(): void
{
$this->driver->set('a', 1);
$this->driver->set('b', 2);
$this->assertTrue($this->driver->exists('a'));
$this->assertTrue($this->driver->exists('b'));
/*$this->assertTrue(*/$this->driver->deleteMultiple(['a', 'b']);//);
$this->assertFalse($this->driver->exists('a'));
$this->assertFalse($this->driver->exists('b'));
}
public function testExpiresAt(): void
{
$this->driver->set('abc', 'def');
$result = $this->driver->expiresAt('abc', 30);
$this->assertTrue($result);
}
public function testExpiresAtBadKey(): void
{
$result = $this->driver->expiresAt('q', 30);
$this->assertFalse($result);
}
}

View File

@ -1,39 +0,0 @@
<?php declare(strict_types=1);
/**
* Banker
*
* A Caching library implementing psr/cache
*
* PHP version 7.0
*
* @package Banker
* @author Timothy J. Warren <tim@timshomepage.net>
* @copyright 2016 - 2017 Timothy J. Warren
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version 1.0.1
* @link https://git.timshomepage.net/timw4mail/banker
*/
namespace Aviat\Banker\Tests\Driver;
use Aviat\Banker\Driver\MemcacheDriver;
use Aviat\Banker\Exception\CacheException;
class MemcacheDriverTest extends DriverTestBase {
public function setup()
{
try
{
$this->driver = new MemcacheDriver([
'host' => 'localhost',
'port' => '11211',
'persistent' => false,
]);
$this->driver->flush();
}
catch (CacheException $e)
{
$this->markTestSkipped();
}
}
}

View File

@ -76,6 +76,7 @@ class ItemTest extends TestCase {
$interval2 = 500;
$this->item->expiresAfter($interval2);
$this->item->save();
$friend2 = new Friend($this->item);
$this->assertEquals($interval2, $friend2->ttl);
}

View File

@ -23,9 +23,9 @@ use PHPUnit\Framework\TestCase;
use Psr\Log\{LoggerInterface, NullLogger};
class PoolTest extends TestCase {
protected $pool;
public function setUp()
{
$this->pool = new Pool([
@ -33,141 +33,176 @@ class PoolTest extends TestCase {
'connection' => []
]);
}
public function testGetDefaultLogger()
public function testGetDefaultLogger(): void
{
$friend = new Friend($this->pool);
$driverFriend = new Friend($friend->driver);
// Check that a valid logger is set
$this->assertInstanceOf(LoggerInterface::class, $friend->getLogger(), "Logger exists after being set");
$this->assertInstanceOf(LoggerInterface::class, $driverFriend->getLogger(), "Logger exists on driver after being set");
// Make sure we get the default Null logger
$this->assertTrue(is_a($friend->getLogger(), NullLogger::class));
$this->assertTrue(is_a($driverFriend->getLogger(), NullLogger::class));
}
public function testSetLoggerInConstructor()
public function testSetLoggerInConstructor(): void
{
$logger = new Logger('test');
$logger->pushHandler(new SyslogHandler(Logger::WARNING));
$pool = new Pool([
'driver' => 'null',
'connection' => [],
], $logger);
$friend = new Friend($pool);
$driverFriend = new Friend($friend->driver);
// Check that a valid logger is set
$this->assertInstanceOf(LoggerInterface::class, $friend->getLogger(), "Logger exists after being set");
$this->assertInstanceOf(LoggerInterface::class, $driverFriend->getLogger(), "Logger exists on driver after being set");
// Make sure we aren't just getting the default Null logger
$this->assertFalse(is_a($friend->getLogger(), NullLogger::class));
$this->assertFalse(is_a($driverFriend->getLogger(), NullLogger::class));
}
public function testGetSetLogger()
{
$logger = new Logger('test');
$logger->pushHandler(new SyslogHandler(Logger::WARNING));
$this->pool->setLogger($logger);
$friend = new Friend($this->pool);
$driverFriend = new Friend($friend->driver);
// Check that a valid logger is set
$this->assertInstanceOf(LoggerInterface::class, $friend->getLogger(), "Logger exists after being set");
$this->assertInstanceOf(LoggerInterface::class, $driverFriend->getLogger(), "Logger exists on driver after being set");
// Make sure we aren't just getting the default Null logger
$this->assertFalse(is_a($friend->getLogger(), NullLogger::class));
$this->assertFalse(is_a($driverFriend->getLogger(), NullLogger::class));
}
public function testGetItem()
public function testGetSetLogger(): void
{
$logger = new Logger('test');
$logger->pushHandler(new SyslogHandler(Logger::WARNING));
$this->pool->setLogger($logger);
$friend = new Friend($this->pool);
$driverFriend = new Friend($friend->driver);
// Check that a valid logger is set
$this->assertInstanceOf(LoggerInterface::class, $friend->getLogger(), "Logger exists after being set");
$this->assertInstanceOf(LoggerInterface::class, $driverFriend->getLogger(), "Logger exists on driver after being set");
// Make sure we aren't just getting the default Null logger
$this->assertFalse(is_a($friend->getLogger(), NullLogger::class));
$this->assertFalse(is_a($driverFriend->getLogger(), NullLogger::class));
}
public function testGetItem(): void
{
$item = $this->pool->getItem('foo');
$this->assertInstanceOf(Item::class, $item);
}
public function testItemBadKey()
public function testItemBadKey(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("Cache key must be a string.");
$this->expectExceptionMessage('Cache key must be a string.');
$this->pool->getItem([]);
}
public function testGetItems()
public function testGetItemsBadKey(): void
{
$this->expectException(InvalidArgumentException::class);
$this->pool->getItems([1,3,2]);
}
public function testGetItems(): void
{
$collection = $this->pool->getItems(['foo', 'bar', 'baz']);
$this->assertInstanceOf(ItemCollection::class, $collection);
foreach($collection as $item)
{
$this->assertInstanceOf(Item::class, $item);
}
}
public function testEmptyGetItems()
public function testGetItemsDeferredItems(): void
{
$collection = $this->pool->getItems();
$this->assertInstanceOf(ItemCollection::class, $collection);
$this->assertEquals(0, count($collection));
$this->pool->clear();
$deferredValues = ['x' => 1, 'y' => 2, 'z' => 3];
$keys = ['x', 'y', 'z'];
foreach ($deferredValues as $key => $value)
{
$item = $this->pool->getItem($key)->set($value);
$this->pool->saveDeferred($item);
}
$collection = $this->pool->getItems($keys);
foreach($collection as $key => $item)
{
$this->assertSame($deferredValues[$key], $item->get());
}
$this->assertCount(3, $collection);
}
public function testHasItem()
public function testEmptyGetItems(): void
{
$this->pool->clear();
$collection = $this->pool->getItems();
$this->assertInstanceOf(ItemCollection::class, $collection);
$this->assertCount(0, $collection);
}
public function testHasItem(): void
{
$this->pool->clear();
// The key doesn't exist yet
$this->assertFalse($this->pool->hasItem('foobar'));
// Create the item
$item = $this->pool->getItem('foobar')
->set('baz')
->save();
// The item exists now
$this->assertTrue($this->pool->hasItem('foobar'));
}
public function testHasItemBadKey()
public function testHasItemBadKey(): void
{
$this->pool->clear();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("Cache key must be a string.");
$this->expectExceptionMessage('Cache key must be a string.');
$this->pool->hasItem(34);
}
public function testClear()
public function testClear(): void
{
// Call clear to make sure we are working from a clean slate to start
$this->pool->clear();
$data = [
'foo' => 'bar',
'bar' => 'baz',
'foobar' => 'foobarbaz'
];
// Set up some data
$this->setupDataInCache($data);
foreach($data as $key => $val)
{
$this->assertTrue($this->pool->hasItem($key));
$item = $this->pool->getItem($key);
$this->assertEquals($val, $item->get());
}
// Now we clear it all!
$this->pool->clear();
foreach($data as $key => $val)
{
$this->assertFalse($this->pool->hasItem($key));
@ -175,41 +210,41 @@ class PoolTest extends TestCase {
$this->assertNull($item->get());
}
}
public function testDeleteItemBadKey()
public function testDeleteItemBadKey(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage("Cache key must be a string.");
$this->pool->deleteItem(34);
}
public function testDeleteItemThatDoesNotExist()
public function testDeleteItemThatDoesNotExist(): void
{
$this->pool->clear();
$this->assertFalse($this->pool->deleteItem('foo'));
}
public function testDeleteItem()
public function testDeleteItem(): void
{
// Start with a clean slate
$this->pool->clear();
$data = [
'foo' => 'bar',
'bar' => 'baz',
'foobar' => 'foobarbaz'
];
$this->setupDataInCache($data);
$this->pool->deleteItem('foo');
// The item no longer exists
$this->assertFalse($this->pool->hasItem('foo'));
$item = $this->pool->getItem('foo');
$this->assertNull($item->get());
// The other items still exist
foreach(['bar', 'foobar'] as $key)
{
@ -218,21 +253,21 @@ class PoolTest extends TestCase {
$this->assertFalse(is_null($item->get()));
}
}
public function testDeleteItems()
public function testDeleteItems(): void
{
$this->pool->clear();
$data = [
'foo' => 'bar',
'bar' => 'baz',
'foobar' => 'foobarbaz'
];
$this->setupDataInCache($data);
$this->pool->deleteItems(['foo', 'bar']);
foreach(['foo', 'bar'] as $key)
{
$this->assertFalse($this->pool->hasItem($key));
@ -240,58 +275,56 @@ class PoolTest extends TestCase {
$this->assertNull($item->get());
}
}
public function testSaveDeferred()
public function testSaveDeferred(): void
{
$this->pool->clear();
$data = [
'foo' => 'bar',
'bar' => 'baz',
'foobar' => 'foobarbaz'
];
$this->setupDeferredData($data);
// See that the data is returned by the pool
foreach($data as $key => $val)
{
$this->assertTrue($this->pool->hasItem($key));
$item = $this->pool->getItem($key);
// The cache hasn't been updated yet, even
// though the pool data has
$this->assertNotEquals($data[$key], $item->get());
// Since the value has been deferred,
// the pool will return the updated value,
// even though the cache hasn't been updated yet
$this->assertEquals($data[$key], $item->get());
}
}
public function testCommit()
public function testCommit(): void
{
$this->pool->clear();
// If there are no deferred items, this will return true
$this->assertTrue($this->pool->commit());
$data = [
'foo' => 'bar',
'bar' => 'baz',
'foobar' => 'foobarbaz'
];
$this->setupDeferredData($data);
// See that the data is returned by the pool
foreach($this->pool->getItems(array_keys($data)) as $key => $item)
{
$this->assertTrue($this->pool->hasItem($key));
// The cache hasn't been updated yet, even
// though the pool data has
$this->assertNotEquals($data[$key], $item->get());
$this->assertEquals($data[$key], $item->get());
}
$this->pool->commit();
// See that the data is saved in the cache backend
foreach($this->pool->getItems(array_keys($data)) as $key => $item)
{
@ -299,25 +332,25 @@ class PoolTest extends TestCase {
$this->assertEquals($data[$key], $item->get());
}
}
protected function setupDeferredData($data)
protected function setupDeferredData($data): void
{
foreach($data as $key => $val)
{
$item = $this->pool->getItem($key)
->set($val);
$this->assertTrue($this->pool->saveDeferred($item));
}
}
protected function setupDataInCache($data)
protected function setupDataInCache($data): void
{
foreach($data as $key => $val)
{
$item = $this->pool->getItem($key)
->set($val);
$this->pool->save($item);
}
}