From e10943814e5dfe74743775d5bdf9a521a19c3f05 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 30 Dec 2016 15:39:05 +0100 Subject: [PATCH 1/2] [Cache] Add DSN, createClient & better error reporting to MemcachedAdapter --- .../Compiler/CachePoolPass.php | 8 +- .../DependencyInjection/Configuration.php | 1 + .../FrameworkExtension.php | 2 +- .../Resources/config/cache.xml | 11 + .../Resources/config/schema/symfony-1.0.xsd | 1 + .../DependencyInjection/ConfigurationTest.php | 1 + .../Bundle/FrameworkBundle/composer.json | 2 +- .../Bundle/FrameworkBundle/phpunit.xml.dist | 1 + .../Cache/Adapter/AbstractAdapter.php | 15 ++ .../Cache/Adapter/MemcachedAdapter.php | 188 +++++++++++++++++- 10 files changed, 213 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index 43abc8e565730..233b01fb430dc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -11,7 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -use Symfony\Component\Cache\Adapter\RedisAdapter; +use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -108,13 +108,13 @@ public static function getServiceProvider(ContainerBuilder $container, $name) { $container->resolveEnvPlaceholders($name, null, $usedEnvs); - if (0 === strpos($name, 'redis://') || $usedEnvs) { + if ($usedEnvs || preg_match('#^[a-z]++://#', $name)) { $dsn = $name; if (!$container->hasDefinition($name = md5($dsn))) { - $definition = new Definition(\Redis::class); + $definition = new Definition(AbstractAdapter::class); $definition->setPublic(false); - $definition->setFactory(array(RedisAdapter::class, 'createConnection')); + $definition->setFactory(array(AbstractAdapter::class, 'createConnection')); $definition->setArguments(array($dsn)); $container->setDefinition($name, $definition); } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 4a8fef38d3093..97663e9285b45 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -706,6 +706,7 @@ private function addCacheSection(ArrayNodeDefinition $rootNode) ->scalarNode('default_doctrine_provider')->end() ->scalarNode('default_psr6_provider')->end() ->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end() + ->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end() ->arrayNode('pools') ->useAttributeAsKey('name') ->prototype('array') diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 3f3c294057f63..aa37f7341340b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1256,7 +1256,7 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con // Inline any env vars referenced in the parameter $container->setParameter('cache.prefix.seed', $container->resolveEnvPlaceholders($container->getParameter('cache.prefix.seed'), true)); } - foreach (array('doctrine', 'psr6', 'redis') as $name) { + foreach (array('doctrine', 'psr6', 'redis', 'memcached') as $name) { if (isset($config[$name = 'default_'.$name.'_provider'])) { $container->setAlias('cache.'.$name, new Alias(Compiler\CachePoolPass::getServiceProvider($container, $config[$name]), false)); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml index c790ce5a6e795..d03b410f56c94 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml @@ -93,6 +93,17 @@ + + + + + + 0 + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index fbf53309f41be..6dce93415e662 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -215,6 +215,7 @@ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index adfc46d14fb52..2bbc1faf3c702 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -272,6 +272,7 @@ protected static function getBundleDefaultConfig() 'system' => 'cache.adapter.system', 'directory' => '%kernel.cache_dir%/pools', 'default_redis_provider' => 'redis://localhost', + 'default_memcached_provider' => 'memcached://localhost', ), 'workflows' => array(), 'php_errors' => array( diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index adcb53eec3b88..54ebc0f0335ca 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.5.9", - "symfony/cache": "~3.2", + "symfony/cache": "~3.3", "symfony/class-loader": "~3.2", "symfony/dependency-injection": "~3.3", "symfony/config": "~2.8|~3.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist b/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist index a105f7ece0a98..f46af037d14b6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist +++ b/src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist @@ -9,6 +9,7 @@ + diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 4a788963ea74b..2134a0efb7cd6 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -115,6 +115,21 @@ public static function createSystemCache($namespace, $defaultLifetime, $version, return new ChainAdapter(array($apcu, $fs)); } + public static function createConnection($dsn, array $options = array()) + { + if (!is_string($dsn)) { + throw new InvalidArgumentException(sprintf('The %s() method expect argument #1 to be string, %s given.', __METHOD__, gettype($dsn))); + } + if (0 === strpos($dsn, 'redis://')) { + return RedisAdapter::createConnection($dsn, $options); + } + if (0 === strpos($dsn, 'memcached://')) { + return MemcachedAdapter::createConnection($dsn, $options); + } + + throw new InvalidArgumentException(sprintf('Unsupported DSN: %s.', $dsn)); + } + /** * Fetches several cache items. * diff --git a/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php index 8e1e0ba1c9df5..788e21ca5d233 100644 --- a/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php @@ -11,22 +11,177 @@ namespace Symfony\Component\Cache\Adapter; +use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\Exception\InvalidArgumentException; + /** * @author Rob Frawley 2nd + * @author Nicolas Grekas */ class MemcachedAdapter extends AbstractAdapter { + private static $defaultClientOptions = array( + 'persistent_id' => null, + 'username' => null, + 'password' => null, + ); + + protected $maxIdLength = 250; + private $client; + public static function isSupported() + { + return extension_loaded('memcached') && version_compare(phpversion('memcached'), '2.2.0', '>='); + } + public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0) { + if (!static::isSupported()) { + throw new CacheException('Memcached >= 2.2.0 is required'); + } + $opt = $client->getOption(\Memcached::OPT_SERIALIZER); + if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { + throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + } + if (!$client->getOption(\Memcached::OPT_BINARY_PROTOCOL)) { + throw new CacheException('MemcachedAdapter: "binary_protocol" option must be enabled.'); + } + $this->maxIdLength -= strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); + parent::__construct($namespace, $defaultLifetime); $this->client = $client; } - public static function isSupported() + /** + * Creates a Memcached instance. + * + * By default, the binary protocol, no block, and libketama compatible options are enabled. + * + * Examples for servers: + * - 'memcached://user:pass@localhost?weight=33' + * - array(array('localhost', 11211, 33)) + * + * @param array[]|string|string[] An array of servers, a DSN, or an array of DSNs + * @param array An array of options + * + * @return \Memcached + * + * @throws \ErrorEception When invalid options or servers are provided. + */ + public static function createConnection($servers, array $options = array()) { - return extension_loaded('memcached') && version_compare(phpversion('memcached'), '2.2.0', '>='); + if (is_string($servers)) { + $servers = array($servers); + } elseif (!is_array($servers)) { + throw new InvalidArgumentException(sprintf('MemcachedAdapter::createClient() expects array or string as first argument, %s given.', gettype($servers))); + } + set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); + try { + if (!static::isSupported()) { + throw new trigger_error('Memcached >= 2.2.0 is required'); + } + $options += static::$defaultClientOptions; + $client = new \Memcached($options['persistent_id']); + $username = $options['username']; + $password = $options['password']; + unset($options['persistent_id'], $options['username'], $options['password']); + $options = array_change_key_case($options, CASE_UPPER); + + // set client's options + $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); + $client->setOption(\Memcached::OPT_NO_BLOCK, true); + if (!array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { + $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); + } + foreach ($options as $name => $value) { + if (is_int($name)) { + continue; + } + if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { + $value = constant('Memcached::'.$name.'_'.strtoupper($value)); + } + $opt = constant('Memcached::OPT_'.$name); + + unset($options[$name]); + $options[$opt] = $value; + } + $client->setOptions($options); + + // parse any DSN in $servers + foreach ($servers as $i => $dsn) { + if (is_array($dsn)) { + continue; + } + if (0 !== strpos($dsn, 'memcached://')) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s does not start with "memcached://"', $dsn)); + } + $params = preg_replace_callback('#^memcached://(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { + if (!empty($m[1])) { + list($username, $password) = explode(':', $m[1], 2) + array(1 => null); + } + + return 'file://'; + }, $dsn); + if (false === $params = parse_url($params)) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); + } + if (!isset($params['host']) && !isset($params['path'])) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $dsn)); + } + if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { + $params['weight'] = $m[1]; + $params['path'] = substr($params['path'], 0, -strlen($m[0])); + } + $params += array( + 'host' => isset($params['host']) ? $params['host'] : $params['path'], + 'port' => isset($params['host']) ? 11211 : null, + 'weight' => 0, + ); + if (isset($params['query'])) { + parse_str($params['query'], $query); + $params += $query; + } + + $servers[$i] = array($params['host'], $params['port'], $params['weight']); + } + + // set client's servers, taking care of persistent connections + if (!$client->isPristine()) { + $oldServers = array(); + foreach ($client->getServerList() as $server) { + $oldServers[] = array($server['host'], $server['port']); + } + + $newServers = array(); + foreach ($servers as $server) { + if (1 < count($server)) { + $server = array_values($server); + unset($server[2]); + $server[1] = (int) $server[1]; + } + $newServers[] = $server; + } + + if ($oldServers !== $newServers) { + // before resetting, ensure $servers is valid + $client->addServers($servers); + $client->resetServerList(); + } + } + $client->addServers($servers); + + if (null !== $username || null !== $password) { + if (!method_exists($client, 'setSaslAuthData')) { + trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.'); + } + $client->setSaslAuthData($username, $password); + } + + return $client; + } finally { + restore_error_handler(); + } } /** @@ -34,7 +189,7 @@ public static function isSupported() */ protected function doSave(array $values, $lifetime) { - return $this->client->setMulti($values, $lifetime) && $this->client->getResultCode() === \Memcached::RES_SUCCESS; + return $this->checkResultCode($this->client->setMulti($values, $lifetime)); } /** @@ -42,7 +197,7 @@ protected function doSave(array $values, $lifetime) */ protected function doFetch(array $ids) { - return $this->client->getMulti($ids); + return $this->checkResultCode($this->client->getMulti($ids)); } /** @@ -50,7 +205,7 @@ protected function doFetch(array $ids) */ protected function doHave($id) { - return $this->client->get($id) !== false || $this->client->getResultCode() === \Memcached::RES_SUCCESS; + return false !== $this->client->get($id) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); } /** @@ -58,14 +213,14 @@ protected function doHave($id) */ protected function doDelete(array $ids) { - $toDelete = count($ids); - foreach ($this->client->deleteMulti($ids) as $result) { - if (\Memcached::RES_SUCCESS === $result || \Memcached::RES_NOTFOUND === $result) { - --$toDelete; + $ok = true; + foreach ($this->checkResultCode($this->client->deleteMulti($ids)) as $result) { + if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) { + $ok = false; } } - return 0 === $toDelete; + return $ok; } /** @@ -73,6 +228,17 @@ protected function doDelete(array $ids) */ protected function doClear($namespace) { - return $this->client->flush(); + return $this->checkResultCode($this->client->flush()); + } + + private function checkResultCode($result) + { + $code = $this->client->getResultCode(); + + if (\Memcached::RES_SUCCESS === $code || \Memcached::RES_NOTFOUND === $code) { + return $result; + } + + throw new CacheException(sprintf('MemcachedAdapter client error: %s.', strtolower($this->client->getResultMessage()))); } } From 87030b43ca21539d5aeb25d740758ba2f773f8bb Mon Sep 17 00:00:00 2001 From: Rob Frawley 2nd Date: Thu, 15 Dec 2016 12:37:16 -0500 Subject: [PATCH 2/2] [cache] Add tests for MemcachedAdapter::createClient() --- .travis.yml | 3 +- phpunit.xml.dist | 1 + .../Tests/Adapter/MemcachedAdapterTest.php | 138 +++++++++++++++++- .../Cache/Tests/Adapter/RedisAdapterTest.php | 4 +- src/Symfony/Component/Cache/phpunit.xml.dist | 1 + 5 files changed, 136 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4897e99485456..065caafe4111e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,7 @@ cache: - php-$MIN_PHP services: + - memcached - mongodb - redis-server @@ -60,7 +61,7 @@ before_install: - if [[ ! $skip && $PHP = 5.* ]]; then (echo yes | pecl install -f apcu-4.0.11 && echo apc.enable_cli = 1 >> $INI_FILE); fi - if [[ ! $skip && $PHP = 7.* ]]; then (echo yes | pecl install -f apcu-5.1.6 && echo apc.enable_cli = 1 >> $INI_FILE); fi - if [[ ! $deps && $PHP = 5.* ]]; then (cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> $INI_FILE); fi - - if [[ ! $skip && $PHP = 5.* ]]; then pecl install -f memcached-2.1.0; fi + - if [[ ! $skip && ! $PHP = hhvm* ]]; then echo extension = memcached.so >> $INI_FILE; fi - if [[ ! $skip && ! $PHP = hhvm* ]]; then echo extension = ldap.so >> $INI_FILE; fi - if [[ ! $skip && ! $PHP = hhvm* ]]; then echo extension = redis.so >> $INI_FILE; fi; - if [[ ! $skip && ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7652c58475569..336c320de95dd 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -16,6 +16,7 @@ + diff --git a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php index 55b4dc19b145d..7a766e073f60c 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Tests\Adapter; +use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\Cache\Adapter\MemcachedAdapter; class MemcachedAdapterTest extends AdapterTestCase @@ -28,14 +29,13 @@ public static function setupBeforeClass() if (!MemcachedAdapter::isSupported()) { self::markTestSkipped('Extension memcached >=2.2.0 required.'); } + self::$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST')); + self::$client->get('foo'); + $code = self::$client->getResultCode(); - self::$client = new \Memcached(); - self::$client->addServers(array(array( - getenv('MEMCACHED_HOST') ?: '127.0.0.1', - getenv('MEMCACHED_PORT') ?: 11211, - ))); - - parent::setupBeforeClass(); + if (\Memcached::RES_SUCCESS !== $code && \Memcached::RES_NOTFOUND !== $code) { + self::markTestSkipped('Memcached error: '.strtolower(self::$client->getResultMessage())); + } } public function createCachePool($defaultLifetime = 0) @@ -43,8 +43,130 @@ public function createCachePool($defaultLifetime = 0) return new MemcachedAdapter(self::$client, str_replace('\\', '.', __CLASS__), $defaultLifetime); } - public function testIsSupported() + public function testOptions() + { + $client = MemcachedAdapter::createConnection(array(), array( + 'libketama_compatible' => false, + 'distribution' => 'modula', + 'compression' => true, + 'serializer' => 'php', + 'hash' => 'md5', + )); + + $this->assertSame(\Memcached::SERIALIZER_PHP, $client->getOption(\Memcached::OPT_SERIALIZER)); + $this->assertSame(\Memcached::HASH_MD5, $client->getOption(\Memcached::OPT_HASH)); + $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); + $this->assertSame(0, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); + $this->assertSame(\Memcached::DISTRIBUTION_MODULA, $client->getOption(\Memcached::OPT_DISTRIBUTION)); + } + + /** + * @dataProvider provideBadOptions + * @expectedException \ErrorException + * @expectedExceptionMessage constant(): Couldn't find constant Memcached:: + */ + public function testBadOptions($name, $value) + { + MemcachedAdapter::createConnection(array(), array($name => $value)); + } + + public function provideBadOptions() + { + return array( + array('foo', 'bar'), + array('hash', 'zyx'), + array('serializer', 'zyx'), + array('distribution', 'zyx'), + ); + } + + /** + * @expectedException \Symfony\Component\Cache\Exception\CacheException + * @expectedExceptionMessage MemcachedAdapter: "binary_protocol" option must be enabled. + */ + public function testBinaryProtocol() + { + new MemcachedAdapter(MemcachedAdapter::createConnection(array(), array('binary_protocol' => false))); + } + + public function testDefaultOptions() { $this->assertTrue(MemcachedAdapter::isSupported()); + + $client = MemcachedAdapter::createConnection(array()); + + $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); + $this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL)); + $this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); + } + + /** + * @expectedException \Symfony\Component\Cache\Exception\CacheException + * @expectedExceptionMessage MemcachedAdapter: "serializer" option must be "php" or "igbinary". + */ + public function testOptionSerializer() + { + if (!\Memcached::HAVE_JSON) { + $this->markTestSkipped('Memcached::HAVE_JSON required'); + } + + new MemcachedAdapter(MemcachedAdapter::createConnection(array(), array('serializer' => 'json'))); + } + + /** + * @dataProvider provideServersSetting + */ + public function testServersSetting($dsn, $host, $port) + { + $client1 = MemcachedAdapter::createConnection($dsn); + $client2 = MemcachedAdapter::createConnection(array($dsn)); + $client3 = MemcachedAdapter::createConnection(array(array($host, $port))); + $expect = array( + 'host' => $host, + 'port' => $port, + ); + + $f = function ($s) { return array('host' => $s['host'], 'port' => $s['port']); }; + $this->assertSame(array($expect), array_map($f, $client1->getServerList())); + $this->assertSame(array($expect), array_map($f, $client2->getServerList())); + $this->assertSame(array($expect), array_map($f, $client3->getServerList())); + } + + public function provideServersSetting() + { + yield array( + 'memcached://127.0.0.1/50', + '127.0.0.1', + 11211, + ); + yield array( + 'memcached://localhost:11222?weight=25', + 'localhost', + 11222, + ); + if (ini_get('memcached.use_sasl')) { + yield array( + 'memcached://user:password@127.0.0.1?weight=50', + '127.0.0.1', + 11211, + ); + } + yield array( + 'memcached:///var/run/memcached.sock?weight=25', + '/var/run/memcached.sock', + 0, + ); + yield array( + 'memcached:///var/local/run/memcached.socket?weight=25', + '/var/local/run/memcached.socket', + 0, + ); + if (ini_get('memcached.use_sasl')) { + yield array( + 'memcached://user:password@/var/local/run/memcached.socket?weight=25', + '/var/local/run/memcached.socket', + 0, + ); + } } } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php index 301d531ac3530..a8f7a673f8b87 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/RedisAdapterTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Tests\Adapter; +use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\Cache\Adapter\RedisAdapter; class RedisAdapterTest extends AbstractRedisAdapterTest @@ -18,8 +19,7 @@ class RedisAdapterTest extends AbstractRedisAdapterTest public static function setupBeforeClass() { parent::setupBeforeClass(); - self::$redis = new \Redis(); - self::$redis->connect(getenv('REDIS_HOST')); + self::$redis = AbstractAdapter::createConnection('redis://'.getenv('REDIS_HOST')); } public function testCreateConnection() diff --git a/src/Symfony/Component/Cache/phpunit.xml.dist b/src/Symfony/Component/Cache/phpunit.xml.dist index 3e164e64b50d9..19b5496277219 100644 --- a/src/Symfony/Component/Cache/phpunit.xml.dist +++ b/src/Symfony/Component/Cache/phpunit.xml.dist @@ -9,6 +9,7 @@ +