[TASK] Run tests on new bamboo infrastructure
[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 * Sets up this test case
29 */
30 protected function setUp()
31 {
32 parent::setUp();
33 if (!extension_loaded('memcache') && !extension_loaded('memcached')) {
34 $this->markTestSkipped('Neither "memcache" nor "memcached" extension was available');
35 }
36 if (!getenv('typo3TestingMemcachedHost')) {
37 $this->markTestSkipped('environment variable "typo3TestingMemcachedHost" must be set to run this test');
38 }
39 // Note we assume that if that typo3TestingMemcachedHost env is set, we can use that for testing,
40 // there is no test to see if the daemon is actually up and running. Tests will fail if env
41 // is set but daemon is down.
42 }
43
44 /**
45 * Initialize MemcacheBackend ($subject)
46 */
47 protected function initializeSubject(): MemcachedBackend
48 {
49 // We know this env is set, otherwise setUp() would skip the tests
50 $memcachedHost = getenv('typo3TestingMemcachedHost');
51 // If typo3TestingMemcachedPort env is set, use it, otherwise fall back to standard port
52 $env = getenv('typo3TestingMemcachedPort');
53 $memcachedPort = is_string($env) ? (int)$env : 11211;
54
55 $subject = new MemcachedBackend('Testing', [ 'servers' => [$memcachedHost . ':' . $memcachedPort] ]);
56 $subject->initializeObject();
57 return $subject;
58 }
59
60 /**
61 * @test
62 */
63 public function setThrowsExceptionIfNoFrontEndHasBeenSet()
64 {
65 $subject = $this->initializeSubject();
66
67 $this->expectException(Exception::class);
68 $this->expectExceptionCode(1207149215);
69
70 $subject->set($this->getUniqueId('MyIdentifier'), 'some data');
71 }
72
73 /**
74 * @test
75 */
76 public function initializeObjectThrowsExceptionIfNoMemcacheServerIsConfigured()
77 {
78 $subject = new MemcachedBackend('Testing');
79 $this->expectException(Exception::class);
80 $this->expectExceptionCode(1213115903);
81 $subject->initializeObject();
82 }
83
84 /**
85 * @test
86 */
87 public function itIsPossibleToSetAndCheckExistenceInCache()
88 {
89 $frontendProphecy = $this->prophesize(FrontendInterface::class);
90 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
91
92 $subject = $this->initializeSubject();
93 $subject->setCache($frontendProphecy->reveal());
94
95 $identifier = $this->getUniqueId('MyIdentifier');
96 $subject->set($identifier, 'Some data');
97 $this->assertTrue($subject->has($identifier));
98 }
99
100 /**
101 * @test
102 */
103 public function itIsPossibleToSetAndGetEntry()
104 {
105 $frontendProphecy = $this->prophesize(FrontendInterface::class);
106 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
107
108 $subject = $this->initializeSubject();
109 $subject->setCache($frontendProphecy->reveal());
110
111 $data = 'Some data';
112 $identifier = $this->getUniqueId('MyIdentifier');
113 $subject->set($identifier, $data);
114 $this->assertEquals($data, $subject->get($identifier));
115 }
116
117 /**
118 * @test
119 */
120 public function getReturnsPreviouslySetDataWithVariousTypes()
121 {
122 $frontendProphecy = $this->prophesize(FrontendInterface::class);
123 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
124
125 $subject = $this->initializeSubject();
126 $subject->setCache($frontendProphecy->reveal());
127
128 $data = [
129 'string' => 'Serialize a string',
130 'integer' => 0,
131 'anotherIntegerValue' => 123456,
132 'float' => 12.34,
133 'bool' => true,
134 'array' => [
135 0 => 'test',
136 1 => 'another test',
137 ],
138 ];
139
140 $subject->set('myIdentifier', $data);
141 $this->assertSame($data, $subject->get('myIdentifier'));
142 }
143
144 /**
145 * Check if we can store ~5 MB of data.
146 *
147 * @test
148 */
149 public function largeDataIsStored()
150 {
151 $frontendProphecy = $this->prophesize(FrontendInterface::class);
152 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
153
154 $subject = $this->initializeSubject();
155 $subject->setCache($frontendProphecy->reveal());
156
157 $data = str_repeat('abcde', 1024 * 1024);
158 $subject->set('tooLargeData', $data);
159 $this->assertTrue($subject->has('tooLargeData'));
160 $this->assertEquals($subject->get('tooLargeData'), $data);
161 }
162
163 /**
164 * @test
165 */
166 public function itIsPossibleToRemoveEntryFromCache()
167 {
168 $frontendProphecy = $this->prophesize(FrontendInterface::class);
169 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
170
171 $subject = $this->initializeSubject();
172 $subject->setCache($frontendProphecy->reveal());
173
174 $data = 'Some data';
175 $identifier = $this->getUniqueId('MyIdentifier');
176 $subject->set($identifier, $data);
177 $subject->remove($identifier);
178 $this->assertFalse($subject->has($identifier));
179 }
180
181 /**
182 * @test
183 */
184 public function itIsPossibleToOverwriteAnEntryInTheCache()
185 {
186 $frontendProphecy = $this->prophesize(FrontendInterface::class);
187 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
188
189 $subject = $this->initializeSubject();
190 $subject->setCache($frontendProphecy->reveal());
191
192 $data = 'Some data';
193 $identifier = $this->getUniqueId('MyIdentifier');
194 $subject->set($identifier, $data);
195 $otherData = 'some other data';
196 $subject->set($identifier, $otherData);
197 $this->assertEquals($otherData, $subject->get($identifier));
198 }
199
200 /**
201 * @test
202 */
203 public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag()
204 {
205 $frontendProphecy = $this->prophesize(FrontendInterface::class);
206 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
207
208 $subject = $this->initializeSubject();
209 $subject->setCache($frontendProphecy->reveal());
210
211 $data = 'Some data';
212 $identifier = $this->getUniqueId('MyIdentifier');
213 $subject->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tag2']);
214 $retrieved = $subject->findIdentifiersByTag('UnitTestTag%tag1');
215 $this->assertEquals($identifier, $retrieved[0]);
216 $retrieved = $subject->findIdentifiersByTag('UnitTestTag%tag2');
217 $this->assertEquals($identifier, $retrieved[0]);
218 }
219
220 /**
221 * @test
222 */
223 public function setRemovesTagsFromPreviousSet()
224 {
225 $frontendProphecy = $this->prophesize(FrontendInterface::class);
226 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
227
228 $subject = $this->initializeSubject();
229 $subject->setCache($frontendProphecy->reveal());
230
231 $data = 'Some data';
232 $identifier = $this->getUniqueId('MyIdentifier');
233 $subject->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tag2']);
234 $subject->set($identifier, $data, ['UnitTestTag%tag3']);
235 $this->assertEquals([], $subject->findIdentifiersByTag('UnitTestTag%tagX'));
236 }
237
238 /**
239 * @test
240 */
241 public function hasReturnsFalseIfTheEntryDoesntExist()
242 {
243 $frontendProphecy = $this->prophesize(FrontendInterface::class);
244 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
245
246 $subject = $this->initializeSubject();
247 $subject->setCache($frontendProphecy->reveal());
248
249 $identifier = $this->getUniqueId('NonExistingIdentifier');
250 $this->assertFalse($subject->has($identifier));
251 }
252
253 /**
254 * @test
255 */
256 public function removeReturnsFalseIfTheEntryDoesntExist()
257 {
258 $frontendProphecy = $this->prophesize(FrontendInterface::class);
259 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
260
261 $subject = $this->initializeSubject();
262 $subject->setCache($frontendProphecy->reveal());
263
264 $identifier = $this->getUniqueId('NonExistingIdentifier');
265 $this->assertFalse($subject->remove($identifier));
266 }
267
268 /**
269 * @test
270 */
271 public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
272 {
273 $frontendProphecy = $this->prophesize(FrontendInterface::class);
274 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
275
276 $subject = $this->initializeSubject();
277 $subject->setCache($frontendProphecy->reveal());
278
279 $data = 'some data' . microtime();
280 $subject->set('BackendMemcacheTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
281 $subject->set('BackendMemcacheTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
282 $subject->set('BackendMemcacheTest3', $data, ['UnitTestTag%test']);
283 $subject->flushByTag('UnitTestTag%special');
284 $this->assertTrue($subject->has('BackendMemcacheTest1'));
285 $this->assertFalse($subject->has('BackendMemcacheTest2'));
286 $this->assertTrue($subject->has('BackendMemcacheTest3'));
287 }
288
289 /**
290 * @test
291 */
292 public function flushByTagsRemovesCacheEntriesWithSpecifiedTags()
293 {
294 $frontendProphecy = $this->prophesize(FrontendInterface::class);
295 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
296
297 $subject = $this->initializeSubject();
298 $subject->setCache($frontendProphecy->reveal());
299
300 $data = 'some data' . microtime();
301 $subject->set('BackendMemcacheTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
302 $subject->set('BackendMemcacheTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
303 $subject->set('BackendMemcacheTest3', $data, ['UnitTestTag%test']);
304 $subject->flushByTags(['UnitTestTag%special', 'UnitTestTag%boring']);
305 $this->assertFalse($subject->has('BackendMemcacheTest1'));
306 $this->assertFalse($subject->has('BackendMemcacheTest2'));
307 $this->assertTrue($subject->has('BackendMemcacheTest3'));
308 }
309
310 /**
311 * @test
312 */
313 public function flushRemovesAllCacheEntries()
314 {
315 $frontendProphecy = $this->prophesize(FrontendInterface::class);
316 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
317
318 $subject = $this->initializeSubject();
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 = $this->initializeSubject();
339 $thisBackend->setCache($thisFrontendProphecy->reveal());
340
341 $thatFrontendProphecy = $this->prophesize(FrontendInterface::class);
342 $thatFrontendProphecy->getIdentifier()->willReturn('thatCache');
343 $thatBackend = $this->initializeSubject();
344 $thatBackend->setCache($thatFrontendProphecy->reveal());
345
346 $thisBackend->set('thisEntry', 'Hello');
347 $thatBackend->set('thatEntry', 'World!');
348 $thatBackend->flush();
349
350 $this->assertEquals('Hello', $thisBackend->get('thisEntry'));
351 $this->assertFalse($thatBackend->has('thatEntry'));
352 }
353 }