[FOLLOWUP][TASK] Doctrine: migrate $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Cache / Backend / ApcBackendTest.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\ApcBackend;
18
19 /**
20 * Testcase for the APC cache backend.
21 *
22 * NOTE: If you want to execute these tests you need to enable apc in
23 * cli context (apc.enable_cli = 1)
24 *
25 * This file is a backport from FLOW3
26 */
27 class ApcBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
28 {
29 /**
30 * Sets up this testcase
31 *
32 * @return void
33 */
34 protected function setUp()
35 {
36 // Currently APCu identifies itself both as "apcu" and "apc" (for compatibility) although it doesn't provide the APC-opcache functionality
37 if (!extension_loaded('apc') || ini_get('apc.enabled') == 0 || ini_get('apc.enable_cli') == 0) {
38 $this->markTestSkipped('APC/APCu extension was not available, or it was disabled for CLI.');
39 }
40 if (ini_get('apc.slam_defense') == 1) {
41 $this->markTestSkipped('This testcase can only be executed with apc.slam_defense = Off');
42 }
43 }
44
45 /**
46 * @test
47 * @expectedException \TYPO3\CMS\Core\Cache\Exception
48 */
49 public function setThrowsExceptionIfNoFrontEndHasBeenSet()
50 {
51 $backend = new ApcBackend('Testing');
52 $data = 'Some data';
53 $identifier = $this->getUniqueId('MyIdentifier');
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 $inCache = $backend->has($identifier);
67 $this->assertTrue($inCache, 'APC backend failed to set and check entry');
68 }
69
70 /**
71 * @test
72 */
73 public function itIsPossibleToSetAndGetEntry()
74 {
75 $backend = $this->setUpBackend();
76 $data = 'Some data';
77 $identifier = $this->getUniqueId('MyIdentifier');
78 $backend->set($identifier, $data);
79 $fetchedData = $backend->get($identifier);
80 $this->assertEquals($data, $fetchedData, 'APC backend failed to set and retrieve data');
81 }
82
83 /**
84 * @test
85 */
86 public function itIsPossibleToRemoveEntryFromCache()
87 {
88 $backend = $this->setUpBackend();
89 $data = 'Some data';
90 $identifier = $this->getUniqueId('MyIdentifier');
91 $backend->set($identifier, $data);
92 $backend->remove($identifier);
93 $inCache = $backend->has($identifier);
94 $this->assertFalse($inCache, 'Failed to set and remove data from APC backend');
95 }
96
97 /**
98 * @test
99 */
100 public function itIsPossibleToOverwriteAnEntryInTheCache()
101 {
102 $backend = $this->setUpBackend();
103 $data = 'Some data';
104 $identifier = $this->getUniqueId('MyIdentifier');
105 $backend->set($identifier, $data);
106 $otherData = 'some other data';
107 $backend->set($identifier, $otherData);
108 $fetchedData = $backend->get($identifier);
109 $this->assertEquals($otherData, $fetchedData, 'APC backend failed to overwrite and retrieve data');
110 }
111
112 /**
113 * @test
114 */
115 public function findIdentifiersByTagFindsSetEntries()
116 {
117 $backend = $this->setUpBackend();
118 $data = 'Some data';
119 $identifier = $this->getUniqueId('MyIdentifier');
120 $backend->set($identifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
121 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag1');
122 $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
123 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
124 $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
125 }
126
127 /**
128 * @test
129 */
130 public function setRemovesTagsFromPreviousSet()
131 {
132 $backend = $this->setUpBackend();
133 $data = 'Some data';
134 $identifier = $this->getUniqueId('MyIdentifier');
135 $backend->set($identifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tagX'));
136 $backend->set($identifier, $data, array('UnitTestTag%tag3'));
137 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tagX');
138 $this->assertEquals(array(), $retrieved, 'Found entry which should no longer exist.');
139 }
140
141 /**
142 * @test
143 */
144 public function setCacheIsSettingIdentifierPrefixWithCacheIdentifier()
145 {
146 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $cacheMock */
147 $cacheMock = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface::class, array(), array(), '', false);
148 $cacheMock->expects($this->any())->method('getIdentifier')->will($this->returnValue(
149 'testidentifier'
150 ));
151
152 /** @var $backendMock \PHPUnit_Framework_MockObject_MockObject|ApcBackend */
153 $backendMock = $this->getMock(
154 ApcBackend::class,
155 array('setIdentifierPrefix', 'getCurrentUserData', 'getPathSite'),
156 array('testcontext')
157 );
158
159 $backendMock->expects($this->once())->method('getCurrentUserData')->will(
160 $this->returnValue(array('name' => 'testname'))
161 );
162
163 $backendMock->expects($this->once())->method('getPathSite')->will(
164 $this->returnValue('testpath')
165 );
166
167 $expectedIdentifier = 'TYPO3_' . \TYPO3\CMS\Core\Utility\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 $inCache = $backend->has($identifier);
180 $this->assertFalse($inCache, '"has" did not return FALSE when checking on non existing identifier');
181 }
182
183 /**
184 * @test
185 */
186 public function removeReturnsFalseIfTheEntryDoesntExist()
187 {
188 $backend = $this->setUpBackend();
189 $identifier = $this->getUniqueId('NonExistingIdentifier');
190 $inCache = $backend->remove($identifier);
191 $this->assertFalse($inCache, '"remove" did not return FALSE when checking on non existing identifier');
192 }
193
194 /**
195 * @test
196 */
197 public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
198 {
199 $backend = $this->setUpBackend();
200 $data = 'some data' . microtime();
201 $backend->set('BackendAPCTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
202 $backend->set('BackendAPCTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
203 $backend->set('BackendAPCTest3', $data, array('UnitTestTag%test'));
204 $backend->flushByTag('UnitTestTag%special');
205 $this->assertTrue($backend->has('BackendAPCTest1'), 'BackendAPCTest1');
206 $this->assertFalse($backend->has('BackendAPCTest2'), 'BackendAPCTest2');
207 $this->assertTrue($backend->has('BackendAPCTest3'), 'BackendAPCTest3');
208 }
209
210 /**
211 * @test
212 */
213 public function flushRemovesAllCacheEntries()
214 {
215 $backend = $this->setUpBackend();
216 $data = 'some data' . microtime();
217 $backend->set('BackendAPCTest1', $data);
218 $backend->set('BackendAPCTest2', $data);
219 $backend->set('BackendAPCTest3', $data);
220 $backend->flush();
221 $this->assertFalse($backend->has('BackendAPCTest1'), 'BackendAPCTest1');
222 $this->assertFalse($backend->has('BackendAPCTest2'), 'BackendAPCTest2');
223 $this->assertFalse($backend->has('BackendAPCTest3'), 'BackendAPCTest3');
224 }
225
226 /**
227 * @test
228 */
229 public function flushRemovesOnlyOwnEntries()
230 {
231 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $thisCache */
232 $thisCache = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface::class, array(), array(), '', false);
233 $thisCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thisCache'));
234 $thisBackend = new ApcBackend('Testing');
235 $thisBackend->setCache($thisCache);
236
237 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $thatCache */
238 $thatCache = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface::class, array(), array(), '', false);
239 $thatCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thatCache'));
240 $thatBackend = new ApcBackend('Testing');
241 $thatBackend->setCache($thatCache);
242 $thisBackend->set('thisEntry', 'Hello');
243 $thatBackend->set('thatEntry', 'World!');
244 $thatBackend->flush();
245 $this->assertEquals('Hello', $thisBackend->get('thisEntry'));
246 $this->assertFalse($thatBackend->has('thatEntry'));
247 }
248
249 /**
250 * Check if we can store ~5 MB of data
251 *
252 * @test
253 */
254 public function largeDataIsStored()
255 {
256 $backend = $this->setUpBackend();
257 $data = str_repeat('abcde', 1024 * 1024);
258 $identifier = $this->getUniqueId('tooLargeData');
259 $backend->set($identifier, $data);
260 $this->assertTrue($backend->has($identifier));
261 $this->assertEquals($backend->get($identifier), $data);
262 }
263
264 /**
265 * @test
266 */
267 public function setTagsOnlyOnceToIdentifier()
268 {
269 $identifier = $this->getUniqueId('MyIdentifier');
270 $tags = array('UnitTestTag%test', 'UnitTestTag%boring');
271
272 $backend = $this->setUpBackend(true);
273 $backend->_call('addIdentifierToTags', $identifier, $tags);
274 $this->assertSame(
275 $tags,
276 $backend->_call('findTagsByIdentifier', $identifier)
277 );
278
279 $backend->_call('addIdentifierToTags', $identifier, $tags);
280 $this->assertSame(
281 $tags,
282 $backend->_call('findTagsByIdentifier', $identifier)
283 );
284 }
285
286 /**
287 * Sets up the APC backend used for testing
288 *
289 * @param bool $accessible TRUE if backend should be encapsulated in accessible proxy otherwise FALSE.
290 * @return \TYPO3\CMS\Core\Tests\AccessibleObjectInterface|ApcBackend
291 */
292 protected function setUpBackend($accessible = false)
293 {
294 /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface $cache */
295 $cache = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface::class, array(), array(), '', false);
296 if ($accessible) {
297 $accessibleClassName = $this->buildAccessibleProxy(ApcBackend::class);
298 $backend = new $accessibleClassName('Testing');
299 } else {
300 $backend = new ApcBackend('Testing');
301 }
302 $backend->setCache($cache);
303 return $backend;
304 }
305 }