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