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 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Cache\ArrayBackend.
+ */
+
+namespace Drupal\Core\Cache;
+
+/**
+ * Defines a memory cache implementation.
+ *
+ * Stores cache items in a PHP array.
+ *
+ * Should be used for unit tests and specialist use-cases only, does not
+ * store cached items between requests.
+ *
+ */
+class ArrayBackend implements CacheBackendInterface {
+
+  /**
+   * Array to store cache objects.
+   */
+  protected $cache;
+
+  /**
+   * All tags invalidated during the request.
+   */
+  protected $invalidated_tags = array();
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::__construct().
+   */
+  public function __construct($bin) {
+  }
+
+  /**
+   * Implements Drupal\Core\Cache\CacheBackendInterface::get().
+   */
+  public function get($cid) {
+    if (isset($this->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 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Cache\ArrayBackendUnitTestCase.
+ */
+
+namespace Drupal\system\Tests\Cache;
+
+use Drupal\Core\Cache\ArrayBackend;
+
+/**
+ * Tests ArrayBackend using GenericBackendUnitTestBase.
+ */
+class ArrayBackendUnitTestCase extends GenericBackendUnitTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => '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 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Cache\DatabaseBackendUnitTestCase.
+ */
+
+namespace Drupal\system\Tests\Cache;
+
+use Drupal\Core\Cache\DatabaseBackend;
+
+/**
+ * Tests DatabaseBackend using GenericBackendUnitTestBase.
+ */
+class DatabaseBackendUnitTestCase extends GenericBackendUnitTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => '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..56d9ba7
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Cache/GenericBackendUnitTestBase.php
@@ -0,0 +1,451 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Cache\GenericBackendUnitTestBase.
+ */
+
+namespace Drupal\system\Tests\Cache;
+
+use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\simpletest\UnitTestBase;
+
+use \stdClass;
+
+/**
+ * Full generic unit test suite for any cache backend. In order to use it for a
+ * cache backend implementation extend this class and override the
+ * createBackendInstace() method to return an object.
+ *
+ * @see DatabaseBackendUnitTestCase
+ *   For a full working implementation.
+ */
+abstract class GenericBackendUnitTestBase extends UnitTestBase {
+
+  /**
+   * Array of objects implementing Drupal\Core\Cache\CacheBackendInterface.
+   *
+   * @var array
+   */
+  protected $cachebackends;
+
+  /**
+   * Cache bin to use for testing.
+   *
+   * @var string
+   */
+  protected $testBin;
+
+  /**
+   * Random value to use in tests.
+   *
+   * @var string
+   */
+  protected $defaultValue;
+
+  /**
+   * Get testing bin.
+   *
+   * Override this method if you want to work on a different bin than the
+   * default one.
+   *
+   * @return string
+   *   Bin name.
+   */
+  protected function getTestBin() {
+    if (!isset($this->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,
+    );
+
+    // Create cache entries.
+    foreach ($variables as $cid => $data) {
+      $backend->set($cid, $data);
+    }
+
+    // Retrieve and test cache objects.
+    foreach ($variables as $cid => $value) {
+      $object = $backend->get($cid);
+      $this->assert(is_object($object), sprintf("Backend returned an object for cache id %s.", $cid));
+      $this->assertIdentical($value, $object->data, sprintf("Data of cached id %s kept is identical in type and value", $cid));
+    }
+  }
+
+  /**
+   * 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);
+    // Test return
+    $this->assert(isset($ret['test3']), "Existing key 3 is set");
+    $this->assert(isset($ret['test7']), "Existing key 7 is set");
+    $this->assertFalse(isset($ret['test21']), "Non existing key 21 is not set");
+    $this->assert(isset($ret['test6']), "Existing key 6 is set");
+    $this->assertFalse(isset($ret['test19']), "Non existing key 19 is not set");
+    $this->assert(isset($ret['test2']), "Existing key 2 is set");
+    // Test values
+    $this->assertIdentical($ret['test3']->data, 5, "Existing key 3 has the correct value");
+    $this->assertIdentical($ret['test7']->data, 17, "Existing key 7 has the correct value");
+    $this->assertIdentical($ret['test6']->data, 13, "Existing key 6 has the correct value");
+    $this->assertIdentical($ret['test2']->data, 3, "Existing key 2 has the correct value");
+    // Test $cids array
+    $this->assertFalse(in_array('test3', $cids), "Existing key 3 is not referenced");
+    $this->assertFalse(in_array('test7', $cids), "Existing key 7 is not referenced");
+    $this->assert(in_array('test21', $cids), "Non existing key 21 is referenced");
+    $this->assertFalse(in_array('test6', $cids), "Existing key 6 is not referenced");
+    $this->assert(in_array('test19', $cids), "Non existing key 19 is referenced");
+    $this->assertFalse(in_array('test2', $cids), "Existing key 2 is not referenced");
+
+    // Proceed the test a second time after deleting and setting new keys
+    // (ensures no static cache stall).
+    $backend->delete('test3');
+    $backend->delete('test6');
+    $backend->set('test19', 57);
+
+    $cids = $reference;
+    $ret = $backend->getMultiple($cids);
+    // Test return
+    $this->assertFalse(isset($ret['test3']), "Removed key 3 is not set");
+    $this->assert(isset($ret['test7']), "Existing key 7 is set");
+    $this->assertFalse(isset($ret['test21']), "Non existing key 21 is not set");
+    $this->assertFalse(isset($ret['test6']), "Removed key 6 is not set");
+    $this->assert(isset($ret['test19']), "Added key 19 is set");
+    $this->assert(isset($ret['test2']), "Existing key 2 is set");
+    // Test values
+    $this->assertIdentical($ret['test7']->data, 17, "Existing key 7 has the correct value");
+    $this->assertIdentical($ret['test19']->data, 57, "Added key 19 has the correct value");
+    $this->assertIdentical($ret['test2']->data, 3, "Existing key 2 has the correct value");
+    // Test $cids array
+    $this->assert(in_array('test3', $cids), "Removed key 3 is referenced");
+    $this->assertFalse(in_array('test7', $cids), "Existing key 7 is not referenced");
+    $this->assert(in_array('test21', $cids), "Non existing key 21 is referenced");
+    $this->assert(in_array('test6', $cids), "Removed key 6 is referenced");
+    $this->assertFalse(in_array('test19', $cids), "Added key 19 is not referenced");
+    $this->assertFalse(in_array('test2', $cids), "Existing key 2 is not referenced");
+  }
+
+  /**
+   * 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 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Cache\GetMultipleTest.
- */
-
-namespace Drupal\system\Tests\Cache;
-
-/**
- * Tests getMultiple().
- */
-class GetMultipleTest extends CacheTestBase {
-
-  public static function getInfo() {
-    return array(
-      'name' => '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 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Cache\IsEmptyTest.
- */
-
-namespace Drupal\system\Tests\Cache;
-
-/**
- * Tests the isEmpty() method.
- */
-class IsEmptyTest extends CacheTestBase {
-  public static function getInfo() {
-    return array(
-      'name' => '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 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\system\Tests\Cache\SavingTest.
- */
-
-namespace Drupal\system\Tests\Cache;
-
-use stdClass;
-
-/**
- * Tests that variables are saved and restored in the right way.
- */
-class SavingTest extends CacheTestBase {
-  public static function getInfo() {
-    return array(
-      'name' => '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.'));
-  }
-}
