diff --git a/.travis.yml b/.travis.yml index f17a990518..5f772c4c13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ before_script: - psql -c 'create database zftest;' -U postgres - echo "extension = memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + - echo "extension = redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - cp ./tests/TestConfiguration.travis.php ./tests/TestConfiguration.php script: @@ -29,6 +30,5 @@ script: matrix: allow_failures: - - php: 5.6 - php: 7.0 - php: hhvm diff --git a/library/Zend/Cache/Backend/RedisCluster.php b/library/Zend/Cache/Backend/RedisCluster.php new file mode 100644 index 0000000000..0cf88ea985 --- /dev/null +++ b/library/Zend/Cache/Backend/RedisCluster.php @@ -0,0 +1,523 @@ + + */ + +/** + * @see Zend_Cache_Backend_Interface + */ +require_once 'Zend/Cache/Backend/ExtendedInterface.php'; + +/** + * @see Zend_Cache_Backend + */ +require_once 'Zend/Cache/Backend.php'; + +class Zend_Cache_Backend_RedisCluster extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface +{ + /** + * Default Values + */ + const DEFAULT_HOST = '127.0.0.1'; + const DEFAULT_PORT = 30001; + const DEFAULT_TIMEOUT = 1.5; + const DEFAULT_READ_TIMEOUT = 2.0; + + /** + * Log message + */ + const METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND = 'method unsupported by Zend_Cache_Backend_RedisCluster'; + const TAGS_UNSUPPORTED_BY_REDISCLUSTER_BACKEND = 'tags unsupported by Zend_Cache_Backend_RedisCluster'; + + /** + * options + */ + protected $_options = [ + 'servers' => [ + [ + 'host' => self::DEFAULT_HOST, + 'port' => self::DEFAULT_PORT + ], + ], + 'timeout' => self::DEFAULT_TIMEOUT, + 'read_timeout' => self::DEFAULT_READ_TIMEOUT, + 'key_prefix' => '' + ]; + + /** + * Redis object + * + * @var mixed redis object + */ + protected $_redis = null; + + /** + * Constructor + * + * @param array $options associative array of options + */ + public function __construct(array $options = []) + { + if (!extension_loaded('redis')) { + Zend_Cache::throwException('The redis extension must be loaded for using this backend !'); + } + parent::__construct($options); + $serverHosts = []; + foreach ($this->_options['servers'] as $server) { + $serverHosts[] = $server['host'] . ':' . $server['port']; + } + $serverHosts[] = $this->_options['timeout']; + $serverHosts[] = $this->_options['read_timeout']; + $this->_redis = new RedisCluster(null, $serverHosts); + } + + /** + * Test if a cache is available for the given id and (if yes) return it (false else) + * + * @param string $id cache id + * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested + * @return string|false cached datas + */ + public function load($id, $doNotTestCacheValidity = true) + { + if (!$this->_redis) { + return false; + } + $data = $this->_redis->get($id); + if ($data != false) { + return $data; + } + return false; + } + + /** + * Test if a cache is available or not (for the given id) + * + * @param string $id cache id + * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record + */ + public function test($id) + { + if (!$this->_redis) { + return false; + } + $tmp = $this->_redis->exists($id); + return $tmp; + } + + /** + * Save some string data into a cache record + * + * Note : $data is always "string" (serialization is done by the + * core not by the backend) + * + * @param string $data Data to cache + * @param string $id Cache id + * @param mixed $tags Array of strings, the cache record will be tagged by each string entry, if false, key + * can only be read if $doNotTestCacheValidity is true + * @param int|bool $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) + * @return boolean true if no problem + */ + public function save($data, $id, $tags = [], $specificLifetime = false) + { + if (!$this->_redis) { + return false; + } + + $lifetime = $this->getLifetime($specificLifetime); + if ($lifetime === null) { + $return = $this->_redis->set($id, $data); + } else { + $return = $this->_redis->setex($id, $lifetime, $data); + } + if ($return === false) { + $rsCode = $this->_redis->getLastError(); + $this->_log("RedisCluster::set() failed: [{$rsCode}]"); + } + if (count($tags) > 0) { + $this->_log(self::METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND); + } + + return $return; + } + + /** + * Remove a cache record + * + * @param string $id Cache id + * @return boolean True if no problem + */ + public function remove($id) + { + return (boolean)$this->_redis->del($id); + } + + /** + * Clean some cache records + * + * Available modes are : + * 'all' (default) => remove all cache entries ($tags is not used) + * 'old' => unsupported + * 'matchingTag' => unsupported + * 'notMatchingTag' => unsupported + * 'matchingAnyTag' => unsupported + * + * @param string $mode Clean mode + * @param array $tags Array of tags + * @throws Zend_Cache_Exception + * @return boolean True if no problem + */ + public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = []) + { + $success_times = true; + $masters = $this->_redis->_masters(); + if ($mode == Zend_Cache::CLEANING_MODE_ALL) { + foreach ($masters as $master) { + $server = implode(',', $master); + $success = $this->_redis->flushDB($server); + !$success ?: $success_times++; + } + return $success_times == count($masters); + } else { + $this->_log(self::METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND); + } + return false; + } + + /** + * Give (if possible) an extra lifetime to the given cache id + * + * @param string $id cache id + * @param int $extraLifetime + * @return boolean true if ok + */ + public function touch($id, $extraLifetime) + { + $ttl = $this->_redis->ttl($id); + return $this->_redis->expire($id, $ttl + $extraLifetime); + } + + /** + * Return an array of metadatas for the given cache id + * + * The array must include these keys : + * - expire : the expire timestamp + * - tags : a string array of tags + * - mtime : timestamp of last modification time + * + * @param string $id cache id + * @return array array of metadatas (false if the cache id is not found) + */ + public function getMetadatas($id) + { + $tmp = $this->_redis->get($id); + if ($tmp === false) { + return $tmp; + } + $ttl = $this->_redis->ttl($id); + return [ + 'expire' => $ttl, + 'tags' => [], + 'mtime' => null + ]; + } + + /** + * Increment cache id value + * + * @param string $id cache id + * @param int $offset + * @param int $initial + * @return boolean $specificLifetime or integer in seconds lifetime + */ + public function increment($id, $offset = 1, $initial = 0, $specificLifetime = false) + { + $result = $this->_redis->incrBy($id, $offset); + return $result; + } + + /** + * Decrement cache id value + * + * @param string $id cache id + * @param int $offset + * @param int $initial + * @return boolean $specificLifetime or integer in seconds lifetime + */ + public function decrement($id, $offset = 1, $initial = 0, $specificLifetime = false) + { + $result = $this->_redis->decrBy($id, $offset); + return $result; + } + + /** + * Remove items of given namespace + * + * @param string $namespace + * @return bool + */ + public function clearByNamespace($namespace) + { + $namespace = (string)$namespace; + if ($namespace === '') { + return false; + } + $this->_redis->del($this->_redis->keys($namespace . '*')); + return true; + } + + /** + * Get keys of given namespace + * + * @param string $namespace + * @return bool + */ + public function getKeysByNamespace($namespace) + { + $namespace = (string)$namespace; + if ($namespace === '') { + return false; + } + $keys = $this->_redis->keys($namespace . '*'); + return $keys; + } + + /** + * Get Values of given namespace + * + * @param string $namespace + * @return mixed + */ + public function getValuesByNamespace($namespace) + { + $namespace = (string)$namespace; + if ($namespace === '') { + return false; + } + $keys = $this->_redis->keys($namespace . '*'); + $values = []; + foreach ($keys as $key) { + $values[$key] = $this->load($key); + } + return $values; + } + + /** + * Removes TTL from a key + * + * @param string $id + * @return bool + */ + public function removeTTL($id) + { + return (boolean)$this->_redis->persist($id); + } + + /** + * Return the filling percentage of the backend storage + * + * @throws Zend_Cache_Exception + * @return int integer between 0 and 100 + */ + public function getFillingPercentage() + { + $this->_log(self::METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND); + return []; + } + + /** + * Return an array of stored cache ids + * + * @return array array of stored cache ids (string) + */ + public function getIds() + { + $this->_log(self::METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND); + return []; + } + + /** + * Return an array of stored tags + * + * @return array array of stored tags (string) + */ + public function getTags() + { + $this->_log(self::METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND); + return []; + } + + /** + * Return an array of stored cache ids which match given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of matching cache ids (string) + */ + public function getIdsMatchingTags($tags = []) + { + $this->_log(self::METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND); + return []; + } + + /** + * Return an array of stored cache ids which don't match given tags + * + * In case of multiple tags, a logical OR is made between tags + * + * @param array $tags array of tags + * @return array array of not matching cache ids (string) + */ + public function getIdsNotMatchingTags($tags = []) + { + $this->_log(self::METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND); + return []; + } + + /** + * Return an array of stored cache ids which match any given tags + * + * In case of multiple tags, a logical AND is made between tags + * + * @param array $tags array of tags + * @return array array of any matching cache ids (string) + */ + public function getIdsMatchingAnyTags($tags = array()) + { + $this->_log(self::METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND); + return []; + } + + /** + * Return the value if is numeric or false if not + * + * + * @param string $id + * @return integer or boolean + */ + public function getCounterKey($id) + { + $tmp = $this->load($id); + return is_numeric($tmp) ? $tmp : false; + } + + /** + * Return the values of the given arrays + * + * @param array $ids + * @return array + */ + public function loadMulti($ids = []) + { + $data = []; + $result = $this->_redis->mGet($ids); + foreach ($ids as $key => $value) { + $data[$value] = $result[$key]; + } + return $data; + } + + /** + * Save the given keys with values. If they have lifetime it saves + * + * @param array $data + * @param array $tags + * @param boolean $specificLifetime + * @return boolean + */ + public function saveMulti($data, $tags = [], $specificLifetime = false) + { + $result = false; + if (is_array($data)) { + $lifetime = $this->getLifetime($specificLifetime); + + foreach ($data as $key => $value) { + $result = $this->save($value, $key, [], $lifetime); + if ($result === false) { + $rsCode = $this->_redis->getLastError(); + $this->_log("RedisCluster::set() failed: [{$rsCode}]"); + } + } + if (count($tags) > 0) { + $this->_log(self::METHOD_UNSUPPORTED_BY_REDISCLUSTER_BACKEND); + } + } + return $result; + } + + /** + * Close connection with redis + * + */ + public function closeConnection() + { + $tmp = $this->_redis->close(); + return $tmp; + } + + /** + * Return an associative array of capabilities (booleans) of the backend + * + * The array must include these keys : + * - automatic_cleaning (is automating cleaning necessary) + * - tags (are tags supported) + * - expired_read (is it possible to read expired cache records + * (for doNotTestCacheValidity option for example)) + * - priority does the backend deal with priority when saving + * - infinite_lifetime (is infinite lifetime can work with this backend) + * - get_list (is it possible to get the list of cache ids and the complete list of tags) + * + * @return array associative of with capabilities + */ + public function getCapabilities() + { + return [ + 'automatic_cleaning' => false, + 'tags' => false, + 'expired_read' => false, + 'priority' => false, + 'infinite_lifetime' => false, + 'get_list' => false + ]; + } +} \ No newline at end of file diff --git a/tests/TestConfiguration.php.dist b/tests/TestConfiguration.php.dist index cf6c0508f1..cf0354edd1 100644 --- a/tests/TestConfiguration.php.dist +++ b/tests/TestConfiguration.php.dist @@ -64,6 +64,8 @@ defined('TESTS_ZEND_AUTH_ADAPTER_LDAP_ONLINE_ENABLED') || define('TESTS_ZEND_AUT * TESTS_ZEND_CACHE_LIBMEMCACHED_ENABLED => memcached extension has to be enabled and * a memcached server has to be available * TESTS_ZEND_CACHE_XCACHE_ENABLED => xcache extension has to be enabled + * TESTS_ZEND_CACHE_REDISCLUSTER_ENABLED => memcache extension has to be enabled and + * a memcached server has to be available */ defined('TESTS_ZEND_CACHE_SQLITE_ENABLED') || define('TESTS_ZEND_CACHE_SQLITE_ENABLED', false); defined('TESTS_ZEND_CACHE_APC_ENABLED') || define('TESTS_ZEND_CACHE_APC_ENABLED', false); @@ -79,6 +81,9 @@ defined('TESTS_ZEND_CACHE_MEMCACHED_PERSISTENT') || define('TESTS_ZEND_CACHE_MEM defined('TESTS_ZEND_CACHE_LIBMEMCACHED_ENABLED') || define('TESTS_ZEND_CACHE_LIBMEMCACHED_ENABLED', false); defined('TESTS_ZEND_CACHE_LIBMEMCACHED_HOST') || define('TESTS_ZEND_CACHE_LIBMEMCACHED_HOST', '127.0.0.1'); defined('TESTS_ZEND_CACHE_LIBMEMCACHED_PORT') || define('TESTS_ZEND_CACHE_LIBMEMCACHED_PORT', 11211); +defined('TESTS_ZEND_CACHE_REDISCLUSTER_ENABLED') || define('TESTS_ZEND_CACHE_REDISCLUSTER_ENABLED', false); +defined('TESTS_ZEND_CACHE_REDISCLUSTER_HOST') || define('TESTS_ZEND_CACHE_REDISCLUSTER_HOST', '127.0.0.1'); +defined('TESTS_ZEND_CACHE_REDISCLUSTER_PORT') || define('TESTS_ZEND_CACHE_REDISCLUSTER_PORT', 30001); defined('TESTS_ZEND_CACHE_LIBMEMCACHED_WEIGHT') || define('TESTS_ZEND_CACHE_LIBMEMCACHED_WEIGHT', 1); /** diff --git a/tests/TestConfiguration.travis.php b/tests/TestConfiguration.travis.php index c7ba739d85..91c0a4da59 100644 --- a/tests/TestConfiguration.travis.php +++ b/tests/TestConfiguration.travis.php @@ -48,10 +48,13 @@ * TESTS_ZEND_CACHE_LIBMEMCACHED_ENABLED => memcached extension has to be enabled and * a memcached server has to be available * TESTS_ZEND_CACHE_XCACHE_ENABLED => xcache extension has to be enabled + * TESTS_ZEND_CACHE_REDISCLUSTER_ENABLED => memcache extension has to be enabled and + * a memcached server has to be available */ defined('TESTS_ZEND_CACHE_SQLITE_ENABLED') || define('TESTS_ZEND_CACHE_SQLITE_ENABLED', true); defined('TESTS_ZEND_CACHE_MEMCACHED_ENABLED') || define('TESTS_ZEND_CACHE_MEMCACHED_ENABLED', true); defined('TESTS_ZEND_CACHE_LIBMEMCACHED_ENABLED') || define('TESTS_ZEND_CACHE_LIBMEMCACHED_ENABLED', true); +defined('TESTS_ZEND_CACHE_REDISCLUSTER_ENABLED') || define('TESTS_ZEND_CACHE_REDISCLUSTER_ENABLED', false); /** * Zend_Db_Adapter_Pdo_Mysql and Zend_Db_Adapter_Mysqli diff --git a/tests/Zend/Cache/AllTests.php b/tests/Zend/Cache/AllTests.php index ee0a9d35f7..61de864eb3 100644 --- a/tests/Zend/Cache/AllTests.php +++ b/tests/Zend/Cache/AllTests.php @@ -45,6 +45,7 @@ require_once 'Zend/Cache/ZendPlatformBackendTest.php'; require_once 'Zend/Cache/ZendServerDiskTest.php'; require_once 'Zend/Cache/ZendServerShMemTest.php'; +require_once 'Zend/Cache/RedisClusterBackendTest.php'; /** * @category Zend @@ -165,6 +166,31 @@ public static function suite() $suite->addTestSuite('Zend_Cache_MemcachedBackendTest'); } + /* + * Check if Redis cluster tests are enabled, and if extension is available. + */ + if (!defined('TESTS_ZEND_CACHE_REDISCLUSTER_ENABLED') || + constant('TESTS_ZEND_CACHE_REDISCLUSTER_ENABLED') === false) { + $skipTest = new Zend_Cache_RedisClusterBackendTest_SkipTests(); + $skipTest->message = 'Tests are not enabled in TestConfiguration.php'; + $suite->addTest($skipTest); + } else if (!extension_loaded('redis')) { + $skipTest = new Zend_Cache_RedisClusterBackendTest_SkipTests(); + $skipTest->message = "Extension 'phpredis' is not loaded"; + $suite->addTest($skipTest); + } else { + if (!defined('TESTS_ZEND_CACHE_REDISCLUSTER_HOST')) { + define('TESTS_ZEND_CACHE_REDISCLUSTER_HOST', '127.0.0.1'); + } + if (!defined('TESTS_ZEND_CACHE_REDISCLUSTER_PORT')) { + define('TESTS_ZEND_CACHE_REDISCLUSTER_PORT', 30001); + } + if (!defined('TESTS_ZEND_CACHE_REDISCLUSTER_PERSISTENT')) { + define('TESTS_ZEND_CACHE_REDISCLUSTER_PERSISTENT', false); + } + $suite->addTestSuite('Zend_Cache_RedisClusterBackendTest'); + } + /* * Check if Memcached2 tests are enabled, and if extension is available. */ diff --git a/tests/Zend/Cache/RedisClusterBackendTest.php b/tests/Zend/Cache/RedisClusterBackendTest.php new file mode 100644 index 0000000000..80e743361f --- /dev/null +++ b/tests/Zend/Cache/RedisClusterBackendTest.php @@ -0,0 +1,491 @@ + TESTS_ZEND_CACHE_REDISCLUSTER_HOST, + 'port' => TESTS_ZEND_CACHE_REDISCLUSTER_PORT, + ); + $options = array( + 'servers' => array($serverValid), + ); + $this->_instance = new Zend_Cache_Backend_RedisCluster($options); + parent::setUp($notag); + } + + public function tearDown() + { + parent::tearDown(); + $this->_instance = null; + } + + public function testConstructorCorrectCall() + { + $test = new Zend_Cache_Backend_RedisCluster(); + } + + function testBackendIsInstanceOfRedisCluster() + { + $this->assertInstanceOf('Zend_Cache_Backend_RedisCluster', $this->_instance); + } + + public function testSaveCorrectCall() + { + $res = $this->_instance->save('data to cache', 'foo'); + $this->assertTrue($res); + } + + public function testSaveWithNullLifeTime() + { + $this->_instance->setDirectives(array('lifetime' => null)); + $res = $this->_instance->save('data to cache', 'foo'); + $this->assertTrue($res); + } + + public function testSaveWithSpecificLifeTime() + { + $this->_instance->setDirectives(array('lifetime' => 3600)); + $res = $this->_instance->save('data to cache', 'foo', [], 10); + $this->assertTrue($res); + } + + function testSaveRedisCluster() + { + $data = 'foo'; + $data1 = 'foo1'; + $id = '125'; + $success = $this->_instance->save($data, $id); + $this->assertTrue($success); + $success = $this->_instance->save($data1, $id); + $this->assertTrue($success); + $loaded = $this->_instance->load($id); + $this->assertEquals($data1, $loaded); + } + + function testTestIDFromRedisCluster() + { + $data = 'foo'; + $id = '125'; + $success = $this->_instance->save($data, $id); + $this->assertTrue($success); + $loaded = $this->_instance->load($id); + $this->assertEquals($data, $loaded); + $loaded = $this->_instance->test($id); + $this->assertTrue($loaded); + $remove = $this->_instance->remove($id); + $this->assertTrue($remove); + $loaded = $this->_instance->test($id); + $this->assertFalse($loaded); + } + + function testLoadIDFromRedisCluster() + { + $data = 'foo'; + $id = '125'; + $success = $this->_instance->save($data, $id); + $this->assertTrue($success); + $remove = $this->_instance->remove($id); + $this->assertTrue($remove); + $loaded = $this->_instance->load($id); + $this->assertFalse($loaded); + } + + function testIncrementDecrementFromRedisCluster() + { + $id = '125'; + $id1 = '128'; + $id2 = '122'; + $success = $this->_instance->increment($id); + $this->assertEquals(1, $success); + $loaded = $this->_instance->load($id); + $this->assertEquals(1, $loaded); + $success = $this->_instance->increment($id); + $this->assertEquals(2, $success); + $success = $this->_instance->increment($id); + $this->assertEquals(3, $success); + $success = $this->_instance->increment($id, 2); + $this->assertEquals(5, $success); + $success = $this->_instance->increment($id, 2, 0); + $this->assertEquals(7, $success); + $success = $this->_instance->decrement($id, 2, 0); + $this->assertEquals(5, $success); + $success = $this->_instance->increment($id1, 2, 1); + $this->assertEquals(2, $success); + $success = $this->_instance->decrement($id2, 2, 0); + $this->assertEquals(-2, $success); + } + + function testClearByNamespace() + { + $data = 'foo'; + $id = '125_1'; + $id1 = '125_2'; + $this->_instance->save($data, $id); + $this->_instance->save($data, $id1); + $this->_instance->clearByNamespace('125_'); + $loaded = $this->_instance->load($id); + $this->assertFalse($loaded); + $loaded = $this->_instance->load($id1); + $this->assertFalse($loaded); + + $keys = $this->_instance->clearByNamespace(''); + $this->assertFalse($keys); + } + + function testGetKeysByNamespace() + { + $data = 'foo'; + $id = '125_1'; + $id1 = '125_2'; + $this->_instance->save($data, $id); + $this->_instance->save($data, $id1); + $keys = $this->_instance->getKeysByNamespace('125_'); + $expected_keys = [$id, $id1]; + $this->assertEquals(0, count(array_diff($expected_keys, $keys))); + $this->assertEquals(0, count(array_diff($expected_keys, $keys))); + + $keys = $this->_instance->getKeysByNamespace('126_'); + $this->assertEquals([], $keys); + + $keys = $this->_instance->getKeysByNamespace(''); + $this->assertFalse($keys); + } + + function testGetValuesByNamespace() + { + $data = 'foo'; + $id = '125_1'; + $id1 = '125_2'; + $this->_instance->save($data, $id); + $this->_instance->save($data, $id1); + $keys = $this->_instance->getValuesByNamespace('125_'); + $expected_keys = [$id => 'foo', $id1 => 'foo']; + $this->assertEquals(0, count(array_diff($expected_keys, $keys))); + $this->assertEquals(0, count(array_diff($expected_keys, $keys))); + + $keys = $this->_instance->getValuesByNamespace('126_'); + $this->assertEquals([], $keys); + + $keys = $this->_instance->getValuesByNamespace(''); + $this->assertFalse($keys); + } + + function testRemoveTTL() + { + $data = 'foo'; + $id = '125'; + $success = $this->_instance->save($data, $id); + $this->assertTrue($success); + $success = $this->_instance->getMetadatas($id); + $expected = [ + 'expire' => 3600, + 'tags' => [], + 'mtime' => null + ]; + $this->assertEquals($expected, $success); + + $success = $this->_instance->removeTTL($id); + $this->assertTrue($success); + $success = $this->_instance->getMetadatas($id); + $expected = [ + 'expire' => -1, + 'tags' => [], + 'mtime' => null + ]; + $this->assertEquals($expected, $success); + } + + function testSaveWithCustomTTL() + { + $data = 'foo'; + $id = '125'; + $customTTL = 300; + $success = $this->_instance->save($data, $id, [], $customTTL); + $this->assertTrue($success); + $success = $this->_instance->getMetadatas($id); + $expected = [ + 'expire' => $customTTL, + 'tags' => [], + 'mtime' => null + ]; + $this->assertEquals($expected, $success); + } + + function testGetCounterKey() + { + $id = '125'; + $success = $this->_instance->increment($id); + $this->assertEquals(1, $success); + $this->assertEquals(1, $this->_instance->getCounterKey($id)); + } + + function testGetCounterKeyReturnFalseWhenNotNumeric() + { + $id = '125'; + $data = 'foo'; + $success = $this->_instance->save($data, $id); + $this->assertEquals(1, $success); + $this->assertFalse($this->_instance->getCounterKey($id)); + } + + function testGetCapabilities() + { + $expected = [ + 'automatic_cleaning' => false, + 'tags' => false, + 'expired_read' => false, + 'priority' => false, + 'infinite_lifetime' => false, + 'get_list' => false + ]; + $this->assertEquals($expected, $this->_instance->getCapabilities()); + } + + function testSaveMulti() + { + $id = '125'; + $data = 'foo'; + + $id1 = '126'; + $data1 = 'foo1'; + + $id2 = '127'; + $data2 = 'foo12'; + + $toBeSaved = [ + $id => $data, + $id1 => $data1, + $id2 => $data2 + ]; + + $saveMultidata = $this->_instance->saveMulti($toBeSaved, []); + $this->assertTrue($saveMultidata); + } + + function testSaveMultiWithLifetime() + { + $ttl = 100; + $id = '125'; + $data = 'foo'; + + $id1 = '126'; + $data1 = 'foo1'; + + $id2 = '127'; + $data2 = 'foo12'; + + $toBeSaved = [ + $id => $data, + $id1 => $data1, + $id2 => $data2 + ]; + + $saveMultidata = $this->_instance->saveMulti($toBeSaved, [], $ttl); + $this->assertTrue($saveMultidata); + + $success = $this->_instance->getMetadatas($id); + $expected = [ + 'expire' => $ttl, + 'tags' => [], + 'mtime' => null + ]; + $this->assertEquals($expected, $success); + } + + function testLoadMulti() + { + $id = '125'; + $data = 'foo'; + $success = $this->_instance->save($data, $id); + $this->assertTrue($success); + + $id1 = '126'; + $data1 = 'foo1'; + $success1 = $this->_instance->save($data1, $id1); + $this->assertTrue($success1); + + $id2 = '127'; + $data2 = 'foo12'; + $success2 = $this->_instance->save($data2, $id2); + $this->assertTrue($success2); + + $getKeys = [$id, $id1, $id2, 'foo']; + $loadMultidata = $this->_instance->loadMulti($getKeys); + + $expected = [ + $id => $data, + $id1 => $data1, + $id2 => $data2, + 'foo' => false + ]; + $this->assertEquals($expected, $loadMultidata); + } + + function testCleanRedisCluster() + { + $id = '125'; + $data = 'foo'; + $success = $this->_instance->save($data, $id); + $this->assertTrue($success); + $loaded = $this->_instance->load($id); + $this->assertEquals($data, $loaded); + + $this->_instance->clean('all'); + $loaded = $this->_instance->load($id); + $this->assertFalse($loaded); + } + + function testCloseConnection() + { + $id = '125'; + $data = 'foo'; + $success = $this->_instance->save($data, $id); + $this->assertTrue($success); + $success = $this->_instance->closeConnection(); + $this->assertTrue($success); + $loaded = $this->_instance->load($id); + $this->assertEquals($data, $loaded); + } + + + public function testCleanModeOld() + { + $this->_instance->setDirectives(array('logging' => false)); + $this->_instance->clean('old'); + // do nothing, just to see if an error occured + $this->_instance->setDirectives(array('logging' => true)); + } + + public function testCleanModeMatchingTags() + { + $this->_instance->setDirectives(array('logging' => false)); + $this->_instance->clean('matchingTag', array('tag1')); + // do nothing, just to see if an error occured + $this->_instance->setDirectives(array('logging' => true)); + } + + public function testCleanModeNotMatchingTags() + { + $this->_instance->setDirectives(array('logging' => false)); + $this->_instance->clean('notMatchingTag', array('tag1')); + // do nothing, just to see if an error occured + $this->_instance->setDirectives(array('logging' => true)); + } + + public function testGetMetadatas($notag = false) + { + $data = 'foo'; + $id = '125'; + $success = $this->_instance->save($data, $id); + $this->assertTrue($success); + $success = $this->_instance->getMetadatas($id); + $expected = [ + 'expire' => 3600, + 'tags' => [], + 'mtime' => null + ]; + $this->assertEquals($expected, $success); + + $id = '126'; + $success = $this->_instance->save($data, $id, [], 10); + $this->assertTrue($success); + $success = $this->_instance->getMetadatas($id); + $expected = [ + 'expire' => 10, + 'tags' => [], + 'mtime' => null + ]; + $this->assertEquals($expected, $success); + + $success = $this->_instance->getMetadatas(225); + $this->assertFalse($success); + } + + public function testTouch() + { + $res = $this->_instance->getMetadatas('bar'); + $bool = $this->_instance->touch('bar', 30); + $this->assertTrue($bool); + $res2 = $this->_instance->getMetadatas('bar'); + $this->assertTrue(($res2['expire'] - $res['expire']) == 30); + } + + // Because of limitations of this backend... + public function testCleanModeMatchingTags2() + { + } + + public function testCleanModeNotMatchingTags2() + { + } + + public function testCleanModeNotMatchingTags3() + { + } + + public function testGetFillingPercentage() + { + } + + public function testGetFillingPercentageOnEmptyBackend() + { + } + + public function testGetWithAnExpiredCacheId() + { + } + + public function testTestWithAnExistingCacheId() + { + } + + public function testTestWithAnExistingCacheIdAndANullLifeTime() + { + } + + public function testGetIds() + { + } + + public function testGetTags() + { + } + + public function testGetIdsMatchingTags() + { + } + + public function testGetIdsNotMatchingTags() + { + } + + public function testGetIdsMatchingAnyTags() + { + } + +} \ No newline at end of file diff --git a/tests/Zend/Cache/SkipTests.php b/tests/Zend/Cache/SkipTests.php index af386cd59e..a6626bd325 100644 --- a/tests/Zend/Cache/SkipTests.php +++ b/tests/Zend/Cache/SkipTests.php @@ -159,3 +159,10 @@ class Zend_Cache_TwoLevelsBackendTest_SkipTests extends Zend_Cache_BackendTest_S class Zend_Cache_ZendServerTest_SkipTests extends Zend_Cache_BackendTest_SkipTests { } + + +class Zend_Cache_RedisClusterBackendTest_SkipTests extends Zend_Cache_BackendTest_SkipTests +{ +} + +