MemcachedEngineTest.php 29 KB

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