[BUGFIX] Add missing namespace parts
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Cache / Backend / ApcuBackendTest.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\ApcuBackend;
18 use TYPO3\CMS\Core\Cache\Exception;
19 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\Components\TestingFramework\Core\AccessibleObjectInterface;
22
23 /**
24 * Test case for the APCu cache backend.
25 *
26 * NOTE: If you want to execute these tests you need to enable apc in
27 * cli context (apc.enable_cli = 1) and disable slam defense (apc.slam_defense = 0)
28 */
29 class ApcuBackendTest extends \TYPO3\Components\TestingFramework\Core\Unit\UnitTestCase
30 {
31 /**
32 * Set up
33 *
34 * @return void
35 */
36 protected function setUp()
37 {
38 // APCu module is called apcu, but options are prefixed with apc
39 if (!extension_loaded('apcu') || !(bool)ini_get('apc.enabled') || !(bool)ini_get('apc.enable_cli')) {
40 $this->markTestSkipped('APCu extension was not available, or it was disabled for CLI.');
41 }
42 if ((bool)ini_get('apc.slam_defense')) {
43 $this->markTestSkipped('This testcase can only be executed with apc.slam_defense = 0');
44 }
45 }
46
47 /**
48 * @test
49 */
50 public function setThrowsExceptionIfNoFrontEndHasBeenSet()
51 {
52 $backend = new ApcuBackend('Testing');
53 $data = 'Some data';
54 $identifier = $this->getUniqueId('MyIdentifier');
55 $this->expectException(Exception::class);
56 $this->expectExceptionCode(1232986118);
57 $backend->set($identifier, $data);
58 }
59
60 /**
61 * @test
62 */
63 public function itIsPossibleToSetAndCheckExistenceInCache()
64 {
65 $backend = $this->setUpBackend();
66 $data = 'Some data';
67 $identifier = $this->getUniqueId('MyIdentifier');
68 $backend->set($identifier, $data);
69 $this->assertTrue($backend->has($identifier));
70 }
71
72 /**
73 * @test
74 */
75 public function itIsPossibleToSetAndGetEntry()
76 {
77 $backend = $this->setUpBackend();
78 $data = 'Some data';
79 $identifier = $this->getUniqueId('MyIdentifier');
80 $backend->set($identifier, $data);
81 $fetchedData = $backend->get($identifier);
82 $this->assertEquals($data, $fetchedData);
83 }
84
85 /**
86 * @test
87 */
88 public function itIsPossibleToRemoveEntryFromCache()
89 {
90 $backend = $this->setUpBackend();
91 $data = 'Some data';
92 $identifier = $this->getUniqueId('MyIdentifier');
93 $backend->set($identifier, $data);
94 $backend->remove($identifier);
95 $this->assertFalse($backend->has($identifier));
96 }
97
98 /**
99 * @test
100 */
101 public function itIsPossibleToOverwriteAnEntryInTheCache()
102 {
103 $backend = $this->setUpBackend();
104 $data = 'Some data';
105 $identifier = $this->getUniqueId('MyIdentifier');
106 $backend->set($identifier, $data);
107 $otherData = 'some other data';
108 $backend->set($identifier, $otherData);
109 $fetchedData = $backend->get($identifier);
110 $this->assertEquals($otherData, $fetchedData);
111 }
112
113 /**
114 * @test
115 */
116 public function findIdentifiersByTagFindsSetEntries()
117 {
118 $backend = $this->setUpBackend();
119 $data = 'Some data';
120 $identifier = $this->getUniqueId('MyIdentifier');
121 $backend->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tag2']);
122 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag1');
123 $this->assertEquals($identifier, $retrieved[0]);
124 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
125 $this->assertEquals($identifier, $retrieved[0]);
126 }
127
128 /**
129 * @test
130 */
131 public function setRemovesTagsFromPreviousSet()
132 {
133 $backend = $this->setUpBackend();
134 $data = 'Some data';
135 $identifier = $this->getUniqueId('MyIdentifier');
136 $backend->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tagX']);
137 $backend->set($identifier, $data, ['UnitTestTag%tag3']);
138 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tagX');
139 $this->assertEquals([], $retrieved);
140 }
141
142 /**
143 * @test
144 */
145 public function setCacheIsSettingIdentifierPrefixWithCacheIdentifier()
146 {
147 /** @var \PHPUnit_Framework_MockObject_MockObject|FrontendInterface $cacheMock */
148 $cacheMock = $this->createMock(FrontendInterface::class);
149 $cacheMock->expects($this->any())->method('getIdentifier')->will($this->returnValue(
150 'testidentifier'
151 ));
152
153 /** @var $backendMock \PHPUnit_Framework_MockObject_MockObject|ApcuBackend */
154 $backendMock = $this->getMockBuilder(ApcuBackend::class)
155 ->setMethods(['setIdentifierPrefix', 'getCurrentUserData', 'getPathSite'])
156 ->setConstructorArgs(['testcontext'])
157 ->getMock();
158
159 $backendMock->expects($this->once())->method('getCurrentUserData')->will(
160 $this->returnValue(['name' => 'testname'])
161 );
162
163 $backendMock->expects($this->once())->method('getPathSite')->will(
164 $this->returnValue('testpath')
165 );
166
167 $expectedIdentifier = 'TYPO3_' . GeneralUtility::shortMD5('testpath' . 'testname' . 'testcontext' . 'testidentifier', 12);
168 $backendMock->expects($this->once())->method('setIdentifierPrefix')->with($expectedIdentifier);
169 $backendMock->setCache($cacheMock);
170 }
171
172 /**
173 * @test
174 */
175 public function hasReturnsFalseIfTheEntryDoesNotExist()
176 {
177 $backend = $this->setUpBackend();
178 $identifier = $this->getUniqueId('NonExistingIdentifier');
179 $this->assertFalse($backend->has($identifier));
180 }
181
182 /**
183 * @test
184 */
185 public function removeReturnsFalseIfTheEntryDoesntExist()
186 {
187 $backend = $this->setUpBackend();
188 $identifier = $this->getUniqueId('NonExistingIdentifier');
189 $this->assertFalse($backend->remove($identifier));
190 }
191
192 /**
193 * @test
194 */
195 public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
196 {
197 $backend = $this->setUpBackend();
198 $data = 'some data' . microtime();
199 $backend->set('BackendAPCUTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
200 $backend->set('BackendAPCUTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
201 $backend->set('BackendAPCUTest3', $data, ['UnitTestTag%test']);
202 $backend->flushByTag('UnitTestTag%special');
203 $this->assertTrue($backend->has('BackendAPCUTest1'));
204 $this->assertFalse($backend->has('BackendAPCUTest2'));
205 $this->assertTrue($backend->has('BackendAPCUTest3'));
206 }
207
208 /**
209 * @test
210 */
211 public function flushByTagsRemovesCacheEntriesWithSpecifiedTags()
212 {
213 $backend = $this->setUpBackend();
214 $data = 'some data' . microtime();
215 $backend->set('BackendAPCUTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
216 $backend->set('BackendAPCUTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
217 $backend->set('BackendAPCUTest3', $data, ['UnitTestTag%test']);
218 $backend->flushByTags(['UnitTestTag%special', 'UnitTestTag%boring']);
219 $this->assertFalse($backend->has('BackendAPCUTest1'), 'BackendAPCTest1');
220 $this->assertFalse($backend->has('BackendAPCUTest2'), 'BackendAPCTest2');
221 $this->assertTrue($backend->has('BackendAPCUTest3'), 'BackendAPCTest3');
222 }
223
224 /**
225 * @test
226 */
227 public function flushRemovesAllCacheEntries()
228 {
229 $backend = $this->setUpBackend();
230 $data = 'some data' . microtime();
231 $backend->set('BackendAPCUTest1', $data);
232 $backend->set('BackendAPCUTest2', $data);
233 $backend->set('BackendAPCUTest3', $data);
234 $backend->flush();
235 $this->assertFalse($backend->has('BackendAPCUTest1'));
236 $this->assertFalse($backend->has('BackendAPCUTest2'));
237 $this->assertFalse($backend->has('BackendAPCUTest3'));
238 }
239
240 /**
241 * @test
242 */
243 public function flushRemovesOnlyOwnEntries()
244 {
245 /** @var \PHPUnit_Framework_MockObject_MockObject|FrontendInterface $thisCache */
246 $thisCache = $this->createMock(FrontendInterface::class);
247 $thisCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thisCache'));
248 $thisBackend = new ApcuBackend('Testing');
249 $thisBackend->setCache($thisCache);
250
251 /** @var \PHPUnit_Framework_MockObject_MockObject|FrontendInterface $thatCache */
252 $thatCache = $this->createMock(FrontendInterface::class);
253 $thatCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thatCache'));
254 $thatBackend = new ApcuBackend('Testing');
255 $thatBackend->setCache($thatCache);
256 $thisBackend->set('thisEntry', 'Hello');
257 $thatBackend->set('thatEntry', 'World!');
258 $thatBackend->flush();
259 $this->assertEquals('Hello', $thisBackend->get('thisEntry'));
260 $this->assertFalse($thatBackend->has('thatEntry'));
261 }
262
263 /**
264 * Check if we can store ~5 MB of data
265 *
266 * @test
267 */
268 public function largeDataIsStored()
269 {
270 $backend = $this->setUpBackend();
271 $data = str_repeat('abcde', 1024 * 1024);
272 $identifier = $this->getUniqueId('tooLargeData');
273 $backend->set($identifier, $data);
274 $this->assertTrue($backend->has($identifier));
275 $this->assertEquals($backend->get($identifier), $data);
276 }
277
278 /**
279 * @test
280 */
281 public function setTagsOnlyOnceToIdentifier()
282 {
283 $identifier = $this->getUniqueId('MyIdentifier');
284 $tags = ['UnitTestTag%test', 'UnitTestTag%boring'];
285
286 $backend = $this->setUpBackend(true);
287 $backend->_call('addIdentifierToTags', $identifier, $tags);
288 $this->assertSame(
289 $tags,
290 $backend->_call('findTagsByIdentifier', $identifier)
291 );
292
293 $backend->_call('addIdentifierToTags', $identifier, $tags);
294 $this->assertSame(
295 $tags,
296 $backend->_call('findTagsByIdentifier', $identifier)
297 );
298 }
299
300 /**
301 * Sets up the APCu backend used for testing
302 *
303 * @param bool $accessible TRUE if backend should be encapsulated in accessible proxy otherwise FALSE.
304 * @return AccessibleObjectInterface|ApcuBackend
305 */
306 protected function setUpBackend($accessible = false)
307 {
308 /** @var \PHPUnit_Framework_MockObject_MockObject|FrontendInterface $cache */
309 $cache = $this->createMock(FrontendInterface::class);
310 if ($accessible) {
311 $accessibleClassName = $this->buildAccessibleProxy(ApcuBackend::class);
312 $backend = new $accessibleClassName('Testing');
313 } else {
314 $backend = new ApcuBackend('Testing');
315 }
316 $backend->setCache($cache);
317 return $backend;
318 }
319 }