a88666c51105e64a0b7c55e30d23751438c30526
[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 * Copyright notice
6 *
7 * (c) 2009-2013 Ingo Renner <ingo@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 /**
28 * Testcase for the APC cache backend.
29 *
30 * NOTE: If you want to execute these tests you need to enable apc in
31 * cli context (apc.enable_cli = 1)
32 *
33 * This file is a backport from FLOW3
34 *
35 * @author Ingo Renner <ingo@typo3.org>
36 */
37 class ApcBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
38
39 /**
40 * Sets up this testcase
41 *
42 * @return void
43 */
44 public function setUp() {
45 // Currently APCu identifies itself both as "apcu" and "apc" (for compatibility) although it doesn't provide the APC-opcache functionality
46 if (!extension_loaded('apc')) {
47 $this->markTestSkipped('APC/APCu extension was not available');
48 }
49 if (ini_get('apc.slam_defense') == 1) {
50 $this->markTestSkipped('This testcase can only be executed with apc.slam_defense = Off');
51 }
52 }
53
54 /**
55 * @test
56 * @expectedException \TYPO3\CMS\Core\Cache\Exception
57 */
58 public function setThrowsExceptionIfNoFrontEndHasBeenSet() {
59 $backend = new \TYPO3\CMS\Core\Cache\Backend\ApcBackend('Testing');
60 $data = 'Some data';
61 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
62 $backend->set($identifier, $data);
63 }
64
65 /**
66 * @test
67 */
68 public function itIsPossibleToSetAndCheckExistenceInCache() {
69 // APC has some slam protection that tries to prevent hammering of cache
70 // entries. This can be disabled, but the option does not work at least
71 // in native PHP 5.3.3 on debian squeeze. While it is no problem with
72 // higher PHP version like the current one on travis-ci.org,
73 // the test is now just skipped on PHP environments that are knows for issues.
74 if (version_compare(phpversion(), '5.3.4', '<')) {
75 $this->markTestSkipped('This test is not reliable with PHP version below 5.3.3');
76 }
77 $backend = $this->setUpBackend();
78 $data = 'Some data';
79 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
80 $backend->set($identifier, $data);
81 $inCache = $backend->has($identifier);
82 $this->assertTrue($inCache, 'APC backend failed to set and check entry');
83 }
84
85 /**
86 * @test
87 */
88 public function itIsPossibleToSetAndGetEntry() {
89 // APC has some slam protection that tries to prevent hammering of cache
90 // entries. This can be disabled, but the option does not work at least
91 // in native PHP 5.3.3 on debian squeeze. While it is no problem with
92 // higher PHP version like the current one on travis-ci.org,
93 // the test is now just skipped on PHP environments that are knows for issues.
94 if (version_compare(phpversion(), '5.3.4', '<')) {
95 $this->markTestSkipped('This test is not reliable with PHP version below 5.3.3');
96 }
97 $backend = $this->setUpBackend();
98 $data = 'Some data';
99 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
100 $backend->set($identifier, $data);
101 $fetchedData = $backend->get($identifier);
102 $this->assertEquals($data, $fetchedData, 'APC backend failed to set and retrieve data');
103 }
104
105 /**
106 * @test
107 */
108 public function itIsPossibleToRemoveEntryFromCache() {
109 $backend = $this->setUpBackend();
110 $data = 'Some data';
111 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
112 $backend->set($identifier, $data);
113 $backend->remove($identifier);
114 $inCache = $backend->has($identifier);
115 $this->assertFalse($inCache, 'Failed to set and remove data from APC backend');
116 }
117
118 /**
119 * @test
120 */
121 public function itIsPossibleToOverwriteAnEntryInTheCache() {
122 $backend = $this->setUpBackend();
123 $data = 'Some data';
124 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
125 $backend->set($identifier, $data);
126 $otherData = 'some other data';
127 $backend->set($identifier, $otherData);
128 $fetchedData = $backend->get($identifier);
129 $this->assertEquals($otherData, $fetchedData, 'APC backend failed to overwrite and retrieve data');
130 }
131
132 /**
133 * @test
134 */
135 public function findIdentifiersByTagFindsSetEntries() {
136 $backend = $this->setUpBackend();
137 $data = 'Some data';
138 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
139 $backend->set($identifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
140 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag1');
141 $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
142 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
143 $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
144 }
145
146 /**
147 * @test
148 */
149 public function setRemovesTagsFromPreviousSet() {
150 $backend = $this->setUpBackend();
151 $data = 'Some data';
152 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
153 $backend->set($identifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tagX'));
154 $backend->set($identifier, $data, array('UnitTestTag%tag3'));
155 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tagX');
156 $this->assertEquals(array(), $retrieved, 'Found entry which should no longer exist.');
157 }
158
159 /**
160 * @test
161 */
162 public function setCacheIsSettingIdentifierPrefixWithCacheIdentifier() {
163 $cacheMock = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\FrontendInterface', array(), array(), '', FALSE);
164 $cacheMock->expects($this->any())->method('getIdentifier')->will($this->returnValue(
165 'testidentifier'
166 ));
167
168 /** @var $backendMock \TYPO3\CMS\Core\Cache\Backend\ApcBackend */
169 $backendMock = $this->getMock(
170 'TYPO3\\CMS\\Core\\Cache\\Backend\\ApcBackend',
171 array('setIdentifierPrefix','getCurrentUserData','getPathSite'),
172 array('testcontext')
173 );
174
175 $backendMock->expects($this->once())->method('getCurrentUserData')->will(
176 $this->returnValue(array('name' => 'testname'))
177 );
178
179 $backendMock->expects($this->once())->method('getPathSite')->will(
180 $this->returnValue('testpath')
181 );
182
183 $expectedIdentifier = 'TYPO3_' . \TYPO3\CMS\Core\Utility\GeneralUtility::shortMD5('testpath' . 'testname' . 'testcontext' . 'testidentifier', 12);
184 $backendMock->expects($this->once())->method('setIdentifierPrefix')->with($expectedIdentifier);
185 $backendMock->setCache($cacheMock);
186 }
187
188 /**
189 * @test
190 */
191 public function hasReturnsFalseIfTheEntryDoesntExist() {
192 $backend = $this->setUpBackend();
193 $identifier = 'NonExistingIdentifier' . md5(uniqid(mt_rand(), TRUE));
194 $inCache = $backend->has($identifier);
195 $this->assertFalse($inCache, '"has" did not return FALSE when checking on non existing identifier');
196 }
197
198 /**
199 * @test
200 */
201 public function removeReturnsFalseIfTheEntryDoesntExist() {
202 $backend = $this->setUpBackend();
203 $identifier = 'NonExistingIdentifier' . md5(uniqid(mt_rand(), TRUE));
204 $inCache = $backend->remove($identifier);
205 $this->assertFalse($inCache, '"remove" did not return FALSE when checking on non existing identifier');
206 }
207
208 /**
209 * @test
210 */
211 public function flushByTagRemovesCacheEntriesWithSpecifiedTag() {
212 if (version_compare(phpversion(), '5.4.0', '<')) {
213 $this->markTestSkipped('This test is not reliable with PHP version below 5.4.0');
214 }
215 $backend = $this->setUpBackend();
216 $data = 'some data' . microtime();
217 $backend->set('BackendAPCTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
218 $backend->set('BackendAPCTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
219 $backend->set('BackendAPCTest3', $data, array('UnitTestTag%test'));
220 $backend->flushByTag('UnitTestTag%special');
221 $this->assertTrue($backend->has('BackendAPCTest1'), 'BackendAPCTest1');
222 $this->assertFalse($backend->has('BackendAPCTest2'), 'BackendAPCTest2');
223 $this->assertTrue($backend->has('BackendAPCTest3'), 'BackendAPCTest3');
224 }
225
226 /**
227 * @test
228 */
229 public function flushRemovesAllCacheEntries() {
230 // APC has some slam protection that tries to prevent hammering of cache
231 // entries. This can be disabled, but the option does not work at least
232 // in native PHP 5.3.3 on debian squeeze. While it is no problem with
233 // higher PHP version like the current one on travis-ci.org,
234 // the test is now just skipped on PHP environments that are knows for issues.
235 if (version_compare(phpversion(), '5.3.4', '<')) {
236 $this->markTestSkipped('This test is not reliable with PHP version below 5.3.3');
237 }
238 $backend = $this->setUpBackend();
239 $data = 'some data' . microtime();
240 $backend->set('BackendAPCTest1', $data);
241 $backend->set('BackendAPCTest2', $data);
242 $backend->set('BackendAPCTest3', $data);
243 $backend->flush();
244 $this->assertFalse($backend->has('BackendAPCTest1'), 'BackendAPCTest1');
245 $this->assertFalse($backend->has('BackendAPCTest2'), 'BackendAPCTest2');
246 $this->assertFalse($backend->has('BackendAPCTest3'), 'BackendAPCTest3');
247 }
248
249 /**
250 * @test
251 */
252 public function flushRemovesOnlyOwnEntries() {
253 $thisCache = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\FrontendInterface', array(), array(), '', FALSE);
254 $thisCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thisCache'));
255 $thisBackend = new \TYPO3\CMS\Core\Cache\Backend\ApcBackend('Testing');
256 $thisBackend->setCache($thisCache);
257 $thatCache = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\FrontendInterface', array(), array(), '', FALSE);
258 $thatCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thatCache'));
259 $thatBackend = new \TYPO3\CMS\Core\Cache\Backend\ApcBackend('Testing');
260 $thatBackend->setCache($thatCache);
261 $thisBackend->set('thisEntry', 'Hello');
262 $thatBackend->set('thatEntry', 'World!');
263 $thatBackend->flush();
264 $this->assertEquals('Hello', $thisBackend->get('thisEntry'));
265 $this->assertFalse($thatBackend->has('thatEntry'));
266 }
267
268 /**
269 * Check if we can store ~5 MB of data
270 *
271 * @test
272 */
273 public function largeDataIsStored() {
274 $backend = $this->setUpBackend();
275 $data = str_repeat('abcde', 1024 * 1024);
276 $identifier = 'tooLargeData' . md5(uniqid(mt_rand(), TRUE));
277 $backend->set($identifier, $data);
278 $this->assertTrue($backend->has($identifier));
279 $this->assertEquals($backend->get($identifier), $data);
280 }
281
282 /**
283 * Sets up the APC backend used for testing
284 *
285 * @return \TYPO3\CMS\Core\Cache\Backend\ApcBackend
286 */
287 protected function setUpBackend() {
288 $cache = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\FrontendInterface', array(), array(), '', FALSE);
289 $backend = new \TYPO3\CMS\Core\Cache\Backend\ApcBackend('Testing');
290 $backend->setCache($cache);
291 return $backend;
292 }
293
294 }
295
296 ?>