diff --git a/core/lib/Drupal/Core/Cache/ArrayBackend.php b/core/lib/Drupal/Core/Cache/ArrayBackend.php new file mode 100644 index 0000000..46ba62e --- /dev/null +++ b/core/lib/Drupal/Core/Cache/ArrayBackend.php @@ -0,0 +1,238 @@ +cache[$cid])) { + return $this->prepareItem($this->cache[$cid]); + } + else { + return FALSE; + } + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::getMultiple(). + */ + public function getMultiple(&$cids) { + $ret = array(); + + $items = array_intersect_key($this->cache, array_flip($cids)); + + foreach ($items as $item) { + $item = $this->prepareItem($item); + if ($item) { + $ret[$item->cid] = $item; + } + } + + $cids = array_diff($cids, array_keys($ret)); + + return $ret; + } + + /** + * Prepares a cached item. + * + * Checks that items are either permanent or did not expire, and returns data + * as appropriate. + * + * @param stdClass $cache + * An item loaded from cache_get() or cache_get_multiple(). + * + * @return mixed + * The item with data as appropriate or FALSE if there is no + * valid item to load. + */ + protected function prepareItem($cache) { + if (!isset($cache->data)) { + return FALSE; + } + + // The cache data is invalid if any of its tags have been cleared since. + if (count($cache->tags) && $this->hasInvalidatedTags($cache)) { + return FALSE; + } + + return $cache; + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::set(). + */ + public function set($cid, $data, $expire = CACHE_PERMANENT, array $tags = array()) { + $this->cache[$cid] = (object) array( + 'cid' => $cid, + 'data' => $data, + 'expire' => $expire, + 'tags' => $tags, + 'checksum' => $this->checksum($this->flattenTags($tags)), + ); + } + + /* + * Calculates a checksum so data can be invalidated using tags. + */ + function checksum($tags) { + $checksum = ""; + + foreach($tags as $tag) { + // Has the tag already been invalidated. + if (isset($this->invalidated_tags[$tag])) { + $checksum = $checksum . $tag . ':' . $this->invalidated_tags[$tag]; + } + } + + return $checksum; + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::delete(). + */ + public function delete($cid) { + unset($this->cache[$cid]); + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::deleteMultiple(). + */ + public function deleteMultiple(array $cids) { + $this->cache = array_diff_key($this->cache, array_flip($cids)); + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::deletePrefix(). + */ + public function deletePrefix($prefix) { + foreach ($this->cache as $cid => $item) { + if (strpos($cid, $prefix) === 0) { + unset($this->cache[$cid]); + } + } + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::flush(). + */ + public function flush() { + $this->cache = array(); + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::expire(). + * + * Cache expiration is not implemented for PHP ArrayBackend as this backend + * only persists during a single request and expiration are done using + * REQUEST_TIME. + */ + public function expire() { + } + + /** + * Checks to see if any of the tags associated with a cache object have been + * invalidated. + * + * @param object @cache + * An cache object to calculate and compare it's original checksum for. + * + * @return boolean + * TRUE if the a tag has been invalidated, FALSE otherwise. + */ + protected function hasInvalidatedTags($cache) { + if ($cache->checksum != $this->checksum($this->flattenTags($cache->tags))) { + return TRUE; + } + return FALSE; + } + + /** + * Flattens a tags array into a numeric array suitable for string storage. + * + * @param array $tags + * Associative array of tags to flatten. + * + * @return + * An array of flattened tag identifiers. + */ + protected function flattenTags(array $tags) { + if (isset($tags[0])) { + return $tags; + } + + $flat_tags = array(); + foreach ($tags as $namespace => $values) { + if (is_array($values)) { + foreach ($values as $value) { + $flat_tags["$namespace:$value"] = "$namespace:$value"; + } + } + else { + $flat_tags["$namespace:$value"] = "$namespace:$values"; + } + } + return $flat_tags; + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). + */ + public function invalidateTags(array $tags) { + $flat_tags = $this->flattenTags($tags); + foreach($flat_tags as $tag) { + if (isset($this->invalidated_tags[$tag])) { + $this->invalidated_tags[$tag] = $this->invalidated_tags[$tag] + 1; + } + else { + $this->invalidated_tags[$tag] = 1; + } + } + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::isEmpty(). + */ + public function isEmpty() { + return empty($this->cache); + } + + /** + * Implements Drupal\Core\Cache\CacheBackendInterface::garbageCollection() + */ + public function garbageCollection() { + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/ArrayBackendUnitTestCase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/ArrayBackendUnitTestCase.php new file mode 100644 index 0000000..db306e7 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/ArrayBackendUnitTestCase.php @@ -0,0 +1,28 @@ + 'Array cache backend', + 'description' => 'Unit test of the array cache backend using the generic cache unit test case.', + 'group' => 'Cache', + ); + } + + protected function createCacheBackend($bin) { + return new ArrayBackend($bin); + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php index 9046557..e4b275e 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/CacheTestBase.php @@ -13,6 +13,7 @@ use Drupal\simpletest\WebTestBase; * Provides helper methods for cache tests. */ abstract class CacheTestBase extends WebTestBase { + protected $default_bin = 'page'; protected $default_cid = 'test_temporary'; protected $default_value = 'CacheTest'; diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/ClearTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/ClearTest.php index ea9b02e..4f7cfca 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/ClearTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/ClearTest.php @@ -11,6 +11,7 @@ namespace Drupal\system\Tests\Cache; * Tests cache clearing methods. */ class ClearTest extends CacheTestBase { + public static function getInfo() { return array( 'name' => 'Cache clear test', @@ -27,83 +28,6 @@ class ClearTest extends CacheTestBase { } /** - * Test clearing using a cid. - */ - function testClearCid() { - $cache = cache($this->default_bin); - $cache->set('test_cid_clear', $this->default_value); - - $this->assertCacheExists(t('Cache was set for clearing cid.'), $this->default_value, 'test_cid_clear'); - $cache->delete('test_cid_clear'); - - $this->assertCacheRemoved(t('Cache was removed after clearing cid.'), 'test_cid_clear'); - } - - /** - * Test clearing using wildcard. - */ - function testClearWildcard() { - $cache = cache($this->default_bin); - $cache->set('test_cid_clear1', $this->default_value); - $cache->set('test_cid_clear2', $this->default_value); - $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value) - && $this->checkCacheExists('test_cid_clear2', $this->default_value), - t('Two caches were created for checking cid "*" with wildcard true.')); - $cache->flush(); - $this->assertFalse($this->checkCacheExists('test_cid_clear1', $this->default_value) - || $this->checkCacheExists('test_cid_clear2', $this->default_value), - t('Two caches removed after clearing cid "*" with wildcard true.')); - - $cache->set('test_cid_clear1', $this->default_value); - $cache->set('test_cid_clear2', $this->default_value); - $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value) - && $this->checkCacheExists('test_cid_clear2', $this->default_value), - t('Two caches were created for checking cid substring with wildcard true.')); - $cache->deletePrefix('test_'); - $this->assertFalse($this->checkCacheExists('test_cid_clear1', $this->default_value) - || $this->checkCacheExists('test_cid_clear2', $this->default_value), - t('Two caches removed after clearing cid substring with wildcard true.')); - } - - /** - * Test clearing using an array. - */ - function testClearArray() { - // Create three cache entries. - $cache = cache($this->default_bin); - $cache->set('test_cid_clear1', $this->default_value); - $cache->set('test_cid_clear2', $this->default_value); - $cache->set('test_cid_clear3', $this->default_value); - $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value) - && $this->checkCacheExists('test_cid_clear2', $this->default_value) - && $this->checkCacheExists('test_cid_clear3', $this->default_value), - t('Three cache entries were created.')); - - // Clear two entries using an array. - $cache->deleteMultiple(array('test_cid_clear1', 'test_cid_clear2')); - $this->assertFalse($this->checkCacheExists('test_cid_clear1', $this->default_value) - || $this->checkCacheExists('test_cid_clear2', $this->default_value), - t('Two cache entries removed after clearing with an array.')); - - $this->assertTrue($this->checkCacheExists('test_cid_clear3', $this->default_value), - t('Entry was not cleared from the cache')); - - // Set the cache clear threshold to 2 to confirm that the full bin is cleared - // when the threshold is exceeded. - variable_set('cache_clear_threshold', 2); - $cache->set('test_cid_clear1', $this->default_value); - $cache->set('test_cid_clear2', $this->default_value); - $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value) - && $this->checkCacheExists('test_cid_clear2', $this->default_value), - t('Two cache entries were created.')); - $cache->deleteMultiple(array('test_cid_clear1', 'test_cid_clear2', 'test_cid_clear3')); - $this->assertFalse($this->checkCacheExists('test_cid_clear1', $this->default_value) - || $this->checkCacheExists('test_cid_clear2', $this->default_value) - || $this->checkCacheExists('test_cid_clear3', $this->default_value), - t('All cache entries removed when the array exceeded the cache clear threshold.')); - } - - /** * Test drupal_flush_all_caches(). */ function testFlushAllCaches() { @@ -124,49 +48,4 @@ class ClearTest extends CacheTestBase { $this->assertFalse($this->checkCacheExists($cid, $this->default_value, $bin), t('All cache entries removed from @bin.', array('@bin' => $bin))); } } - - /** - * Test clearing using cache tags. - */ - function testClearTags() { - $cache = cache($this->default_bin); - $cache->set('test_cid_clear1', $this->default_value, CACHE_PERMANENT, array('test_tag' => array(1))); - $cache->set('test_cid_clear2', $this->default_value, CACHE_PERMANENT, array('test_tag' => array(1))); - $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value) - && $this->checkCacheExists('test_cid_clear2', $this->default_value), - t('Two cache items were created.')); - cache_invalidate(array('test_tag' => array(1))); - $this->assertFalse($this->checkCacheExists('test_cid_clear1', $this->default_value) - || $this->checkCacheExists('test_cid_clear2', $this->default_value), - t('Two caches removed after clearing a cache tag.')); - - $cache->set('test_cid_clear1', $this->default_value, CACHE_PERMANENT, array('test_tag' => array(1))); - $cache->set('test_cid_clear2', $this->default_value, CACHE_PERMANENT, array('test_tag' => array(2))); - $cache->set('test_cid_clear3', $this->default_value, CACHE_PERMANENT, array('test_tag_foo' => array(3))); - $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value) - && $this->checkCacheExists('test_cid_clear2', $this->default_value) - && $this->checkCacheExists('test_cid_clear3', $this->default_value), - t('Two cached items were created.')); - cache_invalidate(array('test_tag_foo' => array(3))); - $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value) - && $this->checkCacheExists('test_cid_clear2', $this->default_value), - t('Cached items not matching the tag were not cleared.')); - - $this->assertFalse($this->checkCacheExists('test_cid_clear3', $this->default_value), - t('Cached item matching the tag was removed.')); - - // For our next trick, we will attempt to clear data in multiple bins. - $tags = array('test_tag' => array(1, 2, 3)); - $bins = array('cache', 'cache_page', 'cache_bootstrap'); - foreach ($bins as $bin) { - cache($bin)->set('test', $this->default_value, CACHE_PERMANENT, $tags); - $this->assertTrue($this->checkCacheExists('test', $this->default_value, $bin), 'Cache item was set in bin.'); - } - cache_invalidate(array('test_tag' => array(2))); - foreach ($bins as $bin) { - $this->assertFalse($this->checkCacheExists('test', $this->default_value, $bin), 'Tag expire affected item in bin.'); - } - $this->assertFalse($this->checkCacheExists('test_cid_clear2', $this->default_value), 'Cached items matching tag were cleared.'); - $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value), 'Cached items not matching tag were not cleared.'); - } } diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTestCase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTestCase.php new file mode 100644 index 0000000..e535540 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/DatabaseBackendUnitTestCase.php @@ -0,0 +1,36 @@ + 'Database backend', + 'description' => 'Unit test of the database backend using the generic cache unit test case.', + 'group' => 'Cache', + ); + } + + protected function createCacheBackend($bin) { + return new DatabaseBackend($bin); + } + + public function setUpCacheBackend() { + drupal_install_schema('system'); + } + + public function tearDownCacheBackend() { + drupal_uninstall_schema('system'); + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/GenericBackendUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericBackendUnitTestBase.php new file mode 100644 index 0000000..ae59f01 --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericBackendUnitTestBase.php @@ -0,0 +1,478 @@ +testBin)) { + $this->testBin = 'page'; + } + return $this->testBin; + } + + /** + * Create a cache backend to test. + * + * Override this method to test a CacheBackend. + * + * @param string $bin + * Bin name to use for this backend instance. + * + * @return Drupal\Core\Cache\CacheBackendInterface + * Cache backend to test. + */ + protected abstract function createCacheBackend($bin); + + /** + * Allow specific implementation to change the environement before test run. + */ + public function setUpCacheBackend() { + } + + /** + * Allow specific implementation to alter the environement after test run but + * before the real tear down, which will changes things such as the database + * prefix. + */ + public function tearDownCacheBackend() { + } + + /** + * Get backend to test, this will get a shared instance set in the object. + * This method should not be overridden. + * + * @return Drupal\Core\Cache\CacheBackendInterface + * Cache backend to test. + */ + protected function getCacheBackend($bin = null) { + if (!isset($bin)) { + $bin = $this->getTestBin(); + } + if (!isset($this->cachebackends[$bin])) { + $this->cachebackends[$bin] = $this->createCacheBackend($bin); + // Ensure the backend is empty. + $this->cachebackends[$bin]->flush(); + } + return $this->cachebackends[$bin]; + } + + public function setUp() { + $this->cachebackends = array(); + $this->defaultValue = $this->randomName(10); + + parent::setUp(); + + $this->setUpCacheBackend(); + } + + public function tearDown() { + // Destruct the registered backend, each test will get a fresh instance, + // properly flushing it here ensure that on persistant data backends they + // will come up empty the next test. + foreach ($this->cachebackends as $bin => $cachebackend) { + $this->cachebackends[$bin]->flush(); + } + unset($this->cachebackends); + + $this->tearDownCacheBackend(); + + parent::tearDown(); + } + + /** + * Test get and set methods. + */ + public function testSetGet() { + $backend = $this->getCacheBackend(); + + $data = 7; + $this->assertIdentical(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1."); + $backend->set('test1', $data); + $cached = $backend->get('test1'); + $this->assert(is_object($cached), "Backend returned an object for cache id test1."); + $this->assertIdentical($data, $cached->data); + + $data = array('value' => 3); + $this->assertIdentical(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2."); + $backend->set('test2', $data); + $cached = $backend->get('test2'); + $this->assert(is_object($cached), "Backend returned an object for cache id test2."); + $this->assertIdentical($data, $cached->data); + } + + /** + * Test delete. + */ + public function testDelete() { + $backend = $this->getCacheBackend(); + + $this->assertIdentical(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1."); + $backend->set('test1', 7); + $this->assert(is_object($backend->get('test1')), "Backend returned an object for cache id test1."); + + $this->assertIdentical(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2."); + $backend->set('test2', 3); + $this->assert(is_object($backend->get('test2')), "Backend returned an object for cache id %cid."); + + $backend->delete('test1'); + $this->assertIdentical(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1 after deletion."); + + $cached = $backend->get('test2'); + $this->assert(is_object($backend->get('test2')), "Backend still has an object for cache id test2."); + + $backend->delete('test2'); + $this->assertIdentical(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2 after deletion."); + } + + /** + * Test that data type is kept when saving. + */ + public function testValueTypeIsKept() { + $backend = $this->getCacheBackend(); + + $variables = array( + 'test1' => 1, + 'test2' => '0', + 'test3' => '', + 'test4' => 12.64, + 'test5' => false, + 'test6' => array(1,2,3), + ); + + // Create cache entries. + foreach ($variables as $cid => $data) { + $backend->set($cid, $data); + } + + // Retrieve and test cache objects. + foreach ($variables as $cid => $data) { + $object = $backend->get($cid); + $this->assert(is_object($object), format_string("Backend returned an object for cache id %cid.", array('%cid' => $cid))); + // Ensure that variable type has been persisted. + $this->assertIdentical($data, $object->data); + } + } + + /** + * Test get multiple feature. + */ + public function testGetMultiple() { + $backend = $this->getCacheBackend(); + + // Set numerous testing keys. + $backend->set('test1', 1); + $backend->set('test2', 3); + $backend->set('test3', 5); + $backend->set('test4', 7); + $backend->set('test5', 11); + $backend->set('test6', 13); + $backend->set('test7', 17); + + // Mismatch order for harder testing. + $reference = array( + 'test3', + 'test7', + 'test21', // Cid does not exist. + 'test6', + 'test19', // Cid does not exist until added before second getMulitple(). + 'test2', + ); + + $cids = $reference; + $ret = $backend->getMultiple($cids); + + // Cids that should be keys $ret array and not in $cid array. + $returned_cids = array( + 'test2', + 'test3', + 'test6', + 'test7', + ); + // Cids that should in $cid array and not keys $ret array. + $missing_cids = array( + 'test19', + 'test21', + ); + + foreach ($returned_cids as $cid) { + // Should be a key in $ret. + $this->assert(isset($ret[$cid]), format_string("Existing cache id %cid is set in return from getMultiple().", array('%cid' => $cid))); + // Should not be a value in $cids. + $this->assertFalse(in_array($cid, $cids), format_string("Existing cache id %cid is not a value in array passed to getMultiple().", array('%cid' => $cid))); + } + foreach ($missing_cids as $cid) { + // Should be a not be key in $ret. + $this->assertFalse(isset($ret[$cid]), format_string("Non existing cache id %cid is not set.", array('%cid' => $cid))); + // Should be a value in $cids. + $this->assertTrue(in_array($cid, $cids), format_string("Non existing cache id %cid is a value in array passed to getMultiple().", array('%cid' => $cid))); + } + + // Test return array values. + $this->assertIdentical($ret['test2']->data, 3, "Existing cache id test2 has the correct value."); + $this->assertIdentical($ret['test3']->data, 5, "Existing cache id test3 has the correct value."); + $this->assertIdentical($ret['test6']->data, 13, "Existing cache id test6 has the correct value."); + $this->assertIdentical($ret['test7']->data, 17, "Existing cache id test7 has the correct value."); + + // Proceed the test a second time after deleting and setting new keys which + // ensures no static cache stall. + $backend->delete('test3'); + $backend->delete('test6'); + $backend->set('test19', 57); + + $cids = $reference; + $ret = $backend->getMultiple($cids); + + // Cids that should be keys $ret array and not in $cid array. + $returned_cids = array( + 'test2', + 'test7', + 'test19' + ); + // Cids that should in $cid array and not keys $ret array. + $missing_cids = array( + 'test3', + 'test6', + 'test21', + ); + + foreach ($returned_cids as $cid) { + // Should be a key in $ret. + $this->assert(isset($ret[$cid]), format_string("Existing cache id %cid is set in return from getMultiple().", array('%cid' => $cid))); + // Should not be a value in $cids. + $this->assertFalse(in_array($cid, $cids), format_string("Existing cache id %cid is not a value in array passed to getMultiple().", array('%cid' => $cid))); + } + foreach ($missing_cids as $cid) { + // Should be a not be key in $ret. + $this->assertFalse(isset($ret[$cid]), format_string("Non existing cache id %cid is not set.", array('%cid' => $cid))); + // Should be a value in $cids. + $this->assertTrue(in_array($cid, $cids), format_string("Non existing cache id %cid is a value in array passed to getMultiple().", array('%cid' => $cid))); + } + + // Test return array values. + $this->assertIdentical($ret['test2']->data, 3, "Existing cache id test2 has the correct value."); + $this->assertIdentical($ret['test7']->data, 17, "Existing cache id test7 has the correct value."); + $this->assertIdentical($ret['test19']->data, 57, "Existing cache id test19 has the correct value."); + } + + /** + * Test is empty feature. + */ + public function testIsEmpty() { + $backend = $this->getCacheBackend(); + + $this->assertTrue($backend->isEmpty(), "Backend is empty"); + + $backend->set('pony', "Shetland"); + $this->assertFalse($backend->isEmpty(), "Backend is not empty"); + + $backend->delete('pony'); + $this->assertTrue($backend->isEmpty(), "Backend is empty"); + } + + /** + * Test delete multiple feature. + */ + public function testDeleteMultiple() { + $backend = $this->getCacheBackend(); + + // Set numerous testing keys. + $backend->set('test1', 1); + $backend->set('test2', 3); + $backend->set('test3', 5); + $backend->set('test4', 7); + $backend->set('test5', 11); + $backend->set('test6', 13); + $backend->set('test7', 17); + + $backend->deleteMultiple(array( + 'test1', + 'test3', + 'test5', + 'test7', + 'test19', // Non existing key should be silent + 'test21', // Non existing key should be silent + )); + + // Test if expected keys have been deleted. + $this->assertIdentical(FALSE, $backend->get('test1'), "Cache id test1 deleted."); + $this->assertIdentical(FALSE, $backend->get('test3'), "Cache id test3 deleted."); + $this->assertIdentical(FALSE, $backend->get('test5'), "Cache id test5 deleted."); + $this->assertIdentical(FALSE, $backend->get('test7'), "Cache id test7 deleted."); + + // Test if expected keys exist. + $this->assertNotIdentical(FALSE, $backend->get('test2'), "Cache id test2 exists."); + $this->assertNotIdentical(FALSE, $backend->get('test4'), "Cache id test4 exists."); + $this->assertNotIdentical(FALSE, $backend->get('test6'), "Cache id test6 exists."); + + // Test if that expected keys do not exist. + $this->assertIdentical(FALSE, $backend->get('test19'), "Cache id test19 does not exist."); + $this->assertIdentical(FALSE, $backend->get('test21'), "Cache id test21 does not exist."); + } + + /** + * Test delete prefix feature. + */ + public function testDeletePrefix() { + $backend = $this->getCacheBackend(); + + // Set numerous testing keys. + $backend->set('banana_test1', 1); + $backend->set('monkey_test2', 3); + $backend->set('monkey_banana_test3', 5); + $backend->set('banana_test_4', 7); + $backend->set('pony_monkey_test5_banana', 11); + $backend->set('monkey_test6', 13); + $backend->set('banana_pony_test7_monkey', 17); + + $backend->deletePrefix('banana'); + // Keys starting with banana have been deleted. + $this->assertIdentical(FALSE, $backend->get('banana_test1'), "Cache id banana_test1 deleted."); + $this->assertIdentical(FALSE, $backend->get('banana_test_4'), "Cache id banana_test_4 deleted."); + $this->assertIdentical(FALSE, $backend->get('banana_pony_test7_monkey'), "Cache id banana_pony_test7_monkey deleted."); + // Keys not starting with banana still exist. + $this->assertNotIdentical(FALSE, $backend->get('monkey_test2'), "Cache id monkey_test2 exists."); + $this->assertNotIdentical(FALSE, $backend->get('monkey_banana_test3'), "Cache id monkey_banana_test3 exists."); + $this->assertNotIdentical(FALSE, $backend->get('pony_monkey_test5_banana'), "Cache id poney_monkey_test5_banana exists."); + $this->assertNotIdentical(FALSE, $backend->get('monkey_test6'), "Cache id monkey_test6 exists."); + + $backend->deletePrefix('monkey'); + // Keys starting with monkey have been deleted. + $this->assertIdentical(FALSE, $backend->get('monkey_test2'), "Cache id monkey_test2 deleted."); + $this->assertIdentical(FALSE, $backend->get('monkey_banana_test3'), "Cache id monkey_banana_test3 deleted."); + $this->assertIdentical(FALSE, $backend->get('banana_pony_test7_monkey'), "Cache id banana_pony_test7_monkey deleted."); + // Keys not starting with monkey still exist. + $this->assertNotIdentical(FALSE, $backend->get('pony_monkey_test5_banana'), "Cache id pony_monkey_test5_banana exists."); + } + + /** + * Test flush prefix feature. + */ + public function testFlush() { + $backend = $this->getCacheBackend(); + + // Set both expiring and non expiring keys + $backend->set('test1', 1, CACHE_PERMANENT); + $backend->set('test2', 3, time() + 1000); + + $backend->flush(); + + $this->assertTrue($backend->isEmpty(), "Backend is empty after flush."); + + $this->assertIdentical(FALSE, $backend->get('test1'), "First key has been removed."); + $this->assertIdentical(FALSE, $backend->get('test2'), "Second key has been removed."); + } + + /** + * Check whether or not a cache entry exists. + * + * @param $cid + * The cache id. + * @param $bin + * The cache bin to use. If not provided the default test bin wil be used. + * + * @return + * TRUE on pass, FALSE on fail. + */ + protected function checkCacheExists($cid, $bin = null) { + $cached = $this->getCacheBackend($bin)->get($cid); + return isset($cached->data); + } + + /** + * Test clearing using cache tags. + */ + function testClearTags() { + $backend = $this->getCacheBackend(); + + $backend->set('test_cid_clear1', $this->defaultValue, CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_clear2', $this->defaultValue, CACHE_PERMANENT, array('test_tag' => array(1))); + $this->assertTrue($this->checkCacheExists('test_cid_clear1') + && $this->checkCacheExists('test_cid_clear2'), + 'Two cache items were created.'); + $backend->invalidateTags(array('test_tag' => array(1))); + $this->assertFalse($this->checkCacheExists('test_cid_clear1') + || $this->checkCacheExists('test_cid_clear2'), + 'Two caches removed after clearing a cache tag.'); + + $backend->set('test_cid_clear1', $this->defaultValue, CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_clear2', $this->defaultValue, CACHE_PERMANENT, array('test_tag' => array(2))); + $backend->set('test_cid_clear3', $this->defaultValue, CACHE_PERMANENT, array('test_tag_foo' => array(3))); + $this->assertTrue($this->checkCacheExists('test_cid_clear1') + && $this->checkCacheExists('test_cid_clear2') + && $this->checkCacheExists('test_cid_clear3'), + 'Two cached items were created.'); + $backend->invalidateTags(array('test_tag_foo' => array(3))); + $this->assertTrue($this->checkCacheExists('test_cid_clear1') + && $this->checkCacheExists('test_cid_clear2'), + 'Cached items not matching the tag were not cleared.'); + + $this->assertFalse($this->checkCacheExists('test_cid_clear3'), + 'Cached item matching the tag was removed.'); + + // Clear data from multiple bins. + $tags = array('test_tag' => array(1, 2, 3)); + $bins = array('path', 'bootstrap', 'page'); + foreach ($bins as $bin) { + $this->getCacheBackend($bin)->set('test', $this->defaultValue, CACHE_PERMANENT, $tags); + $this->assertTrue($this->checkCacheExists('test', $bin), 'Cache item was set in bin.'); + } + + foreach ($bins as $bin) { + $this->getCacheBackend($bin)->invalidateTags(array('test_tag' => array(2))); + } + + foreach ($bins as $bin) { + $this->assertFalse($this->checkCacheExists('test', $bin), 'Tag expire affected item in bin.'); + } + $this->assertFalse($this->checkCacheExists('test_cid_clear2', $bin), 'Cached items matching tag were cleared.'); + $this->assertTrue($this->checkCacheExists('test_cid_clear1', $bin), 'Cached items not matching tag were not cleared.'); + } +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/GetMultipleTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/GetMultipleTest.php deleted file mode 100644 index f981212..0000000 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/GetMultipleTest.php +++ /dev/null @@ -1,56 +0,0 @@ - 'Fetching multiple cache items', - 'description' => 'Confirm that multiple records are fetched correctly.', - 'group' => 'Cache', - ); - } - - function setUp() { - $this->default_bin = 'page'; - parent::setUp(); - } - - /** - * Test getMultiple(). - */ - function testCacheMultiple() { - $item1 = $this->randomName(10); - $item2 = $this->randomName(10); - $cache = cache($this->default_bin); - $cache->set('item1', $item1); - $cache->set('item2', $item2); - $this->assertTrue($this->checkCacheExists('item1', $item1), t('Item 1 is cached.')); - $this->assertTrue($this->checkCacheExists('item2', $item2), t('Item 2 is cached.')); - - // Fetch both records from the database with getMultiple(). - $item_ids = array('item1', 'item2'); - $items = $cache->getMultiple($item_ids); - $this->assertEqual($items['item1']->data, $item1, t('Item was returned from cache successfully.')); - $this->assertEqual($items['item2']->data, $item2, t('Item was returned from cache successfully.')); - - // Remove one item from the cache. - $cache->delete('item2'); - - // Confirm that only one item is returned by getMultiple(). - $item_ids = array('item1', 'item2'); - $items = $cache->getMultiple($item_ids); - $this->assertEqual($items['item1']->data, $item1, t('Item was returned from cache successfully.')); - $this->assertFalse(isset($items['item2']), t('Item was not returned from the cache.')); - $this->assertTrue(count($items) == 1, t('Only valid cache entries returned.')); - } -} diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/IsEmptyTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/IsEmptyTest.php deleted file mode 100644 index bd0d6ca..0000000 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/IsEmptyTest.php +++ /dev/null @@ -1,46 +0,0 @@ - 'Cache emptiness test', - 'description' => 'Check if a cache bin is empty after performing clear operations.', - 'group' => 'Cache' - ); - } - - function setUp() { - $this->default_bin = 'page'; - $this->default_value = $this->randomName(10); - - parent::setUp(); - } - - /** - * Test clearing using a cid. - */ - function testIsEmpty() { - // Clear the cache bin. - $cache = cache($this->default_bin); - $cache->flush(); - $this->assertTrue($cache->isEmpty(), t('The cache bin is empty')); - // Add some data to the cache bin. - $cache->set($this->default_cid, $this->default_value); - $this->assertCacheExists(t('Cache was set.'), $this->default_value, $this->default_cid); - $this->assertFalse($cache->isEmpty(), t('The cache bin is not empty')); - // Remove the cached data. - $cache->delete($this->default_cid); - $this->assertCacheRemoved(t('Cache was removed.'), $this->default_cid); - $this->assertTrue($cache->isEmpty(), t('The cache bin is empty')); - } -} diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/NullBackendTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/NullBackendTest.php index 5a42e5d..3882401 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/NullBackendTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Cache/NullBackendTest.php @@ -14,6 +14,7 @@ use Drupal\simpletest\UnitTestBase; * Tests the cache NullBackend. */ class NullBackendTest extends UnitTestBase { + public static function getInfo() { return array( 'name' => 'Cache NullBackend test', diff --git a/core/modules/system/lib/Drupal/system/Tests/Cache/SavingTest.php b/core/modules/system/lib/Drupal/system/Tests/Cache/SavingTest.php deleted file mode 100644 index 410de25..0000000 --- a/core/modules/system/lib/Drupal/system/Tests/Cache/SavingTest.php +++ /dev/null @@ -1,83 +0,0 @@ - 'Cache saving test', - 'description' => 'Check our variables are saved and restored the right way.', - 'group' => 'Cache' - ); - } - - /** - * Test the saving and restoring of a string. - */ - function testString() { - $this->checkVariable($this->randomName(100)); - } - - /** - * Test the saving and restoring of an integer. - */ - function testInteger() { - $this->checkVariable(100); - } - - /** - * Test the saving and restoring of a double. - */ - function testDouble() { - $this->checkVariable(1.29); - } - - /** - * Test the saving and restoring of an array. - */ - function testArray() { - $this->checkVariable(array('drupal1', 'drupal2' => 'drupal3', 'drupal4' => array('drupal5', 'drupal6'))); - } - - /** - * Test the saving and restoring of an object. - */ - function testObject() { - $test_object = new stdClass(); - $test_object->test1 = $this->randomName(100); - $test_object->test2 = 100; - $test_object->test3 = array('drupal1', 'drupal2' => 'drupal3', 'drupal4' => array('drupal5', 'drupal6')); - - - cache()->set('test_object', $test_object); - $cached = cache()->get('test_object'); - $this->assertTrue(isset($cached->data) && $cached->data == $test_object, t('Object is saved and restored properly.')); - } - - /** - * Check or a variable is stored and restored properly. - */ - function checkVariable($var) { - cache()->set('test_var', $var); - $cached = cache()->get('test_var'); - $this->assertTrue(isset($cached->data) && $cached->data === $var, t('@type is saved and restored properly.', array('@type' => ucfirst(gettype($var))))); - } - - /** - * Test no empty cids are written in cache table. - */ - function testNoEmptyCids() { - $this->drupalGet('user/register'); - $this->assertFalse(cache()->get(''), t('No cache entry is written with an empty cid.')); - } -}