MemcachedEngineTest.php 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP(tm) Project
  13. * @since 2.5.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\Cache\Engine;
  17. use Cake\Cache\Cache;
  18. use Cake\Cache\Engine\MemcachedEngine;
  19. use Cake\TestSuite\TestCase;
  20. use DateInterval;
  21. use Memcached;
  22. /**
  23. * MemcachedEngineTest class
  24. */
  25. class MemcachedEngineTest extends TestCase
  26. {
  27. /**
  28. * @var string
  29. */
  30. protected $port = '11211';
  31. /**
  32. * setUp method
  33. *
  34. * @return void
  35. */
  36. public function setUp(): void
  37. {
  38. parent::setUp();
  39. $this->skipIf(!class_exists('Memcached'), 'Memcached is not installed or configured properly.');
  40. $this->port = env('MEMCACHED_PORT', $this->port);
  41. // phpcs:disable
  42. $socket = @fsockopen('127.0.0.1', (int)$this->port, $errno, $errstr, 1);
  43. // phpcs:enable
  44. $this->skipIf(!$socket, 'Memcached is not running.');
  45. fclose($socket);
  46. $this->_configCache();
  47. }
  48. /**
  49. * Helper method for testing.
  50. *
  51. * @param array $config
  52. * @return void
  53. */
  54. protected function _configCache($config = [])
  55. {
  56. $defaults = [
  57. 'className' => 'Memcached',
  58. 'prefix' => 'cake_',
  59. 'duration' => 3600,
  60. 'servers' => ['127.0.0.1:' . $this->port],
  61. ];
  62. Cache::drop('memcached');
  63. Cache::setConfig('memcached', array_merge($defaults, $config));
  64. }
  65. /**
  66. * tearDown method
  67. *
  68. * @return void
  69. */
  70. public function tearDown(): void
  71. {
  72. parent::tearDown();
  73. Cache::drop('memcached');
  74. Cache::drop('memcached2');
  75. Cache::drop('memcached_groups');
  76. Cache::drop('memcached_helper');
  77. Cache::drop('compressed_memcached');
  78. Cache::drop('long_memcached');
  79. Cache::drop('short_memcached');
  80. }
  81. /**
  82. * testConfig method
  83. *
  84. * @return void
  85. */
  86. public function testConfig()
  87. {
  88. $config = Cache::pool('memcached')->getConfig();
  89. unset($config['path']);
  90. $expecting = [
  91. 'prefix' => 'cake_',
  92. 'duration' => 3600,
  93. 'servers' => ['127.0.0.1:' . $this->port],
  94. 'persistent' => false,
  95. 'compress' => false,
  96. 'username' => null,
  97. 'password' => null,
  98. 'groups' => [],
  99. 'serialize' => 'php',
  100. 'options' => [],
  101. 'host' => null,
  102. 'port' => null,
  103. ];
  104. $this->assertEquals($expecting, $config);
  105. }
  106. /**
  107. * testCompressionSetting method
  108. *
  109. * @return void
  110. */
  111. public function testCompressionSetting()
  112. {
  113. $Memcached = new MemcachedEngine();
  114. $Memcached->init([
  115. 'engine' => 'Memcached',
  116. 'servers' => ['127.0.0.1:' . $this->port],
  117. 'compress' => false,
  118. ]);
  119. $this->assertFalse($Memcached->getOption(\Memcached::OPT_COMPRESSION));
  120. $MemcachedCompressed = new MemcachedEngine();
  121. $MemcachedCompressed->init([
  122. 'engine' => 'Memcached',
  123. 'servers' => ['127.0.0.1:' . $this->port],
  124. 'compress' => true,
  125. ]);
  126. $this->assertTrue($MemcachedCompressed->getOption(\Memcached::OPT_COMPRESSION));
  127. }
  128. /**
  129. * test setting options
  130. *
  131. * @return void
  132. */
  133. public function testOptionsSetting()
  134. {
  135. $memcached = new MemcachedEngine();
  136. $memcached->init([
  137. 'engine' => 'Memcached',
  138. 'servers' => ['127.0.0.1:' . $this->port],
  139. 'options' => [
  140. Memcached::OPT_BINARY_PROTOCOL => true,
  141. ],
  142. ]);
  143. $this->assertSame(1, $memcached->getOption(Memcached::OPT_BINARY_PROTOCOL));
  144. }
  145. /**
  146. * test accepts only valid serializer engine
  147. *
  148. * @return void
  149. */
  150. public function testInvalidSerializerSetting()
  151. {
  152. $this->expectException(\InvalidArgumentException::class);
  153. $this->expectExceptionMessage('invalid_serializer is not a valid serializer engine for Memcached');
  154. $Memcached = new MemcachedEngine();
  155. $config = [
  156. 'className' => 'Memcached',
  157. 'servers' => ['127.0.0.1:' . $this->port],
  158. 'persistent' => false,
  159. 'serialize' => 'invalid_serializer',
  160. ];
  161. $Memcached->init($config);
  162. }
  163. /**
  164. * testPhpSerializerSetting method
  165. *
  166. * @return void
  167. */
  168. public function testPhpSerializerSetting()
  169. {
  170. $Memcached = new MemcachedEngine();
  171. $config = [
  172. 'className' => 'Memcached',
  173. 'servers' => ['127.0.0.1:' . $this->port],
  174. 'persistent' => false,
  175. 'serialize' => 'php',
  176. ];
  177. $Memcached->init($config);
  178. $this->assertSame(Memcached::SERIALIZER_PHP, $Memcached->getOption(Memcached::OPT_SERIALIZER));
  179. }
  180. /**
  181. * testJsonSerializerSetting method
  182. *
  183. * @return void
  184. */
  185. public function testJsonSerializerSetting()
  186. {
  187. $this->skipIf(
  188. !Memcached::HAVE_JSON,
  189. 'Memcached extension is not compiled with json support'
  190. );
  191. $Memcached = new MemcachedEngine();
  192. $config = [
  193. 'engine' => 'Memcached',
  194. 'servers' => ['127.0.0.1:' . $this->port],
  195. 'persistent' => false,
  196. 'serialize' => 'json',
  197. ];
  198. $Memcached->init($config);
  199. $this->assertSame(Memcached::SERIALIZER_JSON, $Memcached->getOption(Memcached::OPT_SERIALIZER));
  200. }
  201. /**
  202. * testIgbinarySerializerSetting method
  203. *
  204. * @return void
  205. */
  206. public function testIgbinarySerializerSetting()
  207. {
  208. $this->skipIf(
  209. !Memcached::HAVE_IGBINARY,
  210. 'Memcached extension is not compiled with igbinary support'
  211. );
  212. $Memcached = new MemcachedEngine();
  213. $config = [
  214. 'engine' => 'Memcached',
  215. 'servers' => ['127.0.0.1:' . $this->port],
  216. 'persistent' => false,
  217. 'serialize' => 'igbinary',
  218. ];
  219. $Memcached->init($config);
  220. $this->assertSame(Memcached::SERIALIZER_IGBINARY, $Memcached->getOption(Memcached::OPT_SERIALIZER));
  221. }
  222. /**
  223. * testMsgpackSerializerSetting method
  224. *
  225. * @return void
  226. */
  227. public function testMsgpackSerializerSetting()
  228. {
  229. $this->skipIf(
  230. !defined('Memcached::HAVE_MSGPACK') || !Memcached::HAVE_MSGPACK,
  231. 'Memcached extension is not compiled with msgpack support'
  232. );
  233. $Memcached = new MemcachedEngine();
  234. $config = [
  235. 'engine' => 'Memcached',
  236. 'servers' => ['127.0.0.1:' . $this->port],
  237. 'persistent' => false,
  238. 'serialize' => 'msgpack',
  239. ];
  240. $Memcached->init($config);
  241. $this->assertSame(Memcached::SERIALIZER_MSGPACK, $Memcached->getOption(Memcached::OPT_SERIALIZER));
  242. }
  243. /**
  244. * testJsonSerializerThrowException method
  245. *
  246. * @return void
  247. */
  248. public function testJsonSerializerThrowException()
  249. {
  250. $this->skipIf(
  251. (bool)Memcached::HAVE_JSON,
  252. 'Memcached extension is compiled with json support'
  253. );
  254. $Memcached = new MemcachedEngine();
  255. $config = [
  256. 'className' => 'Memcached',
  257. 'servers' => ['127.0.0.1:' . $this->port],
  258. 'persistent' => false,
  259. 'serialize' => 'json',
  260. ];
  261. $this->expectException(\InvalidArgumentException::class);
  262. $this->expectExceptionMessage('Memcached extension is not compiled with json support');
  263. $Memcached->init($config);
  264. }
  265. /**
  266. * testMsgpackSerializerThrowException method
  267. *
  268. * @return void
  269. */
  270. public function testMsgpackSerializerThrowException()
  271. {
  272. $this->skipIf(
  273. !defined('Memcached::HAVE_MSGPACK'),
  274. 'Memcached::HAVE_MSGPACK constant is not available in Memcached below 3.0.0'
  275. );
  276. $this->skipIf(
  277. (bool)Memcached::HAVE_MSGPACK,
  278. 'Memcached extension is compiled with msgpack support'
  279. );
  280. $Memcached = new MemcachedEngine();
  281. $config = [
  282. 'engine' => 'Memcached',
  283. 'servers' => ['127.0.0.1:' . $this->port],
  284. 'persistent' => false,
  285. 'serialize' => 'msgpack',
  286. ];
  287. $this->expectException(\InvalidArgumentException::class);
  288. $this->expectExceptionMessage('Memcached extension is not compiled with msgpack support');
  289. $Memcached->init($config);
  290. }
  291. /**
  292. * testIgbinarySerializerThrowException method
  293. *
  294. * @return void
  295. */
  296. public function testIgbinarySerializerThrowException()
  297. {
  298. $this->skipIf(
  299. (bool)Memcached::HAVE_IGBINARY,
  300. 'Memcached extension is compiled with igbinary support'
  301. );
  302. $Memcached = new MemcachedEngine();
  303. $config = [
  304. 'engine' => 'Memcached',
  305. 'servers' => ['127.0.0.1:' . $this->port],
  306. 'persistent' => false,
  307. 'serialize' => 'igbinary',
  308. ];
  309. $this->expectException(\InvalidArgumentException::class);
  310. $this->expectExceptionMessage('Memcached extension is not compiled with igbinary support');
  311. $Memcached->init($config);
  312. }
  313. /**
  314. * test using authentication without memcached installed with SASL support
  315. * throw an exception
  316. *
  317. * @return void
  318. */
  319. public function testSaslAuthException()
  320. {
  321. $this->expectException(\InvalidArgumentException::class);
  322. $this->expectExceptionMessage('Memcached extension is not build with SASL support');
  323. $this->skipIf(
  324. method_exists(Memcached::class, 'setSaslAuthData'),
  325. 'Cannot test exception when sasl has been compiled in.'
  326. );
  327. $MemcachedEngine = new MemcachedEngine();
  328. $config = [
  329. 'engine' => 'Memcached',
  330. 'servers' => ['127.0.0.1:' . $this->port],
  331. 'persistent' => false,
  332. 'username' => 'test',
  333. 'password' => 'password',
  334. ];
  335. $this->expectException(\InvalidArgumentException::class);
  336. $this->expectExceptionMessage('Memcached extension is not built with SASL support');
  337. $MemcachedEngine->init($config);
  338. }
  339. /**
  340. * testConfigDifferentPorts method
  341. *
  342. * @expectedException InvalidArgumentException
  343. * @expectedExceptionMessage Invalid cache configuration. Multiple persistent cache configurations are detected with different 'servers' values. 'servers' values for persistent cache configurations must be the same when using the same persistence id.
  344. * @return void
  345. */
  346. public function testConfigDifferentPorts()
  347. {
  348. $Memcached1 = new MemcachedEngine();
  349. $config1 = [
  350. 'className' => 'Memcached',
  351. 'servers' => ['127.0.0.1:11211'],
  352. 'persistent' => '123',
  353. ];
  354. $Memcached1->init($config1);
  355. $Memcached2 = new MemcachedEngine();
  356. $config2 = [
  357. 'className' => 'Memcached',
  358. 'servers' => ['127.0.0.1:11212'],
  359. 'persistent' => '123',
  360. ];
  361. $Memcached2->init($config2);
  362. }
  363. /**
  364. * testConfig method
  365. *
  366. * @return void
  367. */
  368. public function testMultipleServers()
  369. {
  370. $servers = ['127.0.0.1:' . $this->port, '127.0.0.1:11222'];
  371. $available = true;
  372. $Memcached = new \Memcached();
  373. foreach ($servers as $server) {
  374. [$host, $port] = explode(':', $server);
  375. // phpcs:disable
  376. if (!$Memcached->addServer($host, (int)$port)) {
  377. $available = false;
  378. }
  379. // phpcs:enable
  380. }
  381. $this->skipIf(!$available, 'Need memcached servers at ' . implode(', ', $servers) . ' to run this test.');
  382. $Memcached = new MemcachedEngine();
  383. $Memcached->init(['engine' => 'Memcached', 'servers' => $servers]);
  384. $config = $Memcached->getConfig();
  385. $this->assertEquals($config['servers'], $servers);
  386. Cache::drop('dual_server');
  387. }
  388. /**
  389. * test connecting to an ipv6 server.
  390. *
  391. * @return void
  392. */
  393. public function testConnectIpv6()
  394. {
  395. $Memcached = new MemcachedEngine();
  396. $result = $Memcached->init([
  397. 'prefix' => 'cake_',
  398. 'duration' => 200,
  399. 'engine' => 'Memcached',
  400. 'servers' => [
  401. '[::1]:' . $this->port,
  402. ],
  403. ]);
  404. $this->assertTrue($result);
  405. }
  406. /**
  407. * test domain starts with u
  408. *
  409. * @return void
  410. */
  411. public function testParseServerStringWithU()
  412. {
  413. $Memcached = new MemcachedEngine();
  414. $result = $Memcached->parseServerString('udomain.net:13211');
  415. $this->assertEquals(['udomain.net', '13211'], $result);
  416. }
  417. /**
  418. * test non latin domains.
  419. *
  420. * @return void
  421. */
  422. public function testParseServerStringNonLatin()
  423. {
  424. $Memcached = new MemcachedEngine();
  425. $result = $Memcached->parseServerString('schülervz.net:13211');
  426. $this->assertEquals(['schülervz.net', '13211'], $result);
  427. $result = $Memcached->parseServerString('sülül:1111');
  428. $this->assertEquals(['sülül', '1111'], $result);
  429. }
  430. /**
  431. * test unix sockets.
  432. *
  433. * @return void
  434. */
  435. public function testParseServerStringUnix()
  436. {
  437. $Memcached = new MemcachedEngine();
  438. $result = $Memcached->parseServerString('unix:///path/to/memcachedd.sock');
  439. $this->assertEquals(['/path/to/memcachedd.sock', 0], $result);
  440. }
  441. /**
  442. * testReadAndWriteCache method
  443. *
  444. * @return void
  445. */
  446. public function testReadAndWriteCache()
  447. {
  448. $this->_configCache(['duration' => 1]);
  449. $result = Cache::read('test', 'memcached');
  450. $this->assertNull($result);
  451. $data = 'this is a test of the emergency broadcasting system';
  452. $result = Cache::write('test', $data, 'memcached');
  453. $this->assertTrue($result);
  454. $result = Cache::read('test', 'memcached');
  455. $expecting = $data;
  456. $this->assertSame($expecting, $result);
  457. Cache::delete('test', 'memcached');
  458. }
  459. /**
  460. * Test get with default value
  461. *
  462. * @return void
  463. */
  464. public function testGetDefaultValue()
  465. {
  466. $memcache = Cache::pool('memcached');
  467. $this->assertFalse($memcache->get('nope', false));
  468. $this->assertNull($memcache->get('nope', null));
  469. $this->assertTrue($memcache->get('nope', true));
  470. $this->assertSame(0, $memcache->get('nope', 0));
  471. $memcache->set('yep', 0);
  472. $this->assertSame(0, $memcache->get('yep', false));
  473. }
  474. /**
  475. * testReadMany method
  476. *
  477. * @return void
  478. */
  479. public function testReadMany()
  480. {
  481. $this->_configCache(['duration' => 2]);
  482. $data = [
  483. 'App.falseTest' => false,
  484. 'App.trueTest' => true,
  485. 'App.nullTest' => null,
  486. 'App.zeroTest' => 0,
  487. 'App.zeroTest2' => '0',
  488. ];
  489. foreach ($data as $key => $value) {
  490. Cache::write($key, $value, 'memcached');
  491. }
  492. $read = Cache::readMany(array_merge(array_keys($data), ['App.doesNotExist']), 'memcached');
  493. $this->assertFalse($read['App.falseTest']);
  494. $this->assertTrue($read['App.trueTest']);
  495. $this->assertNull($read['App.nullTest']);
  496. $this->assertSame($read['App.zeroTest'], 0);
  497. $this->assertSame($read['App.zeroTest2'], '0');
  498. $this->assertNull($read['App.doesNotExist']);
  499. }
  500. /**
  501. * testWriteMany method
  502. *
  503. * @return void
  504. */
  505. public function testWriteMany()
  506. {
  507. $this->_configCache(['duration' => 2]);
  508. $data = [
  509. 'App.falseTest' => false,
  510. 'App.trueTest' => true,
  511. 'App.nullTest' => null,
  512. 'App.zeroTest' => 0,
  513. 'App.zeroTest2' => '0',
  514. ];
  515. Cache::writeMany($data, 'memcached');
  516. $this->assertFalse(Cache::read('App.falseTest', 'memcached'));
  517. $this->assertTrue(Cache::read('App.trueTest', 'memcached'));
  518. $this->assertNull(Cache::read('App.nullTest', 'memcached'));
  519. $this->assertSame(Cache::read('App.zeroTest', 'memcached'), 0);
  520. $this->assertSame(Cache::read('App.zeroTest2', 'memcached'), '0');
  521. }
  522. /**
  523. * testExpiry method
  524. *
  525. * @return void
  526. */
  527. public function testExpiry()
  528. {
  529. $this->_configCache(['duration' => 1]);
  530. $result = Cache::read('test', 'memcached');
  531. $this->assertNull($result);
  532. $data = 'this is a test of the emergency broadcasting system';
  533. $result = Cache::write('other_test', $data, 'memcached');
  534. $this->assertTrue($result);
  535. sleep(2);
  536. $result = Cache::read('other_test', 'memcached');
  537. $this->assertNull($result);
  538. $this->_configCache(['duration' => '+1 second']);
  539. $data = 'this is a test of the emergency broadcasting system';
  540. $result = Cache::write('other_test', $data, 'memcached');
  541. $this->assertTrue($result);
  542. sleep(3);
  543. $result = Cache::read('other_test', 'memcached');
  544. $this->assertNull($result);
  545. $result = Cache::read('other_test', 'memcached');
  546. $this->assertNull($result);
  547. $this->_configCache(['duration' => '+29 days']);
  548. $data = 'this is a test of the emergency broadcasting system';
  549. $result = Cache::write('long_expiry_test', $data, 'memcached');
  550. $this->assertTrue($result);
  551. sleep(2);
  552. $result = Cache::read('long_expiry_test', 'memcached');
  553. $expecting = $data;
  554. $this->assertSame($expecting, $result);
  555. }
  556. /**
  557. * test set ttl parameter
  558. *
  559. * @return void
  560. */
  561. public function testSetWithTtl()
  562. {
  563. $this->_configCache(['duration' => 99]);
  564. $engine = Cache::pool('memcached');
  565. $this->assertNull($engine->get('test'));
  566. $data = 'this is a test of the emergency broadcasting system';
  567. $this->assertTrue($engine->set('default_ttl', $data));
  568. $this->assertTrue($engine->set('int_ttl', $data, 1));
  569. $this->assertTrue($engine->set('interval_ttl', $data, new DateInterval('PT1S')));
  570. sleep(2);
  571. $this->assertNull($engine->get('int_ttl'));
  572. $this->assertNull($engine->get('interval_ttl'));
  573. $this->assertSame($data, $engine->get('default_ttl'));
  574. }
  575. /**
  576. * testDeleteCache method
  577. *
  578. * @return void
  579. */
  580. public function testDeleteCache()
  581. {
  582. $data = 'this is a test of the emergency broadcasting system';
  583. $result = Cache::write('delete_test', $data, 'memcached');
  584. $this->assertTrue($result);
  585. $result = Cache::delete('delete_test', 'memcached');
  586. $this->assertTrue($result);
  587. }
  588. /**
  589. * testDeleteMany method
  590. *
  591. * @return void
  592. */
  593. public function testDeleteMany()
  594. {
  595. $this->skipIf(defined('HHVM_VERSION'), 'HHVM does not implement deleteMulti');
  596. $this->_configCache();
  597. $data = [
  598. 'App.falseTest' => false,
  599. 'App.trueTest' => true,
  600. 'App.nullTest' => null,
  601. 'App.zeroTest' => 0,
  602. 'App.zeroTest2' => '0',
  603. ];
  604. foreach ($data as $key => $value) {
  605. Cache::write($key, $value, 'memcached');
  606. }
  607. Cache::write('App.keepTest', 'keepMe', 'memcached');
  608. Cache::deleteMany(array_merge(array_keys($data), ['App.doesNotExist']), 'memcached');
  609. $this->assertNull(Cache::read('App.falseTest', 'memcached'));
  610. $this->assertNull(Cache::read('App.trueTest', 'memcached'));
  611. $this->assertNull(Cache::read('App.nullTest', 'memcached'));
  612. $this->assertNull(Cache::read('App.zeroTest', 'memcached'));
  613. $this->assertNull(Cache::read('App.zeroTest2', 'memcached'));
  614. $this->assertSame('keepMe', Cache::read('App.keepTest', 'memcached'));
  615. }
  616. /**
  617. * testDecrement method
  618. *
  619. * @return void
  620. */
  621. public function testDecrement()
  622. {
  623. $result = Cache::write('test_decrement', 5, 'memcached');
  624. $this->assertTrue($result);
  625. $result = Cache::decrement('test_decrement', 1, 'memcached');
  626. $this->assertSame(4, $result);
  627. $result = Cache::read('test_decrement', 'memcached');
  628. $this->assertSame(4, $result);
  629. $result = Cache::decrement('test_decrement', 2, 'memcached');
  630. $this->assertSame(2, $result);
  631. $result = Cache::read('test_decrement', 'memcached');
  632. $this->assertSame(2, $result);
  633. Cache::delete('test_decrement', 'memcached');
  634. }
  635. /**
  636. * test decrementing compressed keys
  637. *
  638. * @return void
  639. */
  640. public function testDecrementCompressedKeys()
  641. {
  642. Cache::setConfig('compressed_memcached', [
  643. 'engine' => 'Memcached',
  644. 'duration' => '+2 seconds',
  645. 'servers' => ['127.0.0.1:' . $this->port],
  646. 'compress' => true,
  647. ]);
  648. $result = Cache::write('test_decrement', 5, 'compressed_memcached');
  649. $this->assertTrue($result);
  650. $result = Cache::decrement('test_decrement', 1, 'compressed_memcached');
  651. $this->assertSame(4, $result);
  652. $result = Cache::read('test_decrement', 'compressed_memcached');
  653. $this->assertSame(4, $result);
  654. $result = Cache::decrement('test_decrement', 2, 'compressed_memcached');
  655. $this->assertSame(2, $result);
  656. $result = Cache::read('test_decrement', 'compressed_memcached');
  657. $this->assertSame(2, $result);
  658. Cache::delete('test_decrement', 'compressed_memcached');
  659. }
  660. /**
  661. * testIncrement method
  662. *
  663. * @return void
  664. */
  665. public function testIncrement()
  666. {
  667. $result = Cache::write('test_increment', 5, 'memcached');
  668. $this->assertTrue($result);
  669. $result = Cache::increment('test_increment', 1, 'memcached');
  670. $this->assertSame(6, $result);
  671. $result = Cache::read('test_increment', 'memcached');
  672. $this->assertSame(6, $result);
  673. $result = Cache::increment('test_increment', 2, 'memcached');
  674. $this->assertSame(8, $result);
  675. $result = Cache::read('test_increment', 'memcached');
  676. $this->assertSame(8, $result);
  677. Cache::delete('test_increment', 'memcached');
  678. }
  679. /**
  680. * Test that increment and decrement set ttls.
  681. *
  682. * @return void
  683. */
  684. public function testIncrementDecrementExpiring()
  685. {
  686. $this->_configCache(['duration' => 1]);
  687. Cache::write('test_increment', 1, 'memcached');
  688. Cache::write('test_decrement', 1, 'memcached');
  689. $this->assertSame(2, Cache::increment('test_increment', 1, 'memcached'));
  690. $this->assertSame(0, Cache::decrement('test_decrement', 1, 'memcached'));
  691. sleep(1);
  692. $this->assertNull(Cache::read('test_increment', 'memcached'));
  693. $this->assertNull(Cache::read('test_decrement', 'memcached'));
  694. }
  695. /**
  696. * test incrementing compressed keys
  697. *
  698. * @return void
  699. */
  700. public function testIncrementCompressedKeys()
  701. {
  702. Cache::setConfig('compressed_memcached', [
  703. 'engine' => 'Memcached',
  704. 'duration' => '+2 seconds',
  705. 'servers' => ['127.0.0.1:' . $this->port],
  706. 'compress' => true,
  707. ]);
  708. $result = Cache::write('test_increment', 5, 'compressed_memcached');
  709. $this->assertTrue($result);
  710. $result = Cache::increment('test_increment', 1, 'compressed_memcached');
  711. $this->assertSame(6, $result);
  712. $result = Cache::read('test_increment', 'compressed_memcached');
  713. $this->assertSame(6, $result);
  714. $result = Cache::increment('test_increment', 2, 'compressed_memcached');
  715. $this->assertSame(8, $result);
  716. $result = Cache::read('test_increment', 'compressed_memcached');
  717. $this->assertSame(8, $result);
  718. Cache::delete('test_increment', 'compressed_memcached');
  719. }
  720. /**
  721. * test that configurations don't conflict, when a file engine is declared after a memcached one.
  722. *
  723. * @return void
  724. */
  725. public function testConfigurationConflict()
  726. {
  727. Cache::setConfig('long_memcached', [
  728. 'engine' => 'Memcached',
  729. 'duration' => '+3 seconds',
  730. 'servers' => ['127.0.0.1:' . $this->port],
  731. ]);
  732. Cache::setConfig('short_memcached', [
  733. 'engine' => 'Memcached',
  734. 'duration' => '+2 seconds',
  735. 'servers' => ['127.0.0.1:' . $this->port],
  736. ]);
  737. $this->assertTrue(Cache::write('duration_test', 'yay', 'long_memcached'));
  738. $this->assertTrue(Cache::write('short_duration_test', 'boo', 'short_memcached'));
  739. $this->assertSame('yay', Cache::read('duration_test', 'long_memcached'), 'Value was not read %s');
  740. $this->assertSame('boo', Cache::read('short_duration_test', 'short_memcached'), 'Value was not read %s');
  741. usleep(500000);
  742. $this->assertSame('yay', Cache::read('duration_test', 'long_memcached'), 'Value was not read %s');
  743. usleep(3000000);
  744. $this->assertNull(Cache::read('short_duration_test', 'short_memcached'), 'Cache was not invalidated %s');
  745. $this->assertNull(Cache::read('duration_test', 'long_memcached'), 'Value did not expire %s');
  746. Cache::delete('duration_test', 'long_memcached');
  747. Cache::delete('short_duration_test', 'short_memcached');
  748. }
  749. /**
  750. * test clearing memcached.
  751. *
  752. * @return void
  753. */
  754. public function testClear()
  755. {
  756. Cache::setConfig('memcached2', [
  757. 'engine' => 'Memcached',
  758. 'prefix' => 'cake2_',
  759. 'duration' => 3600,
  760. 'servers' => ['127.0.0.1:' . $this->port],
  761. ]);
  762. Cache::write('some_value', 'cache1', 'memcached');
  763. Cache::write('some_value', 'cache2', 'memcached2');
  764. sleep(1);
  765. $this->assertTrue(Cache::clear('memcached'));
  766. $this->assertNull(Cache::read('some_value', 'memcached'));
  767. $this->assertSame('cache2', Cache::read('some_value', 'memcached2'));
  768. Cache::clear('memcached2');
  769. }
  770. /**
  771. * test that a 0 duration can successfully write.
  772. *
  773. * @return void
  774. */
  775. public function testZeroDuration()
  776. {
  777. $this->_configCache(['duration' => 0]);
  778. $result = Cache::write('test_key', 'written!', 'memcached');
  779. $this->assertTrue($result);
  780. $result = Cache::read('test_key', 'memcached');
  781. $this->assertSame('written!', $result);
  782. }
  783. /**
  784. * Tests that configuring groups for stored keys return the correct values when read/written
  785. * Shows that altering the group value is equivalent to deleting all keys under the same
  786. * group
  787. *
  788. * @return void
  789. */
  790. public function testGroupReadWrite()
  791. {
  792. Cache::setConfig('memcached_groups', [
  793. 'engine' => 'Memcached',
  794. 'duration' => 3600,
  795. 'groups' => ['group_a', 'group_b'],
  796. 'prefix' => 'test_',
  797. 'servers' => ['127.0.0.1:' . $this->port],
  798. ]);
  799. Cache::setConfig('memcached_helper', [
  800. 'engine' => 'Memcached',
  801. 'duration' => 3600,
  802. 'prefix' => 'test_',
  803. 'servers' => ['127.0.0.1:' . $this->port],
  804. ]);
  805. $this->assertTrue(Cache::write('test_groups', 'value', 'memcached_groups'));
  806. $this->assertSame('value', Cache::read('test_groups', 'memcached_groups'));
  807. Cache::increment('group_a', 1, 'memcached_helper');
  808. $this->assertNull(Cache::read('test_groups', 'memcached_groups'));
  809. $this->assertTrue(Cache::write('test_groups', 'value2', 'memcached_groups'));
  810. $this->assertSame('value2', Cache::read('test_groups', 'memcached_groups'));
  811. Cache::increment('group_b', 1, 'memcached_helper');
  812. $this->assertNull(Cache::read('test_groups', 'memcached_groups'));
  813. $this->assertTrue(Cache::write('test_groups', 'value3', 'memcached_groups'));
  814. $this->assertSame('value3', Cache::read('test_groups', 'memcached_groups'));
  815. }
  816. /**
  817. * Tests that deleting from a groups-enabled config is possible
  818. *
  819. * @return void
  820. */
  821. public function testGroupDelete()
  822. {
  823. Cache::setConfig('memcached_groups', [
  824. 'engine' => 'Memcached',
  825. 'duration' => 3600,
  826. 'groups' => ['group_a', 'group_b'],
  827. 'servers' => ['127.0.0.1:' . $this->port],
  828. ]);
  829. $this->assertTrue(Cache::write('test_groups', 'value', 'memcached_groups'));
  830. $this->assertSame('value', Cache::read('test_groups', 'memcached_groups'));
  831. $this->assertTrue(Cache::delete('test_groups', 'memcached_groups'));
  832. $this->assertNull(Cache::read('test_groups', 'memcached_groups'));
  833. }
  834. /**
  835. * Test clearing a cache group
  836. *
  837. * @return void
  838. */
  839. public function testGroupClear()
  840. {
  841. Cache::setConfig('memcached_groups', [
  842. 'engine' => 'Memcached',
  843. 'duration' => 3600,
  844. 'groups' => ['group_a', 'group_b'],
  845. 'servers' => ['127.0.0.1:' . $this->port],
  846. ]);
  847. $this->assertTrue(Cache::write('test_groups', 'value', 'memcached_groups'));
  848. $this->assertTrue(Cache::clearGroup('group_a', 'memcached_groups'));
  849. $this->assertNull(Cache::read('test_groups', 'memcached_groups'));
  850. $this->assertTrue(Cache::write('test_groups', 'value2', 'memcached_groups'));
  851. $this->assertTrue(Cache::clearGroup('group_b', 'memcached_groups'));
  852. $this->assertNull(Cache::read('test_groups', 'memcached_groups'));
  853. }
  854. /**
  855. * Test add
  856. *
  857. * @return void
  858. */
  859. public function testAdd()
  860. {
  861. Cache::delete('test_add_key', 'memcached');
  862. $result = Cache::add('test_add_key', 'test data', 'memcached');
  863. $this->assertTrue($result);
  864. $expected = 'test data';
  865. $result = Cache::read('test_add_key', 'memcached');
  866. $this->assertSame($expected, $result);
  867. $result = Cache::add('test_add_key', 'test data 2', 'memcached');
  868. $this->assertFalse($result);
  869. }
  870. }