ef4823bcfb45fd62bccf9a11495cacbed7bdb59e
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Functional / Cache / Backend / MemcachedBackendTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Functional\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 use TYPO3\CMS\Core\Cache\Exception;
19 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
20 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
21
22 /**
23 * Test case
24 */
25 class MemcachedBackendTest extends FunctionalTestCase
26 {
27
28 /**
29 * Sets up this test case
30 */
31 protected function setUp()
32 {
33 parent::setUp();
34 if (!extension_loaded('memcache') && !extension_loaded('memcached')) {
35 $this->markTestSkipped('Neither "memcache" nor "memcached" extension was available');
36 }
37 try {
38 if (!@fsockopen('localhost', 11211)) {
39 $this->markTestSkipped('memcached not reachable');
40 }
41 } catch (\Exception $e) {
42 $this->markTestSkipped('memcached not reachable');
43 }
44 }
45
46 /**
47 * @test
48 */
49 public function setThrowsExceptionIfNoFrontEndHasBeenSet()
50 {
51 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
52 $subject->initializeObject();
53
54 $this->expectException(Exception::class);
55 $this->expectExceptionCode(1207149215);
56
57 $subject->set($this->getUniqueId('MyIdentifier'), 'some data');
58 }
59
60 /**
61 * @test
62 */
63 public function initializeObjectThrowsExceptionIfNoMemcacheServerIsConfigured()
64 {
65 $subject = new MemcachedBackend('Testing');
66 $this->expectException(Exception::class);
67 $this->expectExceptionCode(1213115903);
68 $subject->initializeObject();
69 }
70
71 /**
72 * @test
73 */
74 public function itIsPossibleToSetAndCheckExistenceInCache()
75 {
76 $frontendProphecy = $this->prophesize(FrontendInterface::class);
77 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
78
79 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
80 $subject->initializeObject();
81 $subject->setCache($frontendProphecy->reveal());
82
83 $identifier = $this->getUniqueId('MyIdentifier');
84 $subject->set($identifier, 'Some data');
85 $this->assertTrue($subject->has($identifier));
86 }
87
88 /**
89 * @test
90 */
91 public function itIsPossibleToSetAndGetEntry()
92 {
93 $frontendProphecy = $this->prophesize(FrontendInterface::class);
94 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
95
96 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
97 $subject->initializeObject();
98 $subject->setCache($frontendProphecy->reveal());
99
100 $data = 'Some data';
101 $identifier = $this->getUniqueId('MyIdentifier');
102 $subject->set($identifier, $data);
103 $this->assertEquals($data, $subject->get($identifier));
104 }
105
106 /**
107 * @test
108 */
109 public function getReturnsPreviouslySetDataWithVariousTypes()
110 {
111 $frontendProphecy = $this->prophesize(FrontendInterface::class);
112 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
113
114 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
115 $subject->initializeObject();
116 $subject->setCache($frontendProphecy->reveal());
117
118 $data = [
119 'string' => 'Serialize a string',
120 'integer' => 0,
121 'anotherIntegerValue' => 123456,
122 'float' => 12.34,
123 'bool' => true,
124 'array' => [
125 0 => 'test',
126 1 => 'another test',
127 ],
128 ];
129
130 $subject->set('myIdentifier', $data);
131 $this->assertSame($data, $subject->get('myIdentifier'));
132 }
133
134 /**
135 * Check if we can store ~5 MB of data.
136 *
137 * @test
138 */
139 public function largeDataIsStored()
140 {
141 $frontendProphecy = $this->prophesize(FrontendInterface::class);
142 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
143
144 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
145 $subject->initializeObject();
146 $subject->setCache($frontendProphecy->reveal());
147
148 $data = str_repeat('abcde', 1024 * 1024);
149 $subject->set('tooLargeData', $data);
150 $this->assertTrue($subject->has('tooLargeData'));
151 $this->assertEquals($subject->get('tooLargeData'), $data);
152 }
153
154 /**
155 * @test
156 */
157 public function itIsPossibleToRemoveEntryFromCache()
158 {
159 $frontendProphecy = $this->prophesize(FrontendInterface::class);
160 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
161
162 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
163 $subject->initializeObject();
164 $subject->setCache($frontendProphecy->reveal());
165
166 $data = 'Some data';
167 $identifier = $this->getUniqueId('MyIdentifier');
168 $subject->set($identifier, $data);
169 $subject->remove($identifier);
170 $this->assertFalse($subject->has($identifier));
171 }
172
173 /**
174 * @test
175 */
176 public function itIsPossibleToOverwriteAnEntryInTheCache()
177 {
178 $frontendProphecy = $this->prophesize(FrontendInterface::class);
179 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
180
181 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
182 $subject->initializeObject();
183 $subject->setCache($frontendProphecy->reveal());
184
185 $data = 'Some data';
186 $identifier = $this->getUniqueId('MyIdentifier');
187 $subject->set($identifier, $data);
188 $otherData = 'some other data';
189 $subject->set($identifier, $otherData);
190 $this->assertEquals($otherData, $subject->get($identifier));
191 }
192
193 /**
194 * @test
195 */
196 public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag()
197 {
198 $frontendProphecy = $this->prophesize(FrontendInterface::class);
199 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
200
201 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
202 $subject->initializeObject();
203 $subject->setCache($frontendProphecy->reveal());
204
205 $data = 'Some data';
206 $identifier = $this->getUniqueId('MyIdentifier');
207 $subject->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tag2']);
208 $retrieved = $subject->findIdentifiersByTag('UnitTestTag%tag1');
209 $this->assertEquals($identifier, $retrieved[0]);
210 $retrieved = $subject->findIdentifiersByTag('UnitTestTag%tag2');
211 $this->assertEquals($identifier, $retrieved[0]);
212 }
213
214 /**
215 * @test
216 */
217 public function setRemovesTagsFromPreviousSet()
218 {
219 $frontendProphecy = $this->prophesize(FrontendInterface::class);
220 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
221
222 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
223 $subject->initializeObject();
224 $subject->setCache($frontendProphecy->reveal());
225
226 $data = 'Some data';
227 $identifier = $this->getUniqueId('MyIdentifier');
228 $subject->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tag2']);
229 $subject->set($identifier, $data, ['UnitTestTag%tag3']);
230 $this->assertEquals([], $subject->findIdentifiersByTag('UnitTestTag%tagX'));
231 }
232
233 /**
234 * @test
235 */
236 public function hasReturnsFalseIfTheEntryDoesntExist()
237 {
238 $frontendProphecy = $this->prophesize(FrontendInterface::class);
239 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
240
241 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
242 $subject->initializeObject();
243 $subject->setCache($frontendProphecy->reveal());
244
245 $identifier = $this->getUniqueId('NonExistingIdentifier');
246 $this->assertFalse($subject->has($identifier));
247 }
248
249 /**
250 * @test
251 */
252 public function removeReturnsFalseIfTheEntryDoesntExist()
253 {
254 $frontendProphecy = $this->prophesize(FrontendInterface::class);
255 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
256
257 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
258 $subject->initializeObject();
259 $subject->setCache($frontendProphecy->reveal());
260
261 $identifier = $this->getUniqueId('NonExistingIdentifier');
262 $this->assertFalse($subject->remove($identifier));
263 }
264
265 /**
266 * @test
267 */
268 public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
269 {
270 $frontendProphecy = $this->prophesize(FrontendInterface::class);
271 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
272
273 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
274 $subject->initializeObject();
275 $subject->setCache($frontendProphecy->reveal());
276
277 $data = 'some data' . microtime();
278 $subject->set('BackendMemcacheTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
279 $subject->set('BackendMemcacheTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
280 $subject->set('BackendMemcacheTest3', $data, ['UnitTestTag%test']);
281 $subject->flushByTag('UnitTestTag%special');
282 $this->assertTrue($subject->has('BackendMemcacheTest1'));
283 $this->assertFalse($subject->has('BackendMemcacheTest2'));
284 $this->assertTrue($subject->has('BackendMemcacheTest3'));
285 }
286
287 /**
288 * @test
289 */
290 public function flushByTagsRemovesCacheEntriesWithSpecifiedTags()
291 {
292 $frontendProphecy = $this->prophesize(FrontendInterface::class);
293 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
294
295 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
296 $subject->initializeObject();
297 $subject->setCache($frontendProphecy->reveal());
298
299 $data = 'some data' . microtime();
300 $subject->set('BackendMemcacheTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
301 $subject->set('BackendMemcacheTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
302 $subject->set('BackendMemcacheTest3', $data, ['UnitTestTag%test']);
303 $subject->flushByTags(['UnitTestTag%special', 'UnitTestTag%boring']);
304 $this->assertFalse($subject->has('BackendMemcacheTest1'));
305 $this->assertFalse($subject->has('BackendMemcacheTest2'));
306 $this->assertTrue($subject->has('BackendMemcacheTest3'));
307 }
308
309 /**
310 * @test
311 */
312 public function flushRemovesAllCacheEntries()
313 {
314 $frontendProphecy = $this->prophesize(FrontendInterface::class);
315 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
316
317 $subject = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
318 $subject->initializeObject();
319 $subject->setCache($frontendProphecy->reveal());
320
321 $data = 'some data' . microtime();
322 $subject->set('BackendMemcacheTest1', $data);
323 $subject->set('BackendMemcacheTest2', $data);
324 $subject->set('BackendMemcacheTest3', $data);
325 $subject->flush();
326 $this->assertFalse($subject->has('BackendMemcacheTest1'));
327 $this->assertFalse($subject->has('BackendMemcacheTest2'));
328 $this->assertFalse($subject->has('BackendMemcacheTest3'));
329 }
330
331 /**
332 * @test
333 */
334 public function flushRemovesOnlyOwnEntries()
335 {
336 $thisFrontendProphecy = $this->prophesize(FrontendInterface::class);
337 $thisFrontendProphecy->getIdentifier()->willReturn('thisCache');
338 $thisBackend = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
339 $thisBackend->initializeObject();
340 $thisBackend->setCache($thisFrontendProphecy->reveal());
341
342 $thatFrontendProphecy = $this->prophesize(FrontendInterface::class);
343 $thatFrontendProphecy->getIdentifier()->willReturn('thatCache');
344 $thatBackend = new MemcachedBackend('Testing', [ 'servers' => ['localhost:11211'] ]);
345 $thatBackend->initializeObject();
346 $thatBackend->setCache($thatFrontendProphecy->reveal());
347
348 $thisBackend->set('thisEntry', 'Hello');
349 $thatBackend->set('thatEntry', 'World!');
350 $thatBackend->flush();
351
352 $this->assertEquals('Hello', $thisBackend->get('thisEntry'));
353 $this->assertFalse($thatBackend->has('thatEntry'));
354 }
355 }