[FOLLOWUP][TASK] Doctrine: migrate $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Cache / Backend / MemcachedBackendTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Cache\Backend;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Cache\Backend\MemcachedBackend;
18
19 /**
20 * Testcase for the cache to memcached backend
21 *
22 * This file is a backport from FLOW3
23 */
24 class MemcachedBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
25 {
26 /**
27 * Sets up this testcase
28 *
29 * @return void
30 */
31 protected function setUp()
32 {
33 if (!extension_loaded('memcache') && !extension_loaded('memcached')) {
34 $this->markTestSkipped('Neither "memcache" nor "memcached" extension was available');
35 }
36 try {
37 if (!@fsockopen('localhost', 11211)) {
38 $this->markTestSkipped('memcached not reachable');
39 }
40 } catch (\Exception $e) {
41 $this->markTestSkipped('memcached not reachable');
42 }
43 }
44
45 /**
46 * @test
47 * @expectedException \TYPO3\CMS\Core\Cache\Exception
48 */
49 public function setThrowsExceptionIfNoFrontEndHasBeenSet()
50 {
51 $backendOptions = array('servers' => array('localhost:11211'));
52 $backend = new MemcachedBackend('Testing', $backendOptions);
53 $backend->initializeObject();
54 $data = 'Some data';
55 $identifier = $this->getUniqueId('MyIdentifier');
56 $backend->set($identifier, $data);
57 }
58
59 /**
60 * @test
61 * @expectedException \TYPO3\CMS\Core\Cache\Exception
62 */
63 public function initializeObjectThrowsExceptionIfNoMemcacheServerIsConfigured()
64 {
65 $backend = new MemcachedBackend('Testing');
66 $backend->initializeObject();
67 }
68
69 /**
70 * @test
71 */
72 public function itIsPossibleToSetAndCheckExistenceInCache()
73 {
74 $backend = $this->setUpBackend();
75 $data = 'Some data';
76 $identifier = $this->getUniqueId('MyIdentifier');
77 $backend->set($identifier, $data);
78 $inCache = $backend->has($identifier);
79 $this->assertTrue($inCache, 'Memcache failed to set and check entry');
80 }
81
82 /**
83 * @test
84 */
85 public function itIsPossibleToSetAndGetEntry()
86 {
87 $backend = $this->setUpBackend();
88 $data = 'Some data';
89 $identifier = $this->getUniqueId('MyIdentifier');
90 $backend->set($identifier, $data);
91 $fetchedData = $backend->get($identifier);
92 $this->assertEquals($data, $fetchedData, 'Memcache failed to set and retrieve data');
93 }
94
95 /**
96 * @test
97 */
98 public function itIsPossibleToRemoveEntryFromCache()
99 {
100 $backend = $this->setUpBackend();
101 $data = 'Some data';
102 $identifier = $this->getUniqueId('MyIdentifier');
103 $backend->set($identifier, $data);
104 $backend->remove($identifier);
105 $inCache = $backend->has($identifier);
106 $this->assertFalse($inCache, 'Failed to set and remove data from Memcache');
107 }
108
109 /**
110 * @test
111 */
112 public function itIsPossibleToOverwriteAnEntryInTheCache()
113 {
114 $backend = $this->setUpBackend();
115 $data = 'Some data';
116 $identifier = $this->getUniqueId('MyIdentifier');
117 $backend->set($identifier, $data);
118 $otherData = 'some other data';
119 $backend->set($identifier, $otherData);
120 $fetchedData = $backend->get($identifier);
121 $this->assertEquals($otherData, $fetchedData, 'Memcache failed to overwrite and retrieve data');
122 }
123
124 /**
125 * @test
126 */
127 public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag()
128 {
129 $backend = $this->setUpBackend();
130 $data = 'Some data';
131 $identifier = $this->getUniqueId('MyIdentifier');
132 $backend->set($identifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
133 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag1');
134 $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
135 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
136 $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
137 }
138
139 /**
140 * @test
141 */
142 public function setRemovesTagsFromPreviousSet()
143 {
144 $backend = $this->setUpBackend();
145 $data = 'Some data';
146 $identifier = $this->getUniqueId('MyIdentifier');
147 $backend->set($identifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
148 $backend->set($identifier, $data, array('UnitTestTag%tag3'));
149 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tagX');
150 $this->assertEquals(array(), $retrieved, 'Found entry which should no longer exist.');
151 }
152
153 /**
154 * @test
155 */
156 public function hasReturnsFalseIfTheEntryDoesntExist()
157 {
158 $backend = $this->setUpBackend();
159 $identifier = $this->getUniqueId('NonExistingIdentifier');
160 $inCache = $backend->has($identifier);
161 $this->assertFalse($inCache, '"has" did not return FALSE when checking on non existing identifier');
162 }
163
164 /**
165 * @test
166 */
167 public function removeReturnsFalseIfTheEntryDoesntExist()
168 {
169 $backend = $this->setUpBackend();
170 $identifier = $this->getUniqueId('NonExistingIdentifier');
171 $inCache = $backend->remove($identifier);
172 $this->assertFalse($inCache, '"remove" did not return FALSE when checking on non existing identifier');
173 }
174
175 /**
176 * @test
177 */
178 public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
179 {
180 $backend = $this->setUpBackend();
181 $data = 'some data' . microtime();
182 $backend->set('BackendMemcacheTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
183 $backend->set('BackendMemcacheTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
184 $backend->set('BackendMemcacheTest3', $data, array('UnitTestTag%test'));
185 $backend->flushByTag('UnitTestTag%special');
186 $this->assertTrue($backend->has('BackendMemcacheTest1'), 'BackendMemcacheTest1');
187 $this->assertFalse($backend->has('BackendMemcacheTest2'), 'BackendMemcacheTest2');
188 $this->assertTrue($backend->has('BackendMemcacheTest3'), 'BackendMemcacheTest3');
189 }
190
191 /**
192 * @test
193 */
194 public function flushRemovesAllCacheEntries()
195 {
196 $backend = $this->setUpBackend();
197 $data = 'some data' . microtime();
198 $backend->set('BackendMemcacheTest1', $data);
199 $backend->set('BackendMemcacheTest2', $data);
200 $backend->set('BackendMemcacheTest3', $data);
201 $backend->flush();
202 $this->assertFalse($backend->has('BackendMemcacheTest1'), 'BackendMemcacheTest1');
203 $this->assertFalse($backend->has('BackendMemcacheTest2'), 'BackendMemcacheTest2');
204 $this->assertFalse($backend->has('BackendMemcacheTest3'), 'BackendMemcacheTest3');
205 }
206
207 /**
208 * @test
209 */
210 public function flushRemovesOnlyOwnEntries()
211 {
212 $backendOptions = array('servers' => array('localhost:11211'));
213 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $thisCache */
214 $thisCache = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class, array(), array(), '', false);
215 $thisCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thisCache'));
216 $thisBackend = new MemcachedBackend('Testing', $backendOptions);
217 $thisBackend->setCache($thisCache);
218 $thisBackend->initializeObject();
219
220 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $thatCache */
221 $thatCache = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class, array(), array(), '', false);
222 $thatCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thatCache'));
223 $thatBackend = new MemcachedBackend('Testing', $backendOptions);
224 $thatBackend->setCache($thatCache);
225 $thatBackend->initializeObject();
226 $thisBackend->set('thisEntry', 'Hello');
227 $thatBackend->set('thatEntry', 'World!');
228 $thatBackend->flush();
229 $this->assertEquals('Hello', $thisBackend->get('thisEntry'));
230 $this->assertFalse($thatBackend->has('thatEntry'));
231 }
232
233 /**
234 * Check if we can store ~5 MB of data, this gives some headroom for the
235 * reflection data.
236 *
237 * @test
238 */
239 public function largeDataIsStored()
240 {
241 $backend = $this->setUpBackend();
242 $data = str_repeat('abcde', 1024 * 1024);
243 $backend->set('tooLargeData', $data);
244 $this->assertTrue($backend->has('tooLargeData'));
245 $this->assertEquals($backend->get('tooLargeData'), $data);
246 }
247
248 /**
249 * @test
250 */
251 public function setTagsOnlyOnceToIdentifier()
252 {
253 $backendOptions = array('servers' => array('localhost:11211'));
254 $identifier = $this->getUniqueId('MyIdentifier');
255 $tags = array('UnitTestTag%test', 'UnitTestTag%boring');
256
257 $backend = $this->setUpBackend($backendOptions, true);
258 $backend->_call('addIdentifierToTags', $identifier, $tags);
259 $this->assertSame(
260 $tags,
261 $backend->_call('findTagsByIdentifier', $identifier)
262 );
263
264 $backend->_call('addIdentifierToTags', $identifier, $tags);
265 $this->assertSame(
266 $tags,
267 $backend->_call('findTagsByIdentifier', $identifier)
268 );
269 }
270
271 /**
272 * Sets up the memcached backend used for testing
273 *
274 * @param array $backendOptions Options for the memcache backend
275 * @param bool $accessible TRUE if backend should be encapsulated in accessible proxy otherwise FALSE.
276 * @return \TYPO3\CMS\Core\Tests\AccessibleObjectInterface|MemcachedBackend
277 */
278 protected function setUpBackend(array $backendOptions = array(), $accessible = false)
279 {
280 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $cache */
281 $cache = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface::class, array(), array(), '', false);
282 if ($backendOptions == array()) {
283 $backendOptions = array('servers' => array('localhost:11211'));
284 }
285 if ($accessible) {
286 $accessibleClassName = $this->buildAccessibleProxy(MemcachedBackend::class);
287 $backend = new $accessibleClassName('Testing', $backendOptions);
288 } else {
289 $backend = new MemcachedBackend('Testing', $backendOptions);
290 }
291 $backend->setCache($cache);
292 $backend->initializeObject();
293 return $backend;
294 }
295 }