Merge branch '2.2-cache-groups' into 2.2

Conflicts:
	lib/Cake/Test/Case/Cache/Engine/XcacheEngineTest.php
This commit is contained in:
Jose Lorenzo Rodriguez 2012-04-22 18:59:22 -04:30
commit 9f415d012c
16 changed files with 649 additions and 6 deletions

View file

@ -91,6 +91,8 @@ class Cache {
* The following keys are used in core cache engines: * The following keys are used in core cache engines:
* *
* - `duration` Specify how long items in this cache configuration last. * - `duration` Specify how long items in this cache configuration last.
* - `groups` List of groups or 'tags' associated to every key stored in this config.
* handy for deleting a complete group from cache.
* - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace * - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace
* with either another cache config or another application. * with either another cache config or another application.
* - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable * - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable
@ -452,6 +454,22 @@ class Cache {
return $success; return $success;
} }
/**
* Delete all keys from the cache belonging to the same group.
*
* @param string $group name of the group to be cleared
* @param string $config name of the configuration to use. Defaults to 'default'
* @return boolean True if the cache group was successfully cleared, false otherwise
*/
public static function clearGroup($group, $config = 'default') {
if (!self::isInitialized($config)) {
return false;
}
$success = self::$_engines[$config]->clearGroup($group);
self::set(null, $config);
return $success;
}
/** /**
* Check if Cache has initialized a working config for the given name. * Check if Cache has initialized a working config for the given name.
* *

View file

@ -27,6 +27,14 @@ abstract class CacheEngine {
*/ */
public $settings = array(); public $settings = array();
/**
* Contains the compiled string with all groups
* prefixes to be prepeded to every key in this cache engine
*
* @var string
**/
protected $groupPrefix = null;
/** /**
* Initialize the cache engine * Initialize the cache engine
* *
@ -37,10 +45,14 @@ abstract class CacheEngine {
*/ */
public function init($settings = array()) { public function init($settings = array()) {
$this->settings = array_merge( $this->settings = array_merge(
array('prefix' => 'cake_', 'duration' => 3600, 'probability' => 100), array('prefix' => 'cake_', 'duration' => 3600, 'probability' => 100, 'groups' => array()),
$this->settings, $this->settings,
$settings $settings
); );
if (!empty($this->settings['groups'])) {
sort($this->settings['groups']);
$this->groupPrefix = str_repeat('%s_', count($this->settings['groups']));
}
if (!is_numeric($this->settings['duration'])) { if (!is_numeric($this->settings['duration'])) {
$this->settings['duration'] = strtotime($this->settings['duration']) - time(); $this->settings['duration'] = strtotime($this->settings['duration']) - time();
} }
@ -110,6 +122,29 @@ abstract class CacheEngine {
*/ */
abstract public function clear($check); abstract public function clear($check);
/**
* Clears all values belonging to a group. Is upt to the implementing engine
* to decide whether actually deete the keys or just simulate it to acheive
* the same result.
*
* @param string $groups name of the group to be cleared
* @return boolean
**/
public function clearGroup($group) {
return false;
}
/**
* Does whatever initialization for each group is required
* and returns the `group value` for each of them, this is
* the token representing each group in the cache key
*
* @return array
**/
public function groups() {
return $this->settings['groups'];
}
/** /**
* Cache Engine settings * Cache Engine settings
* *
@ -129,8 +164,14 @@ abstract class CacheEngine {
if (empty($key)) { if (empty($key)) {
return false; return false;
} }
$prefix = '';
if (!empty($this->groupPrefix)) {
$prefix = vsprintf($this->groupPrefix, $this->groups());
}
$key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key))); $key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
return $key; return $prefix . $key;
} }
} }

View file

@ -25,6 +25,14 @@
*/ */
class ApcEngine extends CacheEngine { class ApcEngine extends CacheEngine {
/**
* Contains the compiled group names
* (prefixed witht the global configuration prefix)
*
* @var array
**/
protected $_compiledGroupNames = array();
/** /**
* Initialize the Cache Engine * Initialize the Cache Engine
* *
@ -127,4 +135,48 @@ class ApcEngine extends CacheEngine {
return true; return true;
} }
/**
* Returns the `group value` for each of the configured groups
* If the group initial value was not found, then it initializes
* the group accordingly.
*
* @return array
**/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
$this->_compiledGroupNames[] = $this->settings['prefix'] . $group;
}
}
$groups = apc_fetch($this->_compiledGroupNames);
if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->_compiledGroupNames as $group) {
if (!isset($groups[$group])) {
apc_store($group, 1);
$groups[$group] = 1;
}
}
ksort($groups);
}
$result = array();
$groups = array_values($groups);
foreach ($this->settings['groups'] as $i => $group) {
$result[] = $group . $groups[$i];
}
return $result;
}
/**
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
public function clearGroup($group) {
apc_inc($this->settings['prefix'] . $group, 1, $success);
return $success;
}
} }

View file

@ -82,6 +82,9 @@ class FileEngine extends CacheEngine {
if (substr($this->settings['path'], -1) !== DS) { if (substr($this->settings['path'], -1) !== DS) {
$this->settings['path'] .= DS; $this->settings['path'] .= DS;
} }
if (!empty($this->groupPrefix)) {
$this->groupPrefix = str_replace('_', DS, $this->groupPrefix);
}
return $this->_active(); return $this->_active();
} }
@ -285,7 +288,17 @@ class FileEngine extends CacheEngine {
* @return boolean true if the cache key could be set, false otherwise * @return boolean true if the cache key could be set, false otherwise
*/ */
protected function _setKey($key, $createKey = false) { protected function _setKey($key, $createKey = false) {
$path = new SplFileInfo($this->settings['path'] . $key);
$groups = null;
if (!empty($this->groupPrefix)) {
$groups = vsprintf($this->groupPrefix, $this->groups());
}
$dir = $this->settings['path'] . $groups;
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
$path = new SplFileInfo($dir . $key);
if (!$createKey && !$path->isFile()) { if (!$createKey && !$path->isFile()) {
return false; return false;
@ -324,4 +337,35 @@ class FileEngine extends CacheEngine {
return true; return true;
} }
/**
* Generates a safe key for use with cache engine storage engines.
*
* @param string $key the key passed over
* @return mixed string $key or false
*/
public function key($key) {
if (empty($key)) {
return false;
}
$key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
return $key;
}
/**
* Recursively deletes all files under any directory named as $group
*
* @return boolean success
**/
public function clearGroup($group) {
$directoryIterator = new RecursiveDirectoryIterator($this->settings['path']);
$contents = new RecursiveIteratorIterator($directoryIterator, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($contents as $object) {
$containsGroup = strpos($object->getPathName(), DS . $group . DS) !== false;
if ($object->isFile() && $containsGroup) {
unlink($object->getPathName());
}
}
return true;
}
} }

View file

@ -27,6 +27,14 @@
*/ */
class MemcacheEngine extends CacheEngine { class MemcacheEngine extends CacheEngine {
/**
* Contains the compiled group names
* (prefixed witht the global configuration prefix)
*
* @var array
**/
protected $_compiledGroupNames = array();
/** /**
* Memcache wrapper. * Memcache wrapper.
* *
@ -235,4 +243,47 @@ class MemcacheEngine extends CacheEngine {
return true; return true;
} }
/**
* Returns the `group value` for each of the configured groups
* If the group initial value was not found, then it initializes
* the group accordingly.
*
* @return array
**/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
$this->_compiledGroupNames[] = $this->settings['prefix'] . $group;
}
}
$groups = $this->_Memcache->get($this->_compiledGroupNames);
if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->_compiledGroupNames as $group) {
if (!isset($groups[$group])) {
$this->_Memcache->set($group, 1, false, 0);
$groups[$group] = 1;
}
}
ksort($groups);
}
$result = array();
$groups = array_values($groups);
foreach ($this->settings['groups'] as $i => $group) {
$result[] = $group . $groups[$i];
}
return $result;
}
/**
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
public function clearGroup($group) {
return (bool) $this->_Memcache->increment($this->settings['prefix'] . $group);
}
} }

View file

@ -26,6 +26,14 @@
*/ */
class WincacheEngine extends CacheEngine { class WincacheEngine extends CacheEngine {
/**
* Contains the compiled group names
* (prefixed witht the global configuration prefix)
*
* @var array
**/
protected $_compiledGroupNames = array();
/** /**
* Initialize the Cache Engine * Initialize the Cache Engine
* *
@ -134,4 +142,49 @@ class WincacheEngine extends CacheEngine {
return true; return true;
} }
/**
* Returns the `group value` for each of the configured groups
* If the group initial value was not found, then it initializes
* the group accordingly.
*
* @return array
**/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
$this->_compiledGroupNames[] = $this->settings['prefix'] . $group;
}
}
$groups = wincache_ucache_get($this->_compiledGroupNames);
if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->_compiledGroupNames as $group) {
if (!isset($groups[$group])) {
wincache_ucache_set($group, 1);
$groups[$group] = 1;
}
}
ksort($groups);
}
$result = array();
$groups = array_values($groups);
foreach ($this->settings['groups'] as $i => $group) {
$result[] = $group . $groups[$i];
}
return $result;
}
/**
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
public function clearGroup($group) {
wincache_ucache_inc($this->settings['prefix'] . $group, 1, $success);
return $success;
}
} }

View file

@ -137,6 +137,36 @@ class XcacheEngine extends CacheEngine {
return true; return true;
} }
/**
* Returns the `group value` for each of the configured groups
* If the group initial value was not found, then it initializes
* the group accordingly.
*
* @return array
**/
public function groups() {
$result = array();
foreach ($this->settings['groups'] as $group) {
$value = xcache_get($this->settings['prefix'] . $group);
if (!$value) {
$value = 1;
xcache_set($this->settings['prefix'] . $group, $value, 0);
}
$result[] = $group . $value;
}
return $result;
}
/**
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
public function clearGroup($group) {
return (bool) xcache_inc($this->settings['prefix'] . $group, 1);
}
/** /**
* Populates and reverses $_SERVER authentication values * Populates and reverses $_SERVER authentication values
* Makes necessary changes (and reverting them back) in $_SERVER * Makes necessary changes (and reverting them back) in $_SERVER
@ -173,5 +203,4 @@ class XcacheEngine extends CacheEngine {
} }
} }
} }
} }

View file

@ -217,7 +217,8 @@ class CacheTest extends CakeTestCase {
'probability' => 100, 'probability' => 100,
'engine' => 'File', 'engine' => 'File',
'isWindows' => DIRECTORY_SEPARATOR == '\\', 'isWindows' => DIRECTORY_SEPARATOR == '\\',
'mask' => 0664 'mask' => 0664,
'groups' => array()
); );
$this->assertEquals($expected, Cache::settings('sessions')); $this->assertEquals($expected, Cache::settings('sessions'));

View file

@ -49,6 +49,7 @@ class ApcEngineTest extends CakeTestCase {
parent::tearDown(); parent::tearDown();
Configure::write('Cache.disable', $this->_cacheDisable); Configure::write('Cache.disable', $this->_cacheDisable);
Cache::drop('apc'); Cache::drop('apc');
Cache::drop('apc_groups');
Cache::config('default'); Cache::config('default');
} }
@ -200,4 +201,73 @@ class ApcEngineTest extends CakeTestCase {
$this->assertEquals('survive', apc_fetch('not_cake')); $this->assertEquals('survive', apc_fetch('not_cake'));
apc_delete('not_cake'); apc_delete('not_cake');
} }
/**
* Tests that configuring groups for stored keys return the correct values when read/written
* Shows that altering the group value is equivalent to deleting all keys under the same
* group
*
* @return void
*/
public function testGroupsReadWrite() {
Cache::config('apc_groups', array(
'engine' => 'Apc',
'duration' => 0,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'apc_groups'));
apc_inc('test_group_a');
$this->assertFalse(Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups'));
$this->assertEquals('value2', Cache::read('test_groups', 'apc_groups'));
apc_inc('test_group_b');
$this->assertFalse(Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::write('test_groups', 'value3', 'apc_groups'));
$this->assertEquals('value3', Cache::read('test_groups', 'apc_groups'));
}
/**
* Tests that deleteing from a groups-enabled config is possible
*
* @return void
*/
public function testGroupDelete() {
Cache::config('apc_groups', array(
'engine' => 'Apc',
'duration' => 0,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::delete('test_groups', 'apc_groups'));
$this->assertFalse(Cache::read('test_groups', 'apc_groups'));
}
/**
* Test clearing a cache group
*
* @return void
**/
public function testGroupClear() {
Cache::config('apc_groups', array(
'engine' => 'Apc',
'duration' => 0,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups'));
$this->assertTrue(Cache::clearGroup('group_a', 'apc_groups'));
$this->assertFalse(Cache::read('test_groups', 'apc_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups'));
$this->assertTrue(Cache::clearGroup('group_b', 'apc_groups'));
$this->assertFalse(Cache::read('test_groups', 'apc_groups'));
}
} }

View file

@ -53,6 +53,9 @@ class FileEngineTest extends CakeTestCase {
parent::tearDown(); parent::tearDown();
Cache::clear(false, 'file_test'); Cache::clear(false, 'file_test');
Cache::drop('file_test'); Cache::drop('file_test');
Cache::drop('file_groups');
Cache::drop('file_groups2');
Cache::drop('file_groups3');
} }
/** /**
@ -393,4 +396,60 @@ class FileEngineTest extends CakeTestCase {
Cache::drop('mask_test'); Cache::drop('mask_test');
} }
/**
* Tests that configuring groups for stored keys return the correct values when read/written
*
* @return void
*/
public function testGroupsReadWrite() {
Cache::config('file_groups', array('engine' => 'File', 'duration' => 3600, 'groups' => array('group_a', 'group_b')));
$this->assertTrue(Cache::write('test_groups', 'value', 'file_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'file_groups'));
$this->assertTrue(Cache::write('test_groups2', 'value2', 'file_groups'));
$this->assertTrue(Cache::write('test_groups3', 'value3', 'file_groups'));
}
/**
* Tests that deleteing from a groups-enabled config is possible
*
* @return void
*/
public function testGroupDelete() {
Cache::config('file_groups', array('engine' => 'File', 'duration' => 3600, 'groups' => array('group_a', 'group_b')));
$this->assertTrue(Cache::write('test_groups', 'value', 'file_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'file_groups'));
$this->assertTrue(Cache::delete('test_groups', 'file_groups'));
$this->assertFalse(Cache::read('test_groups', 'file_groups'));
}
/**
* Test clearing a cache group
*
* @return void
**/
public function testGroupClear() {
Cache::config('file_groups', array('engine' => 'File', 'duration' => 3600, 'groups' => array('group_a', 'group_b')));
Cache::config('file_groups2', array('engine' => 'File', 'duration' => 3600, 'groups' => array('group_b')));
Cache::config('file_groups3', array('engine' => 'File', 'duration' => 3600, 'groups' => array('group_a')));
$this->assertTrue(Cache::write('test_groups', 'value', 'file_groups'));
$this->assertTrue(Cache::write('test_groups2', 'value', 'file_groups2'));
$this->assertTrue(Cache::write('test_groups3', 'value', 'file_groups3'));
$this->assertTrue(Cache::clearGroup('group_a', 'file_groups'));
$this->assertFalse(Cache::read('test_groups', 'file_groups'));
$this->assertEquals('value', Cache::read('test_groups2', 'file_groups2'));
$this->assertFalse(Cache::read('test_groups3', 'file_groups3'));
$this->assertTrue(Cache::write('test_groups4', 'value', 'file_groups'));
$this->assertTrue(Cache::write('test_groups5', 'value', 'file_groups2'));
$this->assertTrue(Cache::write('test_groups6', 'value', 'file_groups3'));
$this->assertTrue(Cache::clearGroup('group_b', 'file_groups'));
$this->assertFalse(Cache::read('test_groups4', 'file_groups'));
$this->assertFalse(Cache::read('test_groups5', 'file_groups2'));
$this->assertEquals('value', Cache::read('test_groups6', 'file_groups3'));
}
} }

View file

@ -72,6 +72,8 @@ class MemcacheEngineTest extends CakeTestCase {
parent::tearDown(); parent::tearDown();
Configure::write('Cache.disable', $this->_cacheDisable); Configure::write('Cache.disable', $this->_cacheDisable);
Cache::drop('memcache'); Cache::drop('memcache');
Cache::drop('memcache_groups');
Cache::drop('memcache_helper');
Cache::config('default'); Cache::config('default');
} }
@ -92,6 +94,7 @@ class MemcacheEngineTest extends CakeTestCase {
'compress' => false, 'compress' => false,
'engine' => 'Memcache', 'engine' => 'Memcache',
'persistent' => true, 'persistent' => true,
'groups' => array()
); );
$this->assertEquals($expecting, $settings); $this->assertEquals($expecting, $settings);
} }
@ -378,7 +381,7 @@ class MemcacheEngineTest extends CakeTestCase {
Cache::config('memcache', array('duration' => 0)); Cache::config('memcache', array('duration' => 0));
$result = Cache::write('test_key', 'written!', 'memcache'); $result = Cache::write('test_key', 'written!', 'memcache');
$this->assertTrue('Could not write with duration 0', $result); $this->assertTrue($result);
$result = Cache::read('test_key', 'memcache'); $result = Cache::read('test_key', 'memcache');
$this->assertEquals('written!', $result); $this->assertEquals('written!', $result);
} }
@ -402,4 +405,75 @@ class MemcacheEngineTest extends CakeTestCase {
$memcache->write('key', $value, 50 * DAY); $memcache->write('key', $value, 50 * DAY);
} }
/**
* Tests that configuring groups for stored keys return the correct values when read/written
* Shows that altering the group value is equivalent to deleting all keys under the same
* group
*
* @return void
*/
public function testGroupReadWrite() {
Cache::config('memcache_groups', array(
'engine' => 'Memcache',
'duration' => 3600,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
Cache::config('memcache_helper', array(
'engine' => 'Memcache',
'duration' => 3600,
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'memcache_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'memcache_groups'));
Cache::increment('group_a', 1, 'memcache_helper');
$this->assertFalse(Cache::read('test_groups', 'memcache_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'memcache_groups'));
$this->assertEquals('value2', Cache::read('test_groups', 'memcache_groups'));
Cache::increment('group_b', 1, 'memcache_helper');
$this->assertFalse(Cache::read('test_groups', 'memcache_groups'));
$this->assertTrue(Cache::write('test_groups', 'value3', 'memcache_groups'));
$this->assertEquals('value3', Cache::read('test_groups', 'memcache_groups'));
}
/**
* Tests that deleteing from a groups-enabled config is possible
*
* @return void
*/
public function testGroupDelete() {
Cache::config('memcache_groups', array(
'engine' => 'Memcache',
'duration' => 3600,
'groups' => array('group_a', 'group_b')
));
$this->assertTrue(Cache::write('test_groups', 'value', 'memcache_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'memcache_groups'));
$this->assertTrue(Cache::delete('test_groups', 'memcache_groups'));
$this->assertFalse(Cache::read('test_groups', 'memcache_groups'));
}
/**
* Test clearing a cache group
*
* @return void
**/
public function testGroupClear() {
Cache::config('memcache_groups', array(
'engine' => 'Memcache',
'duration' => 3600,
'groups' => array('group_a', 'group_b')
));
$this->assertTrue(Cache::write('test_groups', 'value', 'memcache_groups'));
$this->assertTrue(Cache::clearGroup('group_a', 'memcache_groups'));
$this->assertFalse(Cache::read('test_groups', 'memcache_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'memcache_groups'));
$this->assertTrue(Cache::clearGroup('group_b', 'memcache_groups'));
$this->assertFalse(Cache::read('test_groups', 'memcache_groups'));
}
} }

View file

@ -48,6 +48,7 @@ class WincacheEngineTest extends CakeTestCase {
parent::tearDown(); parent::tearDown();
Configure::write('Cache.disable', $this->_cacheDisable); Configure::write('Cache.disable', $this->_cacheDisable);
Cache::drop('wincache'); Cache::drop('wincache');
Cache::drop('wincache_groups');
Cache::config('default'); Cache::config('default');
} }
@ -190,4 +191,73 @@ class WincacheEngineTest extends CakeTestCase {
$this->assertFalse(Cache::read('some_value', 'wincache')); $this->assertFalse(Cache::read('some_value', 'wincache'));
$this->assertEquals('safe', wincache_ucache_get('not_cake')); $this->assertEquals('safe', wincache_ucache_get('not_cake'));
} }
/**
* Tests that configuring groups for stored keys return the correct values when read/written
* Shows that altering the group value is equivalent to deleting all keys under the same
* group
*
* @return void
*/
public function testGroupsReadWrite() {
Cache::config('wincache_groups', array(
'engine' => 'Wincache',
'duration' => 0,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'wincache_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'wincache_groups'));
wincache_ucache_inc('test_group_a');
$this->assertFalse(Cache::read('test_groups', 'wincache_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'wincache_groups'));
$this->assertEquals('value2', Cache::read('test_groups', 'wincache_groups'));
wincache_ucache_inc('test_group_b');
$this->assertFalse(Cache::read('test_groups', 'wincache_groups'));
$this->assertTrue(Cache::write('test_groups', 'value3', 'wincache_groups'));
$this->assertEquals('value3', Cache::read('test_groups', 'wincache_groups'));
}
/**
* Tests that deleteing from a groups-enabled config is possible
*
* @return void
*/
public function testGroupDelete() {
Cache::config('wincache_groups', array(
'engine' => 'Wincache',
'duration' => 0,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'wincache_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'wincache_groups'));
$this->assertTrue(Cache::delete('test_groups', 'wincache_groups'));
$this->assertFalse(Cache::read('test_groups', 'wincache_groups'));
}
/**
* Test clearing a cache group
*
* @return void
**/
public function testGroupClear() {
Cache::config('wincache_groups', array(
'engine' => 'Wincache',
'duration' => 0,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'wincache_groups'));
$this->assertTrue(Cache::clearGroup('group_a', 'wincache_groups'));
$this->assertFalse(Cache::read('test_groups', 'wincache_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'wincache_groups'));
$this->assertTrue(Cache::clearGroup('group_b', 'wincache_groups'));
$this->assertFalse(Cache::read('test_groups', 'wincache_groups'));
}
} }

View file

@ -36,6 +36,7 @@ class XcacheEngineTest extends CakeTestCase {
if (!function_exists('xcache_set')) { if (!function_exists('xcache_set')) {
$this->markTestSkipped('Xcache is not installed or configured properly'); $this->markTestSkipped('Xcache is not installed or configured properly');
} }
$this->_cacheDisable = Configure::read('Cache.disable');
Configure::write('Cache.disable', false); Configure::write('Cache.disable', false);
Cache::config('xcache', array('engine' => 'Xcache', 'prefix' => 'cake_')); Cache::config('xcache', array('engine' => 'Xcache', 'prefix' => 'cake_'));
} }
@ -47,7 +48,10 @@ class XcacheEngineTest extends CakeTestCase {
*/ */
public function tearDown() { public function tearDown() {
parent::tearDown(); parent::tearDown();
Configure::write('Cache.disable', $this->_cacheDisable);
Cache::drop('xcache'); Cache::drop('xcache');
Cache::drop('xcache_groups');
Cache::config('default');
} }
/** /**
@ -196,4 +200,73 @@ class XcacheEngineTest extends CakeTestCase {
$result = Cache::read('test_increment'); $result = Cache::read('test_increment');
$this->assertEquals(8, $result); $this->assertEquals(8, $result);
} }
/**
* Tests that configuring groups for stored keys return the correct values when read/written
* Shows that altering the group value is equivalent to deleting all keys under the same
* group
*
* @return void
*/
public function testGroupsReadWrite() {
Cache::config('xcache_groups', array(
'engine' => 'Xcache',
'duration' => 0,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'xcache_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'xcache_groups'));
xcache_inc('test_group_a', 1);
$this->assertFalse(Cache::read('test_groups', 'xcache_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'xcache_groups'));
$this->assertEquals('value2', Cache::read('test_groups', 'xcache_groups'));
xcache_inc('test_group_b', 1);
$this->assertFalse(Cache::read('test_groups', 'xcache_groups'));
$this->assertTrue(Cache::write('test_groups', 'value3', 'xcache_groups'));
$this->assertEquals('value3', Cache::read('test_groups', 'xcache_groups'));
}
/**
* Tests that deleteing from a groups-enabled config is possible
*
* @return void
*/
public function testGroupDelete() {
Cache::config('xcache_groups', array(
'engine' => 'Xcache',
'duration' => 0,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'xcache_groups'));
$this->assertEquals('value', Cache::read('test_groups', 'xcache_groups'));
$this->assertTrue(Cache::delete('test_groups', 'xcache_groups'));
$this->assertFalse(Cache::read('test_groups', 'xcache_groups'));
}
/**
* Test clearing a cache group
*
* @return void
**/
public function testGroupClear() {
Cache::config('xcache_groups', array(
'engine' => 'Xcache',
'duration' => 0,
'groups' => array('group_a', 'group_b'),
'prefix' => 'test_'
));
$this->assertTrue(Cache::write('test_groups', 'value', 'xcache_groups'));
$this->assertTrue(Cache::clearGroup('group_a', 'xcache_groups'));
$this->assertFalse(Cache::read('test_groups', 'xcache_groups'));
$this->assertTrue(Cache::write('test_groups', 'value2', 'xcache_groups'));
$this->assertTrue(Cache::clearGroup('group_b', 'xcache_groups'));
$this->assertFalse(Cache::read('test_groups', 'xcache_groups'));
}
} }

View file

@ -38,4 +38,7 @@ class TestAppCacheEngine extends CacheEngine {
public function clear($check) { public function clear($check) {
} }
public function clearGroup($group) {
}
} }

View file

@ -36,4 +36,6 @@ class TestPluginCacheEngine extends CacheEngine {
public function clear($check) { public function clear($check) {
} }
public function clearGroup($group) {
}
} }

View file

@ -43,6 +43,9 @@
echo 'Settings: <ul>'; echo 'Settings: <ul>';
foreach ($settings as $name => $value): foreach ($settings as $name => $value):
if (is_array($value)):
$value = join(',', $value);
endif;
echo '<li>' . $name . ': ' . $value . '</li>'; echo '<li>' . $name . ': ' . $value . '</li>';
endforeach; endforeach;
echo '</ul>'; echo '</ul>';