Got the base working.

- Working providers: Dummy, Redis and File
- Component now delivers the selected storage based on its config file
- Now provides ObjectStorageTest, a PSR CacheProvider compatible object to save and cache data in ObjectStorage
This commit is contained in:
Abel Hoogeveen 2020-12-20 19:43:02 +01:00
parent 8f3a2ba826
commit 80d0450f5c
Signed by: abelhooge
GPG Key ID: 387E8DC1F73306FC
13 changed files with 993 additions and 31 deletions

View File

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ composer.phar
build/
test/temp/
vendor/
/test/.phpunit.result.cache

View File

@ -0,0 +1,128 @@
<?php
/**
* FuzeWorks ObjectStorage Component.
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-2020 i15
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author i15
* @copyright Copyright (c) 2013 - 2020, i15. (https://i15.nl)
* @license https://opensource.org/licenses/MIT MIT License
*
* @since Version 1.3.0
*
* @version Version 1.3.0
*/
namespace FuzeWorks\ObjectStorage;
use Psr\SimpleCache\CacheInterface;
class ObjectStorageCache implements CacheInterface
{
private iObjectStorageProvider $provider;
public function __construct(iObjectStorageProvider $provider)
{
$this->provider = $provider;
}
private function testTTL(string $key)
{
$meta = $this->provider->getItemMeta('fwcache_' . $key);
if ($meta['ttl'] > 0 && time() > $meta['time'] + $meta['ttl'])
$this->provider->deleteItem('fwcache_' . $key);
}
public function get($key, $default = null)
{
// Remove the item if its TTL has expired
$this->testTTL($key);
// Fetch the value
$res = $this->provider->getItem('fwcache_' . $key);
// If there is no value, return the default
return is_null($res) ? $default : $res;
}
public function set($key, $value, $ttl = null)
{
$meta = [
'time' => time(),
'ttl' => is_int($ttl) ? $ttl : 0
];
return $this->provider->save('fwcache_' . $key, $value, $meta);
}
public function delete($key)
{
return $this->provider->deleteItem('fwcache_' . $key);
}
public function clear()
{
// Fetch the index set
$index = $this->provider->getIndex();
foreach ($index as $entry)
{
if (substr($entry, 0, 8) === 'fwcache_')
$this->provider->deleteItem($entry);
}
return true;
}
public function getMultiple($keys, $default = null)
{
$out = [];
foreach ($keys as $key)
{
$out[$key] = $this->get($key, $default);
}
return $out;
}
public function setMultiple($values, $ttl = null)
{
foreach ($values as $key => $value)
$this->set($key, $value, $ttl);
return true;
}
public function deleteMultiple($keys)
{
foreach ($keys as $key)
$this->delete($key);
return true;
}
public function has($key)
{
$this->testTTL($key);
return $this->provider->hasItem('fwcache_' . $key);
}
}

View File

@ -34,9 +34,14 @@
*/
namespace FuzeWorks\ObjectStorage;
use FuzeWorks\Config;
use FuzeWorks\Configurator;
use FuzeWorks\Exception\ConfigException;
use FuzeWorks\Exception\FactoryException;
use FuzeWorks\Factory;
use FuzeWorks\iComponent;
use FuzeWorks\ObjectStorage\Exception\ObjectStorageException;
use Psr\SimpleCache\CacheInterface;
/**
* ObjectStorageComponent Class.
@ -49,6 +54,27 @@ use FuzeWorks\iComponent;
class ObjectStorageComponent implements iComponent
{
/**
* The configuration file for ObjectStorage
*
* @var array
*/
private array $cfg;
/**
* The currently selected ObjectStorageProvider
*
* @var iObjectStorageProvider
*/
private iObjectStorageProvider $provider;
/**
* The currently used CacheInterface
*
* @var CacheInterface
*/
private CacheInterface $cache;
public function getName(): string
{
return 'ObjectStorageComponent';
@ -59,6 +85,71 @@ class ObjectStorageComponent implements iComponent
return ['storage' => $this];
}
/**
* Fetches and returns the currently selected ObjectStorageProvider
*
* @throws ObjectStorageException
* @return iObjectStorageProvider
*/
public function getStorage(): iObjectStorageProvider
{
// If the provider is already loaded, return that one
if (isset($this->provider))
return $this->provider;
// Load the config, if it isn't loaded yet
if (!isset($this->cfg))
{
try {
/** @var Config $configs */
$configs = Factory::getInstance('config');
$this->cfg = $configs->getConfig('objectstorage')->toArray();
} catch (ConfigException | FactoryException $e) {
throw new ObjectStorageException("Could not get ObjectStorageProvider. No config file named 'config.objectstorage.php' could be found.");
}
}
// Get the currently selected ObjectStorageProvider
$selected = $this->cfg['ObjectStorageProvider'];
if (is_null($selected))
throw new ObjectStorageException("Could not get ObjectStorageProvider. Selected provider is null!");
// Try and load the ObjectStorageProvider
$class = '\FuzeWorks\ObjectStorage\Provider\\' . $selected;
if (!class_exists($class, true))
throw new ObjectStorageException("Could not get ObjectStorageProvider. Selected provider '".$selected."' is not recognized.");
/** @var iObjectStorageProvider $provider */
$provider = new $class();
if (!$provider instanceof iObjectStorageProvider)
throw new ObjectStorageException("Could not get ObjectStorageProvider. Selected provider '".$selected."' is not an instance of iObjectStorageProvider'.");
// Fetch the parameters
$params = isset($this->cfg[$selected]) && is_array($this->cfg[$selected]) ? $this->cfg[$selected] : [];
if (!$provider->init($params))
throw new ObjectStorageException("Could not get ObjectStorageProvider. Selected provider '".$selected."' failed to load.");
$this->provider = $provider;
return $this->provider;
}
/**
* Returns a PSR compatible Cache object
*
* @return CacheInterface
* @throws ObjectStorageException
*/
public function getCache(): CacheInterface
{
if (isset($this->cache))
return $this->cache;
$storageProvider = $this->getStorage();
$this->cache = new ObjectStorageCache($storageProvider);
return $this->cache;
}
public function onAddComponent(Configurator $configurator)
{
}

View File

@ -0,0 +1,117 @@
<?php
/**
* FuzeWorks ObjectStorage Component.
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-2020 i15
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author i15
* @copyright Copyright (c) 2013 - 2020, i15. (https://i15.nl)
* @license https://opensource.org/licenses/MIT MIT License
*
* @since Version 1.3.0
*
* @version Version 1.3.0
*/
namespace FuzeWorks\ObjectStorage\Provider;
use FuzeWorks\ObjectStorage\iObjectStorageProvider;
class DummyProvider implements iObjectStorageProvider
{
private array $data = ['index' => [], 'data' => []];
public function init(array $providerConfig): bool
{
return true;
}
public function getIndex(): array
{
return $this->data['index'];
}
public function getItem(string $key)
{
if (!in_array($key, $this->data['index']))
return null;
return $this->data['data'][$key]['data'];
}
public function getItemMeta(string $key): ?array
{
if (!in_array($key, $this->data['index']))
return null;
return $this->data['data'][$key]['meta'];
}
public function getItems(array $keys = []): array
{
$output = [];
foreach ($keys as $key)
$output[$key] = $this->getItem($key);
return $output;
}
public function hasItem(string $key): bool
{
return in_array($key, $this->data['index']);
}
public function clear(): bool
{
return $this->deleteItems($this->getIndex());
}
public function deleteItem(string $key): bool
{
// Remove the index
if (($k = array_search($key, $this->data['index'])) !== false) {
unset($this->data['index'][$k]);
}
// And remove the data
unset($this->data['data'][$key]);
return true;
}
public function deleteItems(array $keys): bool
{
foreach ($keys as $key)
$this->deleteItem($key);
return true;
}
public function save(string $key, $value, array $metaData = []): bool
{
if (!in_array($key, $this->data['index']))
$this->data['index'][] = $key;
$this->data['data'][$key] = ['data' => $value, 'meta' => $metaData];
return true;
}
}

View File

@ -83,7 +83,7 @@ class FileProvider implements iObjectStorageProvider
public function init(array $providerConfig): bool
{
// First load the directory from the providerConfig
$directory = isset($providerConfig['storageDirectory']) ? $providerConfig['storageDirectory'] : null;
$directory = isset($providerConfig['storage_directory']) ? $providerConfig['storage_directory'] : null;
// Check if the directory exists
if (!file_exists($directory) || !is_dir($directory))
@ -117,7 +117,7 @@ class FileProvider implements iObjectStorageProvider
return $this->index;
}
public function getItem(string $key): ?array
public function getItem(string $key)
{
// Convert the key
$file = $this->directory . DS . crc32($key) . '.fwstorage';
@ -134,11 +134,7 @@ class FileProvider implements iObjectStorageProvider
}
// Otherwise try and load the metaData and contents
$meta = $this->index[$key]['meta'];
$data = unserialize(file_get_contents($file));
// Return the combined data
return ['meta' => $meta, 'data' => $data];
return unserialize(file_get_contents($file));
}
public function getItemMeta(string $key): ?array
@ -218,16 +214,6 @@ class FileProvider implements iObjectStorageProvider
return false;
}
public function commit(): bool
{
// TODO: Implement commit() method.
}
public function revert(): bool
{
// TODO: Implement revert() method.
}
private function commitIndex(): bool
{
if ($this->write_file($this->indexFile, serialize(['index' => $this->index]))) {

View File

@ -0,0 +1,188 @@
<?php
/**
* FuzeWorks ObjectStorage Component.
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-2020 i15
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author i15
* @copyright Copyright (c) 2013 - 2020, i15. (https://i15.nl)
* @license https://opensource.org/licenses/MIT MIT License
*
* @since Version 1.3.0
*
* @version Version 1.3.0
*/
namespace FuzeWorks\ObjectStorage\Provider;
use FuzeWorks\ObjectStorage\Exception\ObjectStorageException;
use FuzeWorks\ObjectStorage\iObjectStorageProvider;
use Redis;
use RedisException;
class RedisProvider implements iObjectStorageProvider
{
/**
* @var Redis
*/
protected Redis $conn;
/**
* Initializes the RedisProvider, by connecting to the Redis Server.
*
* $providerConfig can contain the following keys:
* 'socket_type', being either 'socket' or 'tcp'
* 'socket', when socket_type is socket, contains a handle for the socket
* 'host', when socket_type is tcp, contains the hostname or ip of the server
* 'port', when socket_type is tcp, contains the port of the server
* 'timeout', when socket_type is tcp, contains the amount of time to attempt connecting before failure
* 'db_index', the specific database number to use on the Redis Server
*
* Throws any ObjectStorageException on failure.
*
* @param array $providerConfig
* @return bool
* @throws ObjectStorageException
*/
public function init(array $providerConfig): bool
{
try {
$this->conn = new Redis();
// Afterwards we attempt to connect to the server
$socketType = $providerConfig['socket_type'];
if ($socketType === 'unix')
$success = $this->conn->connect($providerConfig['socket']);
elseif ($socketType === 'tcp')
$success = $this->conn->connect($providerConfig['host'], $providerConfig['port'], $providerConfig['timeout']);
else
$success = false;
// If failed, throw an exception informing so
if (!$success)
throw new ObjectStorageException("Could not load RedisProvider ObjectStorage. Unable to connect to server.");
// If authentication is required, attempt to do so with the provided password
if (isset($providerConfig['password']) && !$this->conn->auth($providerConfig['password']))
throw new ObjectStorageException("Could not load RedisProvider ObjectStorage. Authentication failure.");
// If a db_index is provided, use that one accordingly
if (isset($providerConfig['db_index']) && is_int($providerConfig['db_index']))
$this->conn->select($providerConfig['db_index']);
// And if all goes well, report a true
return true;
// If any sort of failure has occurred along the way,
} catch (RedisException $e) {
throw new ObjectStorageException("Could not load RedisProvider ObjectStorage. RedisException thrown: '" . $e->getMessage() . "'");
}
}
public function getIndex(): array
{
return $this->conn->sMembers('ObjectStorageIndex');
}
public function getItem(string $key)
{
// If the requested key is not part of the index, this item is not tracked and should therefore
// return null.
if (!$this->conn->sIsMember('ObjectStorageIndex', $key))
return null;
// If the data doesn't exist, return null
if (!$this->conn->hExists('fwstorage_' . $key, 'data'))
return null;
return unserialize($this->conn->hGet('fwstorage_' . $key, 'data'));
}
public function getItemMeta(string $key): ?array
{
// If the requested key is not part of the index, this item is not tracked and should therefore
// return null.
if (!$this->conn->sIsMember('ObjectStorageIndex', $key))
return null;
// If the data doesn't exist, return null
if (!$this->conn->hExists('fwstorage_' . $key, 'meta'))
return null;
return unserialize($this->conn->hGet('fwstorage_' . $key, 'meta'));
}
public function getItems(array $keys = []): array
{
$output = [];
foreach ($keys as $key)
$output[$key] = $this->getItem($key);
return $output;
}
public function hasItem(string $key): bool
{
return $this->conn->sIsMember('ObjectStorageIndex', $key);
}
public function clear(): bool
{
return $this->deleteItems($this->getIndex());
}
public function deleteItem(string $key): bool
{
// If the requested key is not part of the index, this item is not tracked and should therefore
// return null.
if ($this->conn->sIsMember('ObjectStorageIndex', $key))
$this->conn->sRem('ObjectStorageIndex', $key);
if ($this->conn->exists('fwstorage_' . $key))
$this->conn->del('fwstorage_' . $key);
return true;
}
public function deleteItems(array $keys): bool
{
foreach ($keys as $key)
$this->deleteItem($key);
return true;
}
public function save(string $key, $value, array $metaData = []): bool
{
// If the requested key is not part of the index, this item is not tracked and should therefore
// return null.
if (!$this->conn->sIsMember('ObjectStorageIndex', $key))
$this->conn->sAdd('ObjectStorageIndex', $key);
// Write to the hash
$this->conn->hSet('fwstorage_' . $key, 'data', serialize($value));
$this->conn->hSet('fwstorage_' . $key, 'meta', serialize($metaData));
return true;
}
}

View File

@ -34,7 +34,6 @@
*/
namespace FuzeWorks\ObjectStorage;
use Traversable;
interface iObjectStorageProvider
{
@ -42,7 +41,7 @@ interface iObjectStorageProvider
public function init(array $providerConfig): bool;
public function getIndex(): array;
public function getItem(string $key): ?array;
public function getItem(string $key);
public function getItemMeta(string $key): ?array;
public function getItems(array $keys = []): array;
public function hasItem(string $key): bool;
@ -50,7 +49,5 @@ interface iObjectStorageProvider
public function deleteItem(string $key): bool;
public function deleteItems(array $keys): bool;
public function save(string $key, $value, array $metaData = []): bool;
public function commit(): bool;
public function revert(): bool;
}

View File

@ -0,0 +1,198 @@
<?php
/**
* FuzeWorks ObjectStorage Component.
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-2020 i15
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author i15
* @copyright Copyright (c) 2013 - 2020, i15. (https://i15.nl)
* @license https://opensource.org/licenses/MIT MIT License
*
* @since Version 1.3.0
*
* @version Version 1.3.0
*/
use FuzeWorks\Factory;
use FuzeWorks\ObjectStorage\ObjectStorageComponent;
use PHPUnit\Framework\TestCase;
use Psr\SimpleCache\CacheInterface;
class ObjectStorageCacheTest extends TestCase
{
private CacheInterface $cache;
public function setUp(): void
{
parent::setUp();
$this->loadProvider();
}
public function tearDown(): void
{
parent::tearDown();
// Always clear the cache after every test
$this->cache->clear();
}
private function loadProvider()
{
/** @var ObjectStorageComponent $objectStorageComponent */
$objectStorageComponent = Factory::getInstance('storage');
$this->cache = $objectStorageComponent->getCache();
}
public function testFoundation()
{
$this->assertInstanceOf('\Psr\SimpleCache\CacheInterface', $this->cache);
$this->assertInstanceOf('\FuzeWorks\ObjectStorage\ObjectStorageCache', $this->cache);
}
/**
* @depends testFoundation
*/
public function testSetGetAndHas()
{
$testData = ['hello', 'world'];
// First check the data isn't there
$this->assertFalse($this->cache->has('testData'));
// Then write it
$this->assertTrue($this->cache->set('testData', $testData));
// Assert it is there and check its contents
$this->assertTrue($this->cache->has('testData'));
$this->assertEquals(['hello', 'world'], $this->cache->get('testData'));
}
/**
* @depends testSetGetAndHas
*/
public function testGetDefaultValue()
{
// Verify that no value exists
$this->assertFalse($this->cache->has('testData'));
$this->assertNull($this->cache->get('testData'));
// And check if the default value is returned
$this->assertEquals('default!', $this->cache->get('testData', 'default!'));
}
/**
* @depends testSetGetAndHas
*/
public function testDeleteValue()
{
// Verify that none exist
$this->assertFalse($this->cache->has('testData'));
// Write some data
$this->assertTrue($this->cache->set('testData', 'someValue'));
$this->assertEquals('someValue', $this->cache->get('testData'));
$this->assertTrue($this->cache->has('testData'));
// Delete it
$this->assertTrue($this->cache->delete('testData'));
$this->assertFalse($this->cache->has('testData'));
}
/**
* @depends testDeleteValue
*/
public function testClear()
{
// Write some data
$this->assertTrue($this->cache->set('testData1', 'value1'));
$this->assertTrue($this->cache->set('testData2', 'value2'));
// Then clear it off
$this->assertTrue($this->cache->clear());
$this->assertFalse($this->cache->has('testData1'));
$this->assertFalse($this->cache->has('testData2'));
}
/**
* @depends testDeleteValue
*/
public function testMultiple()
{
// First check that none of the variables exist
$this->assertFalse($this->cache->has('testData1'));
$this->assertFalse($this->cache->has('testData2'));
$this->assertFalse($this->cache->has('testData3'));
// With a get multiple, and default
$this->assertEquals([
'testData1' => 'default',
'testData2' => 'default',
'testData3' => 'default'
], $this->cache->getMultiple(['testData1', 'testData2', 'testData3'], 'default'));
// Write multiple
$this->assertTrue($this->cache->setMultiple([
'testData1' => 'value1',
'testData2' => 'value2',
'testData3' => 'value3'
]));
// Test the contents
$this->assertEquals([
'testData1' => 'value1',
'testData2' => 'value2',
'testData3' => 'value3'
], $this->cache->getMultiple(['testData1', 'testData2', 'testData3'], 'default'));
// And also delete them all
$this->assertTrue($this->cache->deleteMultiple(['testData1', 'testData2', 'testData3']));
$this->assertFalse($this->cache->has('testData1'));
$this->assertFalse($this->cache->has('testData2'));
$this->assertFalse($this->cache->has('testData3'));
}
/**
* @depends testSetGetAndHas
*/
public function testTTL()
{
$testData = ['hello', 'world'];
// First check the data isn't there
$this->assertFalse($this->cache->has('testData'));
// Then write it
$this->assertTrue($this->cache->set('testData', $testData, 1));
// Assert it is there and check its contents
$this->assertTrue($this->cache->has('testData'));
$this->assertEquals(['hello', 'world'], $this->cache->get('testData'));
// Then wait 2 secs
sleep(2);
// And check again
$this->assertFalse($this->cache->has('testData'));
}
}

View File

@ -0,0 +1,216 @@
<?php
/**
* FuzeWorks ObjectStorage Component.
*
* The FuzeWorks PHP FrameWork
*
* Copyright (C) 2013-2020 i15
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* @author i15
* @copyright Copyright (c) 2013 - 2020, i15. (https://i15.nl)
* @license https://opensource.org/licenses/MIT MIT License
*
* @since Version 1.3.0
*
* @version Version 1.3.0
*/
use FuzeWorks\Factory;
use FuzeWorks\ObjectStorage\iObjectStorageProvider;
use FuzeWorks\ObjectStorage\ObjectStorageComponent;
use PHPUnit\Framework\TestCase;
/**
* Class ObjectStorageProviderTest
*
* @todo getIndex() method
*/
class ObjectStorageProviderTest extends TestCase
{
private iObjectStorageProvider $provider;
public function setUp(): void
{
parent::setUp();
$this->loadProvider();
}
public function tearDown(): void
{
parent::tearDown(); // TODO: Change the autogenerated stub
// Always clear the provider at the end
$this->provider->clear();
}
private function loadProvider()
{
/** @var ObjectStorageComponent $objectStorageComponent */
$objectStorageComponent = Factory::getInstance('storage');
$this->provider = $objectStorageComponent->getStorage();
}
public function testFoundation()
{
$this->assertInstanceOf('\FuzeWorks\ObjectStorage\iObjectStorageProvider', $this->provider);
}
/**
* @depends testFoundation
*/
public function testSave()
{
$testData = ['hello', 'world', 'foo' => 'bar'];
// First assert it does not exist yet
$this->assertNull($this->provider->getItem('testData'));
$this->assertFalse($this->provider->hasItem('testData'));
// Write the data
$this->assertTrue($this->provider->save('testData', $testData));
// Read the data
$this->assertTrue($this->provider->hasItem('testData'));
$this->assertEquals(['hello', 'world', 'foo' => 'bar'], $this->provider->getItem('testData'));
}
/**
* @depends testSave
*/
public function testDeleteItem()
{
$testData = ['o', 'm', 'g'];
// First assert that the data does not exist yet
$this->assertNull($this->provider->getItem('testDeleteData'));
// Write the data
$this->assertTrue($this->provider->save('testDeleteData', $testData));
// Read the data
$this->assertEquals(['o', 'm', 'g'], $this->provider->getItem('testDeleteData'));
// Delete the data
$this->assertTrue($this->provider->deleteItem('testDeleteData'));
// And test that it is truly gone
$this->assertNull($this->provider->getItem('testDeleteData'));
}
/**
* @depends testDeleteItem
*/
public function testDeleteItems()
{
$testData = 'lord';
$testData2 = 'almighty';
// First assert that the data does not exist yet
$this->assertNull($this->provider->getItem('testDeleteData1'));
$this->assertNull($this->provider->getItem('testDeleteData2'));
// Write the data
$this->assertTrue($this->provider->save('testDeleteData1', $testData));
$this->assertTrue($this->provider->save('testDeleteData2', $testData2));
// Read the data
$this->assertEquals(
['testDeleteData1' => 'lord', 'testDeleteData2' => 'almighty'],
$this->provider->getItems(['testDeleteData1', 'testDeleteData2'])
);
// Delete the data
$this->assertTrue($this->provider->deleteItems(['testDeleteData1', 'testDeleteData2']));
// And test that it is truly gone
$this->assertNull($this->provider->getItem('testDeleteData1'));
$this->assertNull($this->provider->getItem('testDeleteData2'));
}
/**
* @depends testDeleteItems
*/
public function testClear()
{
$testData = ['not', 'my', 'department'];
// First assert it does not exist yet
$this->assertNull($this->provider->getItem('testClearData'));
$this->provider->save('testClearData', $testData);
// Test that it can be read
$this->assertEquals(['not', 'my', 'department'], $this->provider->getItem('testClearData'));
// Then attempt to clean it
$this->assertTrue($this->provider->clear());
// And check that it cannot be read
$this->assertNull($this->provider->getItem('testClearData'));
}
public function testItemNotExist()
{
$this->assertNull($this->provider->getItem('doesNotExist'));
}
public function testGetMultipleItems()
{
$testData1 = ['tao', 'te', 'ching'];
$testData2 = ['plato', 'aristotle'];
// First assert they do not exist
$this->assertNull($this->provider->getItem('philo1'));
$this->assertNull($this->provider->getItem('philo2'));
$this->assertEquals(['philo1' => null, 'philo2' => null], $this->provider->getItems(['philo1', 'philo2']));
// Then write both
$this->assertTrue($this->provider->save('philo1', $testData1));
$this->assertTrue($this->provider->save('philo2', $testData2));
// Then read
$this->assertEquals([
'philo1' => ['tao', 'te', 'ching'],
'philo2' => ['plato', 'aristotle']
], $this->provider->getItems(['philo1', 'philo2']));
}
public function testItemMetaData()
{
$testData = ['meine', 'gute'];
$metaData = ['someKey' => 'someValue'];
// First assert that the data does not exist
$this->assertNull($this->provider->getItem('testData'));
$this->assertNull($this->provider->getItemMeta('testData'));
// Then save the data
$this->assertTrue($this->provider->save('testData', $testData, $metaData));
// Check the metaData
$this->assertEquals(['someKey' => 'someValue'], $this->provider->getItemMeta('testData'));
// Remove the key
$this->provider->deleteItem('testData');
$this->assertNull($this->provider->getItemMeta('testData'));
}
}

View File

@ -32,9 +32,13 @@
*
* @version Version 1.3.0
*/
require_once(dirname(__DIR__) . '/vendor/autoload.php');
$configurator = new \FuzeWorks\Configurator();
use FuzeWorks\Configurator;
use FuzeWorks\Priority;
$configurator = new Configurator();
// Set directories
$configurator->setTempDirectory(__DIR__ . '/temp');
@ -43,15 +47,10 @@ $configurator->setLogDirectory(__DIR__ . '/temp');
// Other values
$configurator->setTimeZone('Europe/Amsterdam');
// Add TracyComponent
\FuzeWorks\TracyComponent::enableTracy();
$configurator->addComponent(new \FuzeWorks\TracyComponent());
// And the star of the show: ObjectStorageComponent
$configurator->addComponent(new \FuzeWorks\ObjectStorage\ObjectStorageComponent());
// Debug related
$configurator->enableDebugMode();
$configurator->setDebugAddress('ALL');
// Add the test config file
$configurator->addDirectory(dirname(__FILE__), 'config', Priority::HIGH);
return $configurator->createContainer();

View File

@ -33,4 +33,28 @@
* @version Version 1.3.0
*/
return [];
use FuzeWorks\Core;
return [
// Which provider shall be used
// Options: DummyProvider, RedisProvider, FileProvider
'ObjectStorageProvider' => Core::getEnv('OBJECTSTORAGE_PROVIDER', null),
'DummyProvider' => [],
'RedisProvider' => [
// Type can be 'tcp' or 'unix'
'socket_type' => Core::getEnv('OBJECTSTORAGE_REDIS_SOCKET_TYPE', 'tcp'),
// If socket_type == 'unix', set the socket here
'socket' => Core::getEnv('OBJECTSTORAGE_REDIS_SOCKET', null),
// If socket_type == 'tcp', set the host here
'host' => Core::getEnv('OBJECTSTORAGE_REDIS_HOST', '127.0.0.1'),
// And some standard settings
'port' => Core::getEnv('OBJECTSTORAGE_REDIS_PORT', 6379),
'password' => Core::getEnv('OBJECTSTORAGE_REDIS_PASSWORD', null),
'timeout' => Core::getEnv('OBJECTSTORAGE_REDIS_TIMEOUT', 0),
'db_index' => Core::getEnv('OBJECTSTORAGE_REDIS_DBINDEX', 0),
],
'FileProvider' => [
// The directory where objects get stored by the FileProvider
'storage_directory' => Core::getEnv('OBJECTSTORAGE_FILE_DIRECTORY', Core::$tempDir)
]
];

17
test/phpunit.xml Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" bootstrap="bootstrap.php" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false" colors="false">
<coverage processUncoveredFiles="false">
<include>
<directory suffix=".php">../</directory>
</include>
<exclude>
<directory suffix=".php">../vendor/</directory>
<directory suffix=".php">../test/</directory>
</exclude>
</coverage>
<testsuites>
<testsuite name="ObjectStorage Suite">
<directory>./</directory>
</testsuite>
</testsuites>
</phpunit>