#276267: cache failures.

From: Damien Tournoud <damien@commerceguys.com>


---
 cache.inc                   |    2 -
 simpletest/tests/cache.test |  164 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 165 insertions(+), 1 deletions(-)

diff --git includes/cache.inc includes/cache.inc
index a625266..ce04cdb 100644
--- includes/cache.inc
+++ includes/cache.inc
@@ -389,7 +389,7 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
     // timer. The cache variable is loaded into the $user object by _drupal_session_read()
     // in session.inc. If the data is permanent or we're not enforcing a minimum
     // cache lifetime always return the cached data.
-    if ($cache->expire != CACHE_PERMANENT && variable_get('cache_lifetime', 0) && $user->cache > $cache->created) {
+    if ($cache->expire != CACHE_PERMANENT && variable_get('cache_lifetime', 0) && isset($user->cache) && $user->cache > $cache->created) {
       // This cache data is too old and thus not valid for us, ignore it.
       return FALSE;
     }
diff --git modules/simpletest/tests/cache.test modules/simpletest/tests/cache.test
index c533722..b75d3a0 100644
--- modules/simpletest/tests/cache.test
+++ modules/simpletest/tests/cache.test
@@ -349,3 +349,167 @@ class CacheIsEmptyCase extends CacheTestCase {
     $this->assertTrue(cache_is_empty($this->default_bin), t('The cache bin is empty'));
   }
 }
+
+class CacheExpiryCase extends CacheTestCase {
+  /**
+   * Implementation of getInfo().
+   */
+  function getInfo() {
+    return array(
+      'name' => t('Cache expire test'),
+      'description' => t('Check or the expiration of the cache is working properly'),
+      'group' => t('Cache')
+    );
+  }
+
+  /**
+   * Implementation of setUp().
+   */
+  function setUp() {
+    $this->default_table = 'cache';
+    $this->default_cid = 'test_expiry';
+    $this->default_value = $this->randomName(10);
+
+    parent::setUp();
+  }
+
+  /**
+   * testTemporaryNoLifetime()
+   * Tests the expiry of data when the $expire is set to CACHE_TEMPORARY and lifetime is off.
+   *   - CACHE_TEMPORARY: Indicates that the item should be removed at the next
+   *     general cache wipe.
+   */
+  function testTemporaryNoLifetime() {
+    global $user;
+
+    $this->setupLifetime(0);
+    cache_set($this->default_cid, $this->default_value, $this->default_table, CACHE_TEMPORARY);
+
+    $this->assertCacheExists(t('Temporary cache data without lifetime exists before wipe.'));
+
+    $user->cache = isset($user->cache) ? $user->cache + 2 : time() + 2;
+    $this->assertCacheExists(t('Temporary cache without lifetime valid after user cache expiration.'));
+    $user->cache = $user->cache - 2;
+
+    $this->generalWipe();
+    $this->assertCacheRemoved(t('Temporary cache without lifetime does not exists after wipe.'));
+  }
+
+  /**
+   * testTemporaryLifetime()
+   * Tests the expiry of data when the $expire is set to CACHE_TEMPORARY and lifetime is on.
+   *   - CACHE_TEMPORARY: Indicates that the item should be removed at the next
+   *     general cache wipe.
+   */
+  function testTemporaryLifetime() {
+    global $user;
+
+    $this->setupLifetime(5);
+    cache_set($this->default_cid, $this->default_value, $this->default_table, CACHE_TEMPORARY);
+
+    $this->assertCacheExists(t('Temporary cache with lifetime data exists before wipe.'));
+
+    $user->cache = isset($user->cache) ? $user->cache + 2 : time() + 2;
+    $this->assertCacheExists(t('Temporary cache without lifetime valid after user cache expiration.'));
+    $user->cache = $user->cache - 2;
+
+    $this->generalWipe();
+    $this->assertCacheRemoved(t('Temporary cache with lifetime does not exists after wipe.'));
+  }
+
+  /**
+   * testPermanentNoLifetime()
+   * Tests the expiry of data when the $expire is set to CACHE_PERMANENT and lifetime is off.
+   *   - CACHE_PERMANENT: Indicates that the item should never be removed unless
+   *     explicitly told to using cache_clear_all() with a cache ID.
+   */
+  function testPermanentNoLifetime() {
+    global $user;
+
+    $this->setupLifetime(0);
+    cache_set($this->default_cid, $this->default_value, $this->default_table, CACHE_PERMANENT);
+
+    $this->assertCacheExists(t('Permanent cache data without lifetime exists before wipe.'));
+
+    $user->cache = isset($user->cache) ? $user->cache + 2 : time() + 2;
+    $this->assertCacheExists(t('Permanent cache without lifetime valid after user cache expiration.'));
+    $user->cache = $user->cache - 2;
+
+    $this->generalWipe();
+    $this->assertCacheExists(t('Permanent cache without lifetime exists after wipe.'));
+  }
+
+  /**
+   * testPermanentLifetime()
+   * Tests the expiry of data when the $expire is set to CACHE_PERMANENT and lifetime is on.
+   *   - CACHE_PERMANENT: Indicates that the item should never be removed unless
+   *     explicitly told to using cache_clear_all() with a cache ID.
+   */
+  function testPermanentLifetime() {
+    global $user;
+
+    $this->setupLifetime(5);
+    cache_set($this->default_cid, $this->default_value, $this->default_table, CACHE_PERMANENT);
+
+    $this->assertCacheExists(t('Permanent cache data with lifetime exists before wipe.'));
+
+    $user->cache = isset($user->cache) ? $user->cache + 2 : time() + 2;
+    $this->assertCacheExists(t('Permanent cache with lifetime valid after user cache expiration.'));
+    $user->cache = $user->cache - 2;
+
+    $this->generalWipe();
+    $this->assertCacheExists(t('Permanent cache with lifetime exists after wipe.'));
+  }
+
+  /**
+   * testUnixTimestampNoLifetime()
+   * Tests the expiry of data when the $expire is set to unix timestamp and lifetime is off.
+   *   - A Unix timestamp: Indicates that the item should be kept at least until
+   *     the given time, after which it behaves like CACHE_TEMPORARY.
+   */
+  function testUnixTimestampNoLifetime() {
+    global $user;
+
+    $this->setupLifetime(0);
+    cache_set($this->default_cid, $this->default_value, $this->default_table, time() + 1);
+
+    $this->assertCacheExists(t('Unit timestamp cache data without lifetime exists before wipe.'));
+    $this->generalWipe();
+    $this->assertCacheExists(t('Unit timestamp cache without lifetime exists after wipe.'));
+    sleep(2); // expire
+    $this->assertCacheExists(t('Unit timestamp cache without lifetime exists after expiration.'));
+
+    $user->cache = isset($user->cache) ? $user->cache + 2 : time() + 2;
+    $this->assertCacheExists(t('Unit timestamp cache without lifetime valid after user cache expiration.'));
+    $user->cache = $user->cache - 2;
+
+    $this->generalWipe();
+    $this->assertCacheRemoved(t('Unit timestamp cache without lifetime deleted after expiration and wipe.'));
+  }
+
+  /**
+   * testUnixTimestampLifetime()
+   * Tests the expiry of data when the $expire is set to unix timestamp and lifetime is on.
+   *   - A Unix timestamp: Indicates that the item should be kept at least until
+   *     the given time, after which it behaves like CACHE_TEMPORARY.
+   */
+  function testUnixTimestampLifetime() {
+    global $user;
+
+    $this->setupLifetime(5);
+    cache_set($this->default_cid, $this->default_value, $this->default_table, time() + 1);
+
+    $this->assertCacheExists(t('Unit timestamp cache data without lifetime exists before wipe.'));
+    $this->generalWipe();
+    $this->assertCacheExists(t('Unit timestamp cache with lifetime exists after wipe.'));
+    sleep(2); // expire
+    $this->assertCacheExists(t('Unit timestamp cache with lifetime exists after expiration.'));
+
+    $user->cache = $user->cache + 2;
+    $this->assertCacheRemoved(t('Unit timestamp cache with lifetime not valid after user cache expiration.'));
+    $user->cache = $user->cache - 2;
+
+    $this->generalWipe();
+    $this->assertCacheRemoved(t('Unit timestamp cache with lifetime deleted after expiration and wipe.'));
+  }
+}
