90abb4d6a7723abfb3dcd500975ac496cbcbf7f1
[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 if (!extension_loaded('apc')) {
46 $this->markTestSkipped('APC extension was not available');
47 }
48 if (ini_get('apc.slam_defense') == 1) {
49 $this->markTestSkipped('This testcase can only be executed with apc.slam_defense = Off');
50 }
51 }
52
53 /**
54 * @test
55 * @expectedException \TYPO3\CMS\Core\Cache\Exception
56 */
57 public function setThrowsExceptionIfNoFrontEndHasBeenSet() {
58 $backend = new \TYPO3\CMS\Core\Cache\Backend\ApcBackend('Testing');
59 $data = 'Some data';
60 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
61 $backend->set($identifier, $data);
62 }
63
64 /**
65 * @test
66 */
67 public function itIsPossibleToSetAndCheckExistenceInCache() {
68 // APC has some slam protection that tries to prevent hammering of cache
69 // entries. This can be disabled, but the option does not work at least
70 // in native PHP 5.3.3 on debian squeeze. While it is no problem with
71 // higher PHP version like the current one on travis-ci.org,
72 // the test is now just skipped on PHP environments that are knows for issues.
73 if (version_compare(phpversion(), '5.3.4', '<')) {
74 $this->markTestSkipped('This test is not reliable with PHP version below 5.3.3');
75 }
76 $backend = $this->setUpBackend();
77 $data = 'Some data';
78 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
79 $backend->set($identifier, $data);
80 $inCache = $backend->has($identifier);
81 $this->assertTrue($inCache, 'APC backend failed to set and check entry');
82 }
83
84 /**
85 * @test
86 */
87 public function itIsPossibleToSetAndGetEntry() {
88 // APC has some slam protection that tries to prevent hammering of cache
89 // entries. This can be disabled, but the option does not work at least
90 // in native PHP 5.3.3 on debian squeeze. While it is no problem with
91 // higher PHP version like the current one on travis-ci.org,
92 // the test is now just skipped on PHP environments that are knows for issues.
93 if (version_compare(phpversion(), '5.3.4', '<')) {
94 $this->markTestSkipped('This test is not reliable with PHP version below 5.3.3');
95 }
96 $backend = $this->setUpBackend();
97 $data = 'Some data';
98 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
99 $backend->set($identifier, $data);
100 $fetchedData = $backend->get($identifier);
101 $this->assertEquals($data, $fetchedData, 'APC backend failed to set and retrieve data');
102 }
103
104 /**
105 * @test
106 */
107 public function itIsPossibleToRemoveEntryFromCache() {
108 $backend = $this->setUpBackend();
109 $data = 'Some data';
110 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
111 $backend->set($identifier, $data);
112 $backend->remove($identifier);
113 $inCache = $backend->has($identifier);
114 $this->assertFalse($inCache, 'Failed to set and remove data from APC backend');
115 }
116
117 /**
118 * @test
119 */
120 public function itIsPossibleToOverwriteAnEntryInTheCache() {
121 $backend = $this->setUpBackend();
122 $data = 'Some data';
123 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
124 $backend->set($identifier, $data);
125 $otherData = 'some other data';
126 $backend->set($identifier, $otherData);
127 $fetchedData = $backend->get($identifier);
128 $this->assertEquals($otherData, $fetchedData, 'APC backend failed to overwrite and retrieve data');
129 }
130
131 /**
132 * @test
133 */
134 public function findIdentifiersByTagFindsSetEntries() {
135 $backend = $this->setUpBackend();
136 $data = 'Some data';
137 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
138 $backend->set($identifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
139 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag1');
140 $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
141 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
142 $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
143 }
144
145 /**
146 * @test
147 */
148 public function setRemovesTagsFromPreviousSet() {
149 $backend = $this->setUpBackend();
150 $data = 'Some data';
151 $identifier = 'MyIdentifier' . md5(uniqid(mt_rand(), TRUE));
152 $backend->set($identifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tagX'));
153 $backend->set($identifier, $data, array('UnitTestTag%tag3'));
154 $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tagX');
155 $this->assertEquals(array(), $retrieved, 'Found entry which should no longer exist.');
156 }
157
158 /**
159 * @test
160 */
161 public function setCacheIsSettingIdentifierPrefixWithCacheIdentifier() {
162 $cacheMock = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\FrontendInterface', array(), array(), '', FALSE);
163 $cacheMock->expects($this->any())->method('getIdentifier')->will($this->returnValue(
164 'testidentifier'
165 ));
166
167 /** @var $backendMock \TYPO3\CMS\Core\Cache\Backend\ApcBackend */
168 $backendMock = $this->getMock(
169 'TYPO3\\CMS\\Core\\Cache\\Backend\\ApcBackend',
170 array('setIdentifierPrefix','getCurrentUserData','getPathSite'),
171 array('testcontext')
172 );
173
174 $backendMock->expects($this->once())->method('getCurrentUserData')->will(
175 $this->returnValue(array('name' => 'testname'))
176 );
177
178 $backendMock->expects($this->once())->method('getPathSite')->will(
179 $this->returnValue('testpath')
180 );
181
182 $expectedIdentifier = 'TYPO3_' . \TYPO3\CMS\Core\Utility\GeneralUtility::shortMD5('testpath' . 'testname' . 'testcontext' . 'testidentifier', 12);
183 $backendMock->expects($this->once())->method('setIdentifierPrefix')->with($expectedIdentifier);
184 $backendMock->setCache($cacheMock);
185 }
186
187 /**
188 * @test
189 */
190 public function hasReturnsFalseIfTheEntryDoesntExist() {
191 $backend = $this->setUpBackend();
192 $identifier = 'NonExistingIdentifier' . md5(uniqid(mt_rand(), TRUE));
193 $inCache = $backend->has($identifier);
194 $this->assertFalse($inCache, '"has" did not return FALSE when checking on non existing identifier');
195 }
196
197 /**
198 * @test
199 */
200 public function removeReturnsFalseIfTheEntryDoesntExist() {
201 $backend = $this->setUpBackend();
202 $identifier = 'NonExistingIdentifier' . md5(uniqid(mt_rand(), TRUE));
203 $inCache = $backend->remove($identifier);
204 $this->assertFalse($inCache, '"remove" did not return FALSE when checking on non existing identifier');
205 }
206
207 /**
208 * @test
209 */
210 public function flushByTagRemovesCacheEntriesWithSpecifiedTag() {
211 $backend = $this->setUpBackend();
212 $data = 'some data' . microtime();
213 $backend->set('BackendAPCTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
214 $backend->set('BackendAPCTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
215 $backend->set('BackendAPCTest3', $data, array('UnitTestTag%test'));
216 $backend->flushByTag('UnitTestTag%special');
217 $this->assertTrue($backend->has('BackendAPCTest1'), 'BackendAPCTest1');
218 $this->assertFalse($backend->has('BackendAPCTest2'), 'BackendAPCTest2');
219 $this->assertTrue($backend->has('BackendAPCTest3'), 'BackendAPCTest3');
220 }
221
222 /**
223 * @test
224 */
225 public function flushRemovesAllCacheEntries() {
226 // APC has some slam protection that tries to prevent hammering of cache
227 // entries. This can be disabled, but the option does not work at least
228 // in native PHP 5.3.3 on debian squeeze. While it is no problem with
229 // higher PHP version like the current one on travis-ci.org,
230 // the test is now just skipped on PHP environments that are knows for issues.
231 if (version_compare(phpversion(), '5.3.4', '<')) {
232 $this->markTestSkipped('This test is not reliable with PHP version below 5.3.3');
233 }
234 $backend = $this->setUpBackend();
235 $data = 'some data' . microtime();
236 $backend->set('BackendAPCTest1', $data);
237 $backend->set('BackendAPCTest2', $data);
238 $backend->set('BackendAPCTest3', $data);
239 $backend->flush();
240 $this->assertFalse($backend->has('BackendAPCTest1'), 'BackendAPCTest1');
241 $this->assertFalse($backend->has('BackendAPCTest2'), 'BackendAPCTest2');
242 $this->assertFalse($backend->has('BackendAPCTest3'), 'BackendAPCTest3');
243 }
244
245 /**
246 * @test
247 */
248 public function flushRemovesOnlyOwnEntries() {
249 $thisCache = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\FrontendInterface', array(), array(), '', FALSE);
250 $thisCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thisCache'));
251 $thisBackend = new \TYPO3\CMS\Core\Cache\Backend\ApcBackend('Testing');
252 $thisBackend->setCache($thisCache);
253 $thatCache = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\FrontendInterface', array(), array(), '', FALSE);
254 $thatCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thatCache'));
255 $thatBackend = new \TYPO3\CMS\Core\Cache\Backend\ApcBackend('Testing');
256 $thatBackend->setCache($thatCache);
257 $thisBackend->set('thisEntry', 'Hello');
258 $thatBackend->set('thatEntry', 'World!');
259 $thatBackend->flush();
260 $this->assertEquals('Hello', $thisBackend->get('thisEntry'));
261 $this->assertFalse($thatBackend->has('thatEntry'));
262 }
263
264 /**
265 * Check if we can store ~5 MB of data
266 *
267 * @test
268 */
269 public function largeDataIsStored() {
270 $backend = $this->setUpBackend();
271 $data = str_repeat('abcde', 1024 * 1024);
272 $identifier = 'tooLargeData' . md5(uniqid(mt_rand(), TRUE));
273 $backend->set($identifier, $data);
274 $this->assertTrue($backend->has($identifier));
275 $this->assertEquals($backend->get($identifier), $data);
276 }
277
278 /**
279 * Sets up the APC backend used for testing
280 *
281 * @return \TYPO3\CMS\Core\Cache\Backend\ApcBackend
282 */
283 protected function setUpBackend() {
284 $cache = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\FrontendInterface', array(), array(), '', FALSE);
285 $backend = new \TYPO3\CMS\Core\Cache\Backend\ApcBackend('Testing');
286 $backend->setCache($cache);
287 return $backend;
288 }
289
290 }
291
292 ?>