2018-04-17 02:11:51 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is part of the Symfony package.
|
|
|
|
*
|
|
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
|
|
|
*
|
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
* file that was distributed with this source code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Symfony\Component\Cache\Tests\Adapter;
|
|
|
|
|
|
|
|
use Symfony\Component\Cache\Adapter\AbstractAdapter;
|
|
|
|
use Symfony\Component\Cache\Adapter\MemcachedAdapter;
|
|
|
|
|
|
|
|
class MemcachedAdapterTest extends AdapterTestCase
|
|
|
|
{
|
2024-01-12 05:08:24 +00:00
|
|
|
protected $skippedTests = [
|
2018-04-17 02:11:51 +00:00
|
|
|
'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite',
|
|
|
|
'testDefaultLifeTime' => 'Testing expiration slows down the test suite',
|
2024-01-12 05:08:24 +00:00
|
|
|
];
|
2018-04-17 02:11:51 +00:00
|
|
|
|
|
|
|
protected static $client;
|
|
|
|
|
2024-01-12 05:08:24 +00:00
|
|
|
public static function setUpBeforeClass()
|
2018-04-17 02:11:51 +00:00
|
|
|
{
|
|
|
|
if (!MemcachedAdapter::isSupported()) {
|
|
|
|
self::markTestSkipped('Extension memcached >=2.2.0 required.');
|
|
|
|
}
|
2024-01-12 05:08:24 +00:00
|
|
|
self::$client = AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST'), ['binary_protocol' => false]);
|
2018-04-17 02:11:51 +00:00
|
|
|
self::$client->get('foo');
|
|
|
|
$code = self::$client->getResultCode();
|
|
|
|
|
|
|
|
if (\Memcached::RES_SUCCESS !== $code && \Memcached::RES_NOTFOUND !== $code) {
|
|
|
|
self::markTestSkipped('Memcached error: '.strtolower(self::$client->getResultMessage()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function createCachePool($defaultLifetime = 0)
|
|
|
|
{
|
|
|
|
$client = $defaultLifetime ? AbstractAdapter::createConnection('memcached://'.getenv('MEMCACHED_HOST')) : self::$client;
|
|
|
|
|
|
|
|
return new MemcachedAdapter($client, str_replace('\\', '.', __CLASS__), $defaultLifetime);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testOptions()
|
|
|
|
{
|
2024-01-12 05:08:24 +00:00
|
|
|
$client = MemcachedAdapter::createConnection([], [
|
2018-04-17 02:11:51 +00:00
|
|
|
'libketama_compatible' => false,
|
|
|
|
'distribution' => 'modula',
|
|
|
|
'compression' => true,
|
|
|
|
'serializer' => 'php',
|
|
|
|
'hash' => 'md5',
|
2024-01-12 05:08:24 +00:00
|
|
|
]);
|
2018-04-17 02:11:51 +00:00
|
|
|
|
|
|
|
$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
|
|
|
|
*/
|
|
|
|
public function testBadOptions($name, $value)
|
|
|
|
{
|
2024-01-12 05:08:24 +00:00
|
|
|
if (\PHP_VERSION_ID < 80000) {
|
|
|
|
$this->expectException('ErrorException');
|
|
|
|
$this->expectExceptionMessage('constant(): Couldn\'t find constant Memcached::');
|
|
|
|
} else {
|
|
|
|
$this->expectException('Error');
|
|
|
|
$this->expectExceptionMessage('Undefined constant Memcached::');
|
|
|
|
}
|
|
|
|
|
|
|
|
MemcachedAdapter::createConnection([], [$name => $value]);
|
2018-04-17 02:11:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function provideBadOptions()
|
|
|
|
{
|
2024-01-12 05:08:24 +00:00
|
|
|
return [
|
|
|
|
['foo', 'bar'],
|
|
|
|
['hash', 'zyx'],
|
|
|
|
['serializer', 'zyx'],
|
|
|
|
['distribution', 'zyx'],
|
|
|
|
];
|
2018-04-17 02:11:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function testDefaultOptions()
|
|
|
|
{
|
|
|
|
$this->assertTrue(MemcachedAdapter::isSupported());
|
|
|
|
|
2024-01-12 05:08:24 +00:00
|
|
|
$client = MemcachedAdapter::createConnection([]);
|
2018-04-17 02:11:51 +00:00
|
|
|
|
|
|
|
$this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION));
|
|
|
|
$this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL));
|
2024-01-12 05:08:24 +00:00
|
|
|
$this->assertSame(1, $client->getOption(\Memcached::OPT_TCP_NODELAY));
|
2018-04-17 02:11:51 +00:00
|
|
|
$this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE));
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testOptionSerializer()
|
|
|
|
{
|
2024-01-12 05:08:24 +00:00
|
|
|
$this->expectException('Symfony\Component\Cache\Exception\CacheException');
|
|
|
|
$this->expectExceptionMessage('MemcachedAdapter: "serializer" option must be "php" or "igbinary".');
|
2018-04-17 02:11:51 +00:00
|
|
|
if (!\Memcached::HAVE_JSON) {
|
|
|
|
$this->markTestSkipped('Memcached::HAVE_JSON required');
|
|
|
|
}
|
|
|
|
|
2024-01-12 05:08:24 +00:00
|
|
|
new MemcachedAdapter(MemcachedAdapter::createConnection([], ['serializer' => 'json']));
|
2018-04-17 02:11:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider provideServersSetting
|
|
|
|
*/
|
|
|
|
public function testServersSetting($dsn, $host, $port)
|
|
|
|
{
|
|
|
|
$client1 = MemcachedAdapter::createConnection($dsn);
|
2024-01-12 05:08:24 +00:00
|
|
|
$client2 = MemcachedAdapter::createConnection([$dsn]);
|
|
|
|
$client3 = MemcachedAdapter::createConnection([[$host, $port]]);
|
|
|
|
$expect = [
|
2018-04-17 02:11:51 +00:00
|
|
|
'host' => $host,
|
|
|
|
'port' => $port,
|
2024-01-12 05:08:24 +00:00
|
|
|
];
|
2018-04-17 02:11:51 +00:00
|
|
|
|
2024-01-12 05:08:24 +00:00
|
|
|
$f = function ($s) { return ['host' => $s['host'], 'port' => $s['port']]; };
|
|
|
|
$this->assertSame([$expect], array_map($f, $client1->getServerList()));
|
|
|
|
$this->assertSame([$expect], array_map($f, $client2->getServerList()));
|
|
|
|
$this->assertSame([$expect], array_map($f, $client3->getServerList()));
|
2018-04-17 02:11:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function provideServersSetting()
|
|
|
|
{
|
2024-01-12 05:08:24 +00:00
|
|
|
yield [
|
2018-04-17 02:11:51 +00:00
|
|
|
'memcached://127.0.0.1/50',
|
|
|
|
'127.0.0.1',
|
|
|
|
11211,
|
2024-01-12 05:08:24 +00:00
|
|
|
];
|
|
|
|
yield [
|
2018-04-17 02:11:51 +00:00
|
|
|
'memcached://localhost:11222?weight=25',
|
|
|
|
'localhost',
|
|
|
|
11222,
|
2024-01-12 05:08:24 +00:00
|
|
|
];
|
|
|
|
if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) {
|
|
|
|
yield [
|
2018-04-17 02:11:51 +00:00
|
|
|
'memcached://user:password@127.0.0.1?weight=50',
|
|
|
|
'127.0.0.1',
|
|
|
|
11211,
|
2024-01-12 05:08:24 +00:00
|
|
|
];
|
2018-04-17 02:11:51 +00:00
|
|
|
}
|
2024-01-12 05:08:24 +00:00
|
|
|
yield [
|
2018-04-17 02:11:51 +00:00
|
|
|
'memcached:///var/run/memcached.sock?weight=25',
|
|
|
|
'/var/run/memcached.sock',
|
|
|
|
0,
|
2024-01-12 05:08:24 +00:00
|
|
|
];
|
|
|
|
yield [
|
2018-04-17 02:11:51 +00:00
|
|
|
'memcached:///var/local/run/memcached.socket?weight=25',
|
|
|
|
'/var/local/run/memcached.socket',
|
|
|
|
0,
|
2024-01-12 05:08:24 +00:00
|
|
|
];
|
|
|
|
if (filter_var(ini_get('memcached.use_sasl'), \FILTER_VALIDATE_BOOLEAN)) {
|
|
|
|
yield [
|
2018-04-17 02:11:51 +00:00
|
|
|
'memcached://user:password@/var/local/run/memcached.socket?weight=25',
|
|
|
|
'/var/local/run/memcached.socket',
|
|
|
|
0,
|
2024-01-12 05:08:24 +00:00
|
|
|
];
|
2018-04-17 02:11:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @dataProvider provideDsnWithOptions
|
|
|
|
*/
|
|
|
|
public function testDsnWithOptions($dsn, array $options, array $expectedOptions)
|
|
|
|
{
|
|
|
|
$client = MemcachedAdapter::createConnection($dsn, $options);
|
|
|
|
|
|
|
|
foreach ($expectedOptions as $option => $expect) {
|
|
|
|
$this->assertSame($expect, $client->getOption($option));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function provideDsnWithOptions()
|
|
|
|
{
|
|
|
|
if (!class_exists('\Memcached')) {
|
|
|
|
self::markTestSkipped('Extension memcached required.');
|
|
|
|
}
|
|
|
|
|
2024-01-12 05:08:24 +00:00
|
|
|
yield [
|
2018-04-17 02:11:51 +00:00
|
|
|
'memcached://localhost:11222?retry_timeout=10',
|
2024-01-12 05:08:24 +00:00
|
|
|
[\Memcached::OPT_RETRY_TIMEOUT => 8],
|
|
|
|
[\Memcached::OPT_RETRY_TIMEOUT => 10],
|
|
|
|
];
|
|
|
|
yield [
|
2018-04-17 02:11:51 +00:00
|
|
|
'memcached://localhost:11222?socket_recv_size=1&socket_send_size=2',
|
2024-01-12 05:08:24 +00:00
|
|
|
[\Memcached::OPT_RETRY_TIMEOUT => 8],
|
|
|
|
[\Memcached::OPT_SOCKET_RECV_SIZE => 1, \Memcached::OPT_SOCKET_SEND_SIZE => 2, \Memcached::OPT_RETRY_TIMEOUT => 8],
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testClear()
|
|
|
|
{
|
|
|
|
$this->assertTrue($this->createCachePool()->clear());
|
2018-04-17 02:11:51 +00:00
|
|
|
}
|
|
|
|
}
|