[TASK] Add leading backslashes to InvalidArgumentException
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Cache / Backend / DbBackendTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Cache\Backend;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2009-2011 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 DB cache backend
29 *
30 * @author Ingo Renner <ingo@typo3.org>
31 * @package TYPO3
32 * @subpackage tests
33 */
34 class DbBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
35
36 /**
37 * Enable backup of global and system variables
38 *
39 * @var boolean
40 */
41 protected $backupGlobals = TRUE;
42
43 /**
44 * @var \TYPO3\CMS\Core\Database\DatabaseConnection Backup of original TYPO3_DB instance
45 */
46 protected $typo3DbBackup;
47
48 /**
49 * @var string Name of the testing data table
50 */
51 protected $testingCacheTable;
52
53 /**
54 * @var string Name of the testing tags table
55 */
56 protected $testingTagsTable;
57
58 /**
59 * Set up testcases
60 */
61 public function setUp() {
62 $this->typo3DbBackup = $GLOBALS['TYPO3_DB'];
63 $tablePrefix = 'cf_';
64 $this->testingCacheTable = $tablePrefix . 'Testing';
65 $this->testingTagsTable = $tablePrefix . 'Testing_tags';
66 }
67
68 /**
69 * Sets up the backend used for testing
70 *
71 * @return void
72 */
73 protected function setUpBackend(array $backendOptions = array()) {
74 $GLOBALS['TYPO3_DB']->sql_query('CREATE TABLE ' . $this->testingCacheTable . ' (
75 id int(11) unsigned NOT NULL auto_increment,
76 identifier varchar(250) DEFAULT \'\' NOT NULL,
77 expires int(11) unsigned DEFAULT \'0\' NOT NULL,
78 content mediumblob,
79 PRIMARY KEY (id),
80 KEY cache_id (identifier, expires)
81 ) ENGINE=InnoDB;
82 ');
83 $GLOBALS['TYPO3_DB']->sql_query('CREATE TABLE ' . $this->testingTagsTable . ' (
84 id int(11) unsigned NOT NULL auto_increment,
85 identifier varchar(250) DEFAULT \'\' NOT NULL,
86 tag varchar(250) DEFAULT \'\' NOT NULL,
87 PRIMARY KEY (id),
88 KEY cache_id (identifier),
89 KEY cache_tag (tag)
90 ) ENGINE=InnoDB;
91 ');
92 $backend = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Cache\\Backend\\Typo3DatabaseBackend', 'Testing', $backendOptions);
93 return $backend;
94 }
95
96 /**
97 * Helper method to inject a mock frontend to backend instance
98 *
99 * @param \TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend $backend Current backend instance
100 * @return \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface Mock frontend
101 */
102 protected function setUpMockFrontendOfBackend(\TYPO3\CMS\Core\Cache\Backend\Typo3DatabaseBackend $backend) {
103 $mockCache = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\AbstractFrontend', array(), array(), '', FALSE);
104 $mockCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('Testing'));
105 $backend->setCache($mockCache);
106 return $mockCache;
107 }
108
109 /**
110
111 */
112 public function tearDown() {
113 $GLOBALS['TYPO3_DB'] = $this->typo3DbBackup;
114 $GLOBALS['TYPO3_DB']->sql_query('DROP TABLE IF EXISTS ' . $this->testingCacheTable . ';');
115 $GLOBALS['TYPO3_DB']->sql_query('DROP TABLE IF EXISTS ' . $this->testingTagsTable . ';');
116 }
117
118 /**
119 * @test
120 */
121 public function setCacheCalculatesCacheTableName() {
122 $backend = $this->setUpBackend();
123 $this->setUpMockFrontendOfBackend($backend);
124 $this->assertEquals($this->testingCacheTable, $backend->getCacheTable());
125 }
126
127 /**
128 * @test
129 */
130 public function setCacheCalculatesTagsTableName() {
131 $backend = $this->setUpBackend();
132 $this->setUpMockFrontendOfBackend($backend);
133 $this->assertEquals($this->testingTagsTable, $backend->getTagsTable());
134 }
135
136 /**
137 * @test
138 * @expectedException \TYPO3\CMS\Core\Cache\Exception
139 */
140 public function setThrowsExceptionIfFrontendWasNotSet() {
141 $backend = $this->setUpBackend();
142 $backend->set('identifier', 'data');
143 }
144
145 /**
146 * @test
147 * @expectedException \TYPO3\CMS\Core\Cache\Exception\InvalidDataException
148 */
149 public function setThrowsExceptionIfDataIsNotAString() {
150 $backend = $this->setUpBackend();
151 $this->setUpMockFrontendOfBackend($backend);
152 $data = array('Some data');
153 $entryIdentifier = 'BackendDbTest';
154 $backend->set($entryIdentifier, $data);
155 }
156
157 /**
158 * @test
159 */
160 public function setInsertsEntryInTable() {
161 $backend = $this->setUpBackend();
162 $this->setUpMockFrontendOfBackend($backend);
163 $data = 'some data' . microtime();
164 $entryIdentifier = 'BackendDbTest';
165 $backend->set($entryIdentifier, $data);
166 $entryFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', $this->testingCacheTable, 'identifier = \'' . $entryIdentifier . '\'');
167 $this->assertEquals($data, $entryFound['content']);
168 }
169
170 /**
171 * @test
172 */
173 public function setRemovesAnAlreadyExistingCacheEntryForTheSameIdentifier() {
174 $backend = $this->setUpBackend();
175 $this->setUpMockFrontendOfBackend($backend);
176 $data1 = 'some data' . microtime();
177 $data2 = $data1 . '_different';
178 $entryIdentifier = 'BackendDbRemoveBeforeSetTest';
179 $backend->set($entryIdentifier, $data1, array(), 500);
180 $backend->set($entryIdentifier, $data2, array(), 200);
181 $entriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', $this->testingCacheTable, 'identifier = \'' . $entryIdentifier . '\'');
182 $this->assertEquals(1, count($entriesFound));
183 }
184
185 /**
186 * @test
187 */
188 public function setReallySavesSpecifiedTags() {
189 $backend = $this->setUpBackend();
190 $this->setUpMockFrontendOfBackend($backend);
191 $data = 'some data' . microtime();
192 $entryIdentifier = 'BackendDbTest';
193 $backend->set($entryIdentifier, $data, array('UnitTestTag%tag1', 'UnitTestTag%tag2'));
194 $entriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', $this->testingTagsTable, 'identifier = \'' . $entryIdentifier . '\'');
195 $tags = array();
196 foreach ($entriesFound as $entry) {
197 $tags[] = $entry['tag'];
198 }
199 $this->assertTrue(count($tags) > 0);
200 $this->assertTrue(in_array('UnitTestTag%tag1', $tags));
201 $this->assertTrue(in_array('UnitTestTag%tag2', $tags));
202 }
203
204 /**
205 * @test
206 */
207 public function setSavesCompressedDataWithEnabledCompression() {
208 $backend = $this->setUpBackend(array(
209 'compression' => TRUE
210 ));
211 $this->setUpMockFrontendOfBackend($backend);
212 $data = 'some data ' . microtime();
213 $entryIdentifier = 'BackendDbTest';
214 $backend->set($entryIdentifier, $data);
215 $entry = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('content', $this->testingCacheTable, 'identifier = \'' . $entryIdentifier . '\'');
216 $this->assertEquals($data, @gzuncompress($entry['content']));
217 }
218
219 /**
220 * @test
221 */
222 public function setSavesPlaintextDataWithEnabledCompressionAndCompressionLevel0() {
223 $backend = $this->setUpBackend(array(
224 'compression' => TRUE,
225 'compressionLevel' => 0
226 ));
227 $this->setUpMockFrontendOfBackend($backend);
228 $data = 'some data ' . microtime();
229 $entryIdentifier = 'BackendDbTest';
230 $backend->set($entryIdentifier, $data);
231 $entry = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('content', $this->testingCacheTable, 'identifier = \'' . $entryIdentifier . '\'');
232 $this->assertGreaterThan(0, substr_count($entry['content'], $data));
233 }
234
235 /**
236 * @test
237 * @expectedException \TYPO3\CMS\Core\Cache\Exception
238 */
239 public function getThrowsExceptionIfFrontendWasNotSet() {
240 $backend = $this->setUpBackend();
241 $backend->get('identifier');
242 }
243
244 /**
245 * @test
246 */
247 public function getReturnsContentOfTheCorrectCacheEntry() {
248 $backend = $this->setUpBackend();
249 $this->setUpMockFrontendOfBackend($backend);
250 $data = 'some data' . microtime();
251 $entryIdentifier = 'BackendDbTest';
252 $backend->set($entryIdentifier, $data, array(), 500);
253 $data = 'some other data' . microtime();
254 $backend->set($entryIdentifier, $data, array(), 100);
255 $loadedData = $backend->get($entryIdentifier);
256 $this->assertEquals($data, $loadedData);
257 }
258
259 /**
260 * @test
261 * @expectedException \TYPO3\CMS\Core\Cache\Exception
262 */
263 public function hasThrowsExceptionIfFrontendWasNotSet() {
264 $backend = $this->setUpBackend();
265 $backend->has('identifier');
266 }
267
268 /**
269 * @test
270 */
271 public function hasReturnsTheCorrectResult() {
272 $backend = $this->setUpBackend();
273 $this->setUpMockFrontendOfBackend($backend);
274 $data = 'some data' . microtime();
275 $entryIdentifier = 'BackendDbTest';
276 $backend->set($entryIdentifier, $data);
277 $this->assertTrue($backend->has($entryIdentifier));
278 $this->assertFalse($backend->has($entryIdentifier . 'Not'));
279 }
280
281 /**
282 * @test
283 * @expectedException \TYPO3\CMS\Core\Cache\Exception
284 */
285 public function removeThrowsExceptionIfFrontendWasNotSet() {
286 $backend = $this->setUpBackend();
287 $backend->remove('identifier');
288 }
289
290 /**
291 * @test
292 */
293 public function removeReallyRemovesACacheEntry() {
294 $backend = $this->setUpBackend();
295 $this->setUpMockFrontendOfBackend($backend);
296 $data = 'some data' . microtime();
297 $entryIdentifier = 'BackendDbRemovalTest';
298 $backend->set($entryIdentifier, $data);
299 $backend->remove($entryIdentifier);
300 $entriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', $this->testingCacheTable, 'identifier = \'' . $entryIdentifier . '\'');
301 $this->assertTrue(count($entriesFound) == 0);
302 }
303
304 /**
305 * @test
306 * @expectedException \TYPO3\CMS\Core\Cache\Exception
307 */
308 public function collectGarbageThrowsExceptionIfFrontendWasNotSet() {
309 $backend = $this->setUpBackend();
310 $backend->collectGarbage();
311 }
312
313 /**
314 * @test
315 */
316 public function collectGarbageReallyRemovesAnExpiredCacheEntry() {
317 $backend = $this->setUpBackend();
318 $mockCache = $this->setUpMockFrontendOfBackend($backend);
319 $data = 'some data' . microtime();
320 $entryIdentifier = 'BackendDbRemovalTest';
321 $backend->set($entryIdentifier, $data, array(), 1);
322 $GLOBALS['EXEC_TIME'] += 2;
323 // setCache calls initializeCommonReferences which recalculate expire statement
324 // needed after manual $GLOBALS['EXEC_TIME'] manipulation
325 $backend->setCache($mockCache);
326 $backend->collectGarbage();
327 $entriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', $this->testingCacheTable, 'identifier = \'' . $entryIdentifier . '\'');
328 $this->assertTrue(count($entriesFound) == 0);
329 }
330
331 /**
332 * @test
333 */
334 public function collectGarbageReallyRemovesAllExpiredCacheEntries() {
335 $backend = $this->setUpBackend();
336 $mockCache = $this->setUpMockFrontendOfBackend($backend);
337 $data = 'some data' . microtime();
338 $entryIdentifier = 'BackendDbRemovalTest';
339 $backend->set($entryIdentifier . 'A', $data, array(), 1);
340 $backend->set($entryIdentifier . 'B', $data, array(), 1);
341 $backend->set($entryIdentifier . 'C', $data, array(), 1);
342 $GLOBALS['EXEC_TIME'] += 2;
343 // setCache calls initializeCommonReferences which recalculate expire statement
344 // needed after manual $GLOBALS['EXEC_TIME'] manipulation
345 $backend->setCache($mockCache);
346 $backend->collectGarbage();
347 $entriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', $this->testingCacheTable, '');
348 $this->assertTrue(count($entriesFound) == 0);
349 }
350
351 /**
352 * @test
353 */
354 public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag() {
355 $backend = $this->setUpBackend();
356 $this->setUpMockFrontendOfBackend($backend);
357 $data = 'some data' . microtime();
358 $backend->set('BackendDbTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
359 $backend->set('BackendDbTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
360 $backend->set('BackendDbTest3', $data, array('UnitTestTag%test'));
361 $expectedEntry = 'BackendDbTest2';
362 $actualEntries = $backend->findIdentifiersByTag('UnitTestTag%special');
363 $this->assertTrue(is_array($actualEntries));
364 $this->assertEquals($expectedEntry, array_pop($actualEntries));
365 }
366
367 /**
368 * @test
369 * @expectedException \TYPO3\CMS\Core\Cache\Exception
370 */
371 public function flushThrowsExceptionIfFrontendWasNotSet() {
372 $backend = $this->setUpBackend();
373 $backend->flush();
374 }
375
376 /**
377 * @test
378 */
379 public function flushRemovesAllCacheEntries() {
380 $backend = $this->setUpBackend();
381 $this->setUpMockFrontendOfBackend($backend);
382 $data = 'some data' . microtime();
383 $backend->set('BackendDbTest1', $data, array('UnitTestTag%test'));
384 $backend->set('BackendDbTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
385 $backend->set('BackendDbTest3', $data, array('UnitTestTag%test'));
386 $backend->flush();
387 $entriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', $this->testingCacheTable, '');
388 $this->assertTrue(count($entriesFound) == 0);
389 }
390
391 /**
392 * @test
393 * @expectedException \TYPO3\CMS\Core\Cache\Exception
394 */
395 public function flushByTagThrowsExceptionIfFrontendWasNotSet() {
396 $backend = $this->setUpBackend();
397 $backend->flushByTag(array());
398 }
399
400 /**
401 * @test
402 */
403 public function flushByTagRemovesCacheEntriesWithSpecifiedTag() {
404 $backend = $this->setUpBackend();
405 $this->setUpMockFrontendOfBackend($backend);
406 $data = 'some data' . microtime();
407 $backend->set('BackendDbTest1', $data, array('UnitTestTag%test', 'UnitTestTag%boring'));
408 $backend->set('BackendDbTest2', $data, array('UnitTestTag%test', 'UnitTestTag%special'));
409 $backend->set('BackendDbTest3', $data, array('UnitTestTag%test'));
410 $backend->flushByTag('UnitTestTag%special');
411 $this->assertTrue($backend->has('BackendDbTest1'), 'BackendDbTest1 does not exist anymore.');
412 $this->assertFalse($backend->has('BackendDbTest2'), 'BackendDbTest2 still exists.');
413 $this->assertTrue($backend->has('BackendDbTest3'), 'BackendDbTest3 does not exist anymore.');
414 $tagEntriesFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', $this->testingTagsTable, 'tag = ' . $GLOBALS['TYPO3_DB']->fullQuoteStr('UnitTestTag%special', $this->testingTagsTable));
415 $this->assertEquals(0, count($tagEntriesFound));
416 }
417
418 /**
419 * @test
420 */
421 public function hasReturnsTheCorrectResultForEntryWithExceededLifetime() {
422 $backend = $this->setUpBackend();
423 $mockCache = $this->setUpMockFrontendOfBackend($backend);
424 $data = 'some data' . microtime();
425 $entryIdentifier = 'BackendDbTest';
426 $backend->set($entryIdentifier, $data);
427 $expiredEntryIdentifier = 'ExpiredBackendDbTest';
428 $expiredData = 'some old data' . microtime();
429 $backend->set($expiredEntryIdentifier, $expiredData, array(), 1);
430 $GLOBALS['EXEC_TIME'] += 2;
431 // setCache calls initializeCommonReferences which recalculate expire statement
432 // needed after manual $GLOBALS['EXEC_TIME'] manipulation
433 $backend->setCache($mockCache);
434 $this->assertFalse($backend->has($expiredEntryIdentifier));
435 }
436
437 /**
438 * @test
439 */
440 public function hasReturnsTrueForEntryWithUnlimitedLifetime() {
441 $backend = $this->setUpBackend();
442 $mockCache = $this->setUpMockFrontendOfBackend($backend);
443 $entryIdentifier = 'BackendDbTest';
444 $backend->set($entryIdentifier, 'data', array(), 0);
445 $GLOBALS['EXEC_TIME'] += 1;
446 // setCache calls initializeCommonReferences which recalculate expire statement
447 // needed after manual $GLOBALS['EXEC_TIME'] manipulation
448 $backend->setCache($mockCache);
449 $this->assertTrue($backend->has($entryIdentifier));
450 }
451
452 /**
453 * @test
454 */
455 public function getReturnsFalseForEntryWithExceededLifetime() {
456 $backend = $this->setUpBackend();
457 $mockCache = $this->setUpMockFrontendOfBackend($backend);
458 $data = 'some data' . microtime();
459 $entryIdentifier = 'BackendDbTest';
460 $backend->set($entryIdentifier, $data);
461 $expiredEntryIdentifier = 'ExpiredBackendDbTest';
462 $expiredData = 'some old data' . microtime();
463 $backend->set($expiredEntryIdentifier, $expiredData, array(), 1);
464 $GLOBALS['EXEC_TIME'] += 2;
465 // setCache calls initializeCommonReferences which recalculate expire statement
466 // needed after manual $GLOBALS['EXEC_TIME'] manipulation
467 $backend->setCache($mockCache);
468 $this->assertEquals($data, $backend->get($entryIdentifier));
469 $this->assertFalse($backend->get($expiredEntryIdentifier));
470 }
471
472 /**
473 * @test
474 * @expectedException \TYPO3\CMS\Core\Cache\Exception
475 */
476 public function findIdentifiersByTagThrowsExceptionIfFrontendWasNotSet() {
477 $backend = $this->setUpBackend();
478 $backend->findIdentifiersByTag('identifier');
479 }
480
481 /**
482 * @test
483 */
484 public function findIdentifiersByTagReturnsEmptyArrayForEntryWithExceededLifetime() {
485 $backend = $this->setUpBackend();
486 $mockCache = $this->setUpMockFrontendOfBackend($backend);
487 $backend->set('BackendDbTest', 'some data', array('UnitTestTag%special'), 1);
488 $GLOBALS['EXEC_TIME'] += 2;
489 // setCache calls initializeCommonReferences which recalculate expire statement
490 // needed after manual $GLOBALS['EXEC_TIME'] manipulation
491 $backend->setCache($mockCache);
492 $this->assertEquals(array(), $backend->findIdentifiersByTag('UnitTestTag%special'));
493 }
494
495 /**
496 * @test
497 */
498 public function setWithUnlimitedLifetimeWritesCorrectEntry() {
499 $backend = $this->setUpBackend();
500 $this->setUpMockFrontendOfBackend($backend);
501 $data = 'some data' . microtime();
502 $entryIdentifier = 'BackendFileTest';
503 $backend->set($entryIdentifier, $data, array(), 0);
504 $entryFound = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', $this->testingCacheTable, '');
505 $this->assertTrue(is_array($entryFound));
506 $retrievedData = $entryFound['content'];
507 $this->assertEquals($data, $retrievedData);
508 }
509
510 }
511
512 ?>