[FEATURE] Use dynamic path for typo3temp/var/
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Cache / Backend / FileBackendTest.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 org\bovigo\vfs\vfsStreamDirectory;
18 use org\bovigo\vfs\vfsStreamWrapper;
19 use TYPO3\CMS\Core\Cache\Exception\InvalidDataException;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22 /**
23 * Testcase for the File cache backend
24 */
25 class FileBackendTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
26 {
27 /**
28 * Subject is not notice free, disable E_NOTICES
29 */
30 protected static $suppressNotices = true;
31
32 /**
33 * Sets up this testcase
34 */
35 protected function setUp()
36 {
37 if (!class_exists('org\\bovigo\\vfs\\vfsStreamWrapper')) {
38 $this->markTestSkipped('File backend tests are not available with this phpunit version.');
39 }
40
41 vfsStreamWrapper::register();
42 vfsStreamWrapper::setRoot(new vfsStreamDirectory('Foo'));
43 }
44
45 /**
46 * @test
47 */
48 public function setCacheDirectoryThrowsExceptionOnNonWritableDirectory()
49 {
50 $this->expectException(\TYPO3\CMS\Core\Cache\Exception::class);
51 $this->expectExceptionCode(1303669848);
52
53 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
54
55 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
56 ->setMethods(['dummy'])
57 ->disableOriginalConstructor()
58 ->getMock();
59 $backend->setCacheDirectory('http://localhost/');
60
61 $backend->setCache($mockCache);
62 }
63
64 /**
65 * @test
66 */
67 public function setCacheDirectoryAllowsAbsolutePathWithoutTrailingSlash()
68 {
69 $backend = $this->getAccessibleMock(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class, ['dummy'], [], '', false);
70 $backend->_set('cacheIdentifier', 'test');
71 $backend->setCacheDirectory('/tmp/foo');
72 $this->assertEquals('/tmp/foo/test/', $backend->_get('temporaryCacheDirectory'));
73 }
74
75 /**
76 * @test
77 */
78 public function setCacheDirectoryAllowsAbsolutePathWithTrailingSlash()
79 {
80 $backend = $this->getAccessibleMock(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class, ['dummy'], [], '', false);
81 $backend->_set('cacheIdentifier', 'test');
82 $backend->setCacheDirectory('/tmp/foo/');
83 $this->assertEquals('/tmp/foo/test/', $backend->_get('temporaryCacheDirectory'));
84 }
85
86 /**
87 * @test
88 */
89 public function setCacheDirectoryAllowsRelativePathWithoutTrailingSlash()
90 {
91 $backend = $this->getAccessibleMock(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class, ['dummy'], [], '', false);
92 $backend->_set('cacheIdentifier', 'test');
93 $backend->setCacheDirectory('tmp/foo');
94 // get PATH_site without trailing slash
95 $path = GeneralUtility::fixWindowsFilePath(realpath(PATH_site));
96 $this->assertEquals($path . '/tmp/foo/test/', $backend->_get('temporaryCacheDirectory'));
97 }
98
99 /**
100 * @test
101 */
102 public function setCacheDirectoryAllowsRelativePathWithTrailingSlash()
103 {
104 $backend = $this->getAccessibleMock(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class, ['dummy'], [], '', false);
105 $backend->_set('cacheIdentifier', 'test');
106 $backend->setCacheDirectory('tmp/foo/');
107 // get PATH_site without trailing slash
108 $path = GeneralUtility::fixWindowsFilePath(realpath(PATH_site));
109 $this->assertEquals($path . '/tmp/foo/test/', $backend->_get('temporaryCacheDirectory'));
110 }
111
112 /**
113 * @test
114 */
115 public function setCacheDirectoryAllowsRelativeDottedPathWithoutTrailingSlash()
116 {
117 $backend = $this->getAccessibleMock(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class, ['dummy'], [], '', false);
118 $backend->_set('cacheIdentifier', 'test');
119 $backend->setCacheDirectory('../tmp/foo');
120 // get PATH_site without trailing slash
121 $path = GeneralUtility::fixWindowsFilePath(realpath(PATH_site));
122 $this->assertEquals($path . '/../tmp/foo/test/', $backend->_get('temporaryCacheDirectory'));
123 }
124
125 /**
126 * @test
127 */
128 public function setCacheDirectoryAllowsRelativeDottedPathWithTrailingSlash()
129 {
130 $backend = $this->getAccessibleMock(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class, ['dummy'], [], '', false);
131 $backend->_set('cacheIdentifier', 'test');
132 $backend->setCacheDirectory('../tmp/foo/');
133 // get PATH_site without trailing slash
134 $path = GeneralUtility::fixWindowsFilePath(realpath(PATH_site));
135 $this->assertEquals($path . '/../tmp/foo/test/', $backend->_get('temporaryCacheDirectory'));
136 }
137
138 /**
139 * @test
140 */
141 public function setCacheDirectoryAllowsAbsoluteDottedPathWithoutTrailingSlash()
142 {
143 $backend = $this->getAccessibleMock(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class, ['dummy'], [], '', false);
144 $backend->_set('cacheIdentifier', 'test');
145 $backend->setCacheDirectory('/tmp/../foo');
146 $this->assertEquals('/tmp/../foo/test/', $backend->_get('temporaryCacheDirectory'));
147 }
148
149 /**
150 * @test
151 */
152 public function setCacheDirectoryAllowsAbsoluteDottedPathWithTrailingSlash()
153 {
154 $backend = $this->getAccessibleMock(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class, ['dummy'], [], '', false);
155 $backend->_set('cacheIdentifier', 'test');
156 $backend->setCacheDirectory('/tmp/../foo/');
157 $this->assertEquals('/tmp/../foo/test/', $backend->_get('temporaryCacheDirectory'));
158 }
159
160 /**
161 * @test
162 */
163 public function getCacheDirectoryReturnsTheCurrentCacheDirectory()
164 {
165 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
166 $mockCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('SomeCache'));
167
168 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
169 ->setMethods(['dummy'])
170 ->disableOriginalConstructor()
171 ->getMock();
172 $backend->setCacheDirectory('vfs://Foo/');
173 $backend->setCache($mockCache);
174
175 $this->assertEquals('vfs://Foo/cache/data/SomeCache/', $backend->getCacheDirectory());
176 }
177
178 /**
179 * @test
180 */
181 public function aDedicatedCacheDirectoryIsUsedForCodeCaches()
182 {
183 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\PhpFrontend::class);
184 $mockCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('SomeCache'));
185
186 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
187 ->setMethods(['dummy'])
188 ->disableOriginalConstructor()
189 ->getMock();
190 $backend->setCacheDirectory('vfs://Foo/');
191 $backend->setCache($mockCache);
192
193 $this->assertEquals('vfs://Foo/cache/code/SomeCache/', $backend->getCacheDirectory());
194 }
195
196 /**
197 * @test
198 */
199 public function setThrowsExceptionIfDataIsNotAString()
200 {
201 $this->expectException(InvalidDataException::class);
202 $this->expectExceptionCode(1204481674);
203
204 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
205
206 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
207 ->setMethods(['dummy'])
208 ->disableOriginalConstructor()
209 ->getMock();
210 $backend->setCacheDirectory('vfs://Foo/');
211 $backend->setCache($mockCache);
212
213 $backend->set('some identifier', ['not a string']);
214 }
215
216 /**
217 * @test
218 */
219 public function setReallySavesToTheSpecifiedDirectory()
220 {
221 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
222 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
223
224 $data = 'some data' . microtime();
225 $entryIdentifier = 'BackendFileTest';
226 $pathAndFilename = 'vfs://Foo/cache/data/UnitTestCache/' . $entryIdentifier;
227
228 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
229 ->setMethods(['dummy'])
230 ->disableOriginalConstructor()
231 ->getMock();
232 $backend->setCacheDirectory('vfs://Foo/');
233 $backend->setCache($mockCache);
234
235 $backend->set($entryIdentifier, $data);
236
237 $this->assertFileExists($pathAndFilename);
238 $retrievedData = file_get_contents($pathAndFilename, null, null, 0, strlen($data));
239 $this->assertEquals($data, $retrievedData);
240 }
241
242 /**
243 * @test
244 */
245 public function setOverwritesAnAlreadyExistingCacheEntryForTheSameIdentifier()
246 {
247 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
248 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
249
250 $data1 = 'some data' . microtime();
251 $data2 = 'some data' . microtime();
252 $entryIdentifier = 'BackendFileRemoveBeforeSetTest';
253
254 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
255 ->setMethods(['dummy'])
256 ->disableOriginalConstructor()
257 ->getMock();
258 $backend->setCacheDirectory('vfs://Foo/');
259 $backend->setCache($mockCache);
260
261 $backend->set($entryIdentifier, $data1, [], 500);
262 $backend->set($entryIdentifier, $data2, [], 200);
263
264 $pathAndFilename = 'vfs://Foo/cache/data/UnitTestCache/' . $entryIdentifier;
265 $this->assertFileExists($pathAndFilename);
266 $retrievedData = file_get_contents($pathAndFilename, null, null, 0, strlen($data2));
267 $this->assertEquals($data2, $retrievedData);
268 }
269
270 /**
271 * @test
272 */
273 public function setAlsoSavesSpecifiedTags()
274 {
275 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
276 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
277
278 $data = 'some data' . microtime();
279 $entryIdentifier = 'BackendFileRemoveBeforeSetTest';
280
281 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
282 ->setMethods(['dummy'])
283 ->disableOriginalConstructor()
284 ->getMock();
285 $backend->setCacheDirectory('vfs://Foo/');
286 $backend->setCache($mockCache);
287
288 $backend->set($entryIdentifier, $data, ['Tag1', 'Tag2']);
289
290 $pathAndFilename = 'vfs://Foo/cache/data/UnitTestCache/' . $entryIdentifier;
291 $this->assertFileExists($pathAndFilename);
292 $retrievedData = file_get_contents(
293 $pathAndFilename,
294 null,
295 null,
296 strlen($data) + \TYPO3\CMS\Core\Cache\Backend\FileBackend::EXPIRYTIME_LENGTH,
297 9
298 );
299 $this->assertEquals('Tag1 Tag2', $retrievedData);
300 }
301
302 /**
303 * @test
304 */
305 public function setCacheDetectsAndLoadsAFrozenCache()
306 {
307 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
308 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
309
310 $data = 'some data' . microtime();
311 $entryIdentifier = 'BackendFileTest';
312
313 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
314 ->setMethods(['dummy'])
315 ->disableOriginalConstructor()
316 ->getMock();
317 $backend->setCacheDirectory('vfs://Foo/');
318 $backend->setCache($mockCache);
319
320 $backend->set($entryIdentifier, $data, ['Tag1', 'Tag2']);
321
322 $backend->freeze();
323
324 unset($backend);
325
326 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
327 ->setMethods(['dummy'])
328 ->disableOriginalConstructor()
329 ->getMock();
330 $backend->setCacheDirectory('vfs://Foo/');
331 $backend->setCache($mockCache);
332
333 $this->assertTrue($backend->isFrozen());
334 $this->assertEquals($data, $backend->get($entryIdentifier));
335 }
336
337 /**
338 * @test
339 */
340 public function getReturnsContentOfTheCorrectCacheFile()
341 {
342 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
343 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
344
345 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
346 ->setMethods(['setTag'])
347 ->disableOriginalConstructor()
348 ->getMock();
349 $backend->setCacheDirectory('vfs://Foo/');
350 $backend->setCache($mockCache);
351
352 $entryIdentifier = 'BackendFileTest';
353
354 $data = 'some data' . microtime();
355 $backend->set($entryIdentifier, $data, [], 500);
356
357 $data = 'some other data' . microtime();
358 $backend->set($entryIdentifier, $data, [], 100);
359
360 $loadedData = $backend->get($entryIdentifier);
361 $this->assertEquals($data, $loadedData);
362 }
363
364 /**
365 * @test
366 */
367 public function getReturnsFalseForExpiredEntries()
368 {
369 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
370 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
371
372 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
373 ->setMethods(['isCacheFileExpired'])
374 ->disableOriginalConstructor()
375 ->getMock();
376 $backend->expects($this->once())->method('isCacheFileExpired')->with('vfs://Foo/cache/data/UnitTestCache/ExpiredEntry')->will($this->returnValue(true));
377 $backend->setCacheDirectory('vfs://Foo/');
378 $backend->setCache($mockCache);
379
380 $this->assertFalse($backend->get('ExpiredEntry'));
381 }
382
383 /**
384 * @test
385 */
386 public function getDoesNotCheckIfAnEntryIsExpiredIfTheCacheIsFrozen()
387 {
388 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
389 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
390
391 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
392 ->setMethods(['isCacheFileExpired'])
393 ->disableOriginalConstructor()
394 ->getMock();
395 $backend->setCacheDirectory('vfs://Foo/');
396 $backend->setCache($mockCache);
397
398 $backend->expects($this->once())->method('isCacheFileExpired');
399
400 $backend->set('foo', 'some data');
401 $backend->freeze();
402 $this->assertEquals('some data', $backend->get('foo'));
403 $this->assertFalse($backend->get('bar'));
404 }
405
406 /**
407 * @test
408 */
409 public function hasReturnsTrueIfAnEntryExists()
410 {
411 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
412 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
413
414 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
415 ->setMethods(['dummy'])
416 ->disableOriginalConstructor()
417 ->getMock();
418 $backend->setCacheDirectory('vfs://Foo/');
419 $backend->setCache($mockCache);
420
421 $entryIdentifier = 'BackendFileTest';
422
423 $data = 'some data' . microtime();
424 $backend->set($entryIdentifier, $data);
425
426 $this->assertTrue($backend->has($entryIdentifier), 'has() did not return TRUE.');
427 $this->assertFalse($backend->has($entryIdentifier . 'Not'), 'has() did not return FALSE.');
428 }
429
430 /**
431 * @test
432 */
433 public function hasReturnsFalseForExpiredEntries()
434 {
435 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
436 ->setMethods(['isCacheFileExpired'])
437 ->disableOriginalConstructor()
438 ->getMock();
439 $backend->expects($this->exactly(2))->method('isCacheFileExpired')->will($this->onConsecutiveCalls(true, false));
440
441 $this->assertFalse($backend->has('foo'));
442 $this->assertTrue($backend->has('bar'));
443 }
444
445 /**
446 * @test
447 */
448 public function hasDoesNotCheckIfAnEntryIsExpiredIfTheCacheIsFrozen()
449 {
450 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
451 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
452
453 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
454 ->setMethods(['isCacheFileExpired'])
455 ->disableOriginalConstructor()
456 ->getMock();
457 $backend->setCacheDirectory('vfs://Foo/');
458 $backend->setCache($mockCache);
459
460 $backend->expects($this->once())->method('isCacheFileExpired'); // Indirectly called by freeze() -> get()
461
462 $backend->set('foo', 'some data');
463 $backend->freeze();
464 $this->assertTrue($backend->has('foo'));
465 $this->assertFalse($backend->has('bar'));
466 }
467
468 /**
469 * @test
470 */
471 public function removeReallyRemovesACacheEntry()
472 {
473 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
474 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
475
476 $data = 'some data' . microtime();
477 $entryIdentifier = 'BackendFileTest';
478 $pathAndFilename = 'vfs://Foo/cache/data/UnitTestCache/' . $entryIdentifier;
479
480 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
481 ->setMethods(['dummy'])
482 ->disableOriginalConstructor()
483 ->getMock();
484 $backend->setCacheDirectory('vfs://Foo/');
485 $backend->setCache($mockCache);
486
487 $backend->set($entryIdentifier, $data);
488 $this->assertFileExists($pathAndFilename);
489
490 $backend->remove($entryIdentifier);
491 $this->assertFileNotExists($pathAndFilename);
492 }
493
494 /**
495 */
496 public function invalidEntryIdentifiers()
497 {
498 return [
499 'trailing slash' => ['/myIdentifer'],
500 'trailing dot and slash' => ['./myIdentifer'],
501 'trailing two dots and slash' => ['../myIdentifier'],
502 'trailing with multiple dots and slashes' => ['.././../myIdentifier'],
503 'slash in middle part' => ['my/Identifier'],
504 'dot and slash in middle part' => ['my./Identifier'],
505 'two dots and slash in middle part' => ['my../Identifier'],
506 'multiple dots and slashes in middle part' => ['my.././../Identifier'],
507 'pending slash' => ['myIdentifier/'],
508 'pending dot and slash' => ['myIdentifier./'],
509 'pending dots and slash' => ['myIdentifier../'],
510 'pending multiple dots and slashes' => ['myIdentifier.././../'],
511 ];
512 }
513
514 /**
515 * @test
516 * @dataProvider invalidEntryIdentifiers
517 */
518 public function setThrowsExceptionForInvalidIdentifier($identifier)
519 {
520 $this->expectException(\InvalidArgumentException::class);
521 $this->expectExceptionCode(1282073032);
522
523 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
524 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
525
526 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
527 ->setMethods(['dummy'])
528 ->setConstructorArgs(['test'])
529 ->getMock();
530 $backend->setCacheDirectory('vfs://Foo/');
531 $backend->setCache($mockCache);
532
533 $backend->set($identifier, 'cache data', []);
534 }
535
536 /**
537 * @test
538 * @dataProvider invalidEntryIdentifiers
539 */
540 public function getThrowsExceptionForInvalidIdentifier($identifier)
541 {
542 $this->expectException(\InvalidArgumentException::class);
543 $this->expectExceptionCode(1282073033);
544
545 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
546 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
547
548 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
549 ->setMethods(['dummy'])
550 ->disableOriginalConstructor()
551 ->getMock();
552 $backend->setCacheDirectory('vfs://Foo/');
553 $backend->setCache($mockCache);
554
555 $backend->get($identifier);
556 }
557
558 /**
559 * @test
560 * @dataProvider invalidEntryIdentifiers
561 */
562 public function hasThrowsExceptionForInvalidIdentifier($identifier)
563 {
564 $this->expectException(\InvalidArgumentException::class);
565 $this->expectExceptionCode(1282073034);
566
567 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
568 ->setMethods(['dummy'])
569 ->disableOriginalConstructor()
570 ->getMock();
571
572 $backend->has($identifier);
573 }
574
575 /**
576 * @test
577 * @dataProvider invalidEntryIdentifiers
578 */
579 public function removeThrowsExceptionForInvalidIdentifier($identifier)
580 {
581 $this->expectException(\InvalidArgumentException::class);
582 $this->expectExceptionCode(1282073035);
583
584 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
585 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
586
587 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
588 ->setMethods(['dummy'])
589 ->disableOriginalConstructor()
590 ->getMock();
591 $backend->setCacheDirectory('vfs://Foo/');
592 $backend->setCache($mockCache);
593
594 $backend->remove($identifier);
595 }
596
597 /**
598 * @test
599 * @dataProvider invalidEntryIdentifiers
600 */
601 public function requireOnceThrowsExceptionForInvalidIdentifier($identifier)
602 {
603 $this->expectException(\InvalidArgumentException::class);
604 $this->expectExceptionCode(1282073036);
605
606 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
607 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
608
609 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
610 ->setMethods(['dummy'])
611 ->disableOriginalConstructor()
612 ->getMock();
613 $backend->setCacheDirectory('vfs://Foo/');
614 $backend->setCache($mockCache);
615
616 $backend->requireOnce($identifier);
617 }
618
619 /**
620 * @test
621 */
622 public function requireOnceIncludesAndReturnsResultOfIncludedPhpFile()
623 {
624 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
625 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
626
627 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
628 ->setMethods(['dummy'])
629 ->disableOriginalConstructor()
630 ->getMock();
631 $backend->setCacheDirectory('vfs://Foo/');
632 $backend->setCache($mockCache);
633
634 $entryIdentifier = 'SomePhpEntry';
635
636 $data = '<?php return "foo"; ?>';
637 $backend->set($entryIdentifier, $data);
638
639 $loadedData = $backend->requireOnce($entryIdentifier);
640 $this->assertEquals('foo', $loadedData);
641 }
642
643 /**
644 * @test
645 */
646 public function requireOnceDoesNotCheckExpiryTimeIfBackendIsFrozen()
647 {
648 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
649 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
650
651 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
652 ->setMethods(['isCacheFileExpired'])
653 ->disableOriginalConstructor()
654 ->getMock();
655 $backend->setCacheDirectory('vfs://Foo/');
656 $backend->setCache($mockCache);
657
658 $backend->expects($this->once())->method('isCacheFileExpired'); // Indirectly called by freeze() -> get()
659
660 $data = '<?php return "foo"; ?>';
661 $backend->set('FooEntry', $data);
662
663 $backend->freeze();
664
665 $loadedData = $backend->requireOnce('FooEntry');
666 $this->assertEquals('foo', $loadedData);
667 }
668
669 /**
670 * @test
671 */
672 public function findIdentifiersByTagFindsCacheEntriesWithSpecifiedTag()
673 {
674 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
675 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
676
677 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
678 ->setMethods(['dummy'])
679 ->disableOriginalConstructor()
680 ->getMock();
681 $backend->setCacheDirectory('vfs://Foo/');
682 $backend->setCache($mockCache);
683
684 $data = 'some data' . microtime();
685 $backend->set('BackendFileTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
686 $backend->set('BackendFileTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
687 $backend->set('BackendFileTest3', $data, ['UnitTestTag%test']);
688
689 $expectedEntry = 'BackendFileTest2';
690
691 $actualEntries = $backend->findIdentifiersByTag('UnitTestTag%special');
692 $this->assertInternalType('array', $actualEntries);
693 $this->assertEquals($expectedEntry, array_pop($actualEntries));
694 }
695
696 /**
697 * @test
698 */
699 public function findIdentifiersByTagDoesNotReturnExpiredEntries()
700 {
701 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
702 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
703
704 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
705 ->setMethods(['dummy'])
706 ->disableOriginalConstructor()
707 ->getMock();
708 $backend->setCacheDirectory('vfs://Foo/');
709 $backend->setCache($mockCache);
710
711 $data = 'some data';
712 $backend->set('BackendFileTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
713 $backend->set('BackendFileTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special'], -100);
714 $backend->set('BackendFileTest3', $data, ['UnitTestTag%test']);
715
716 $this->assertSame([], $backend->findIdentifiersByTag('UnitTestTag%special'));
717 $this->assertSame(['BackendFileTest1', 'BackendFileTest3'], $backend->findIdentifiersByTag('UnitTestTag%test'));
718 }
719
720 /**
721 * @test
722 */
723 public function flushRemovesAllCacheEntries()
724 {
725 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
726 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
727
728 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
729 ->setMethods(['dummy'])
730 ->disableOriginalConstructor()
731 ->getMock();
732 $backend->setCacheDirectory('vfs://Foo/');
733 $backend->setCache($mockCache);
734
735 $data = 'some data';
736 $backend->set('BackendFileTest1', $data);
737 $backend->set('BackendFileTest2', $data);
738
739 $this->assertFileExists('vfs://Foo/cache/data/UnitTestCache/BackendFileTest1');
740 $this->assertFileExists('vfs://Foo/cache/data/UnitTestCache/BackendFileTest2');
741
742 $backend->flush();
743
744 $this->assertFileNotExists('vfs://Foo/cache/data/UnitTestCache/BackendFileTest1');
745 $this->assertFileNotExists('vfs://Foo/cache/data/UnitTestCache/BackendFileTest2');
746 }
747
748 /**
749 * @test
750 */
751 public function flushCreatesCacheDirectoryAgain()
752 {
753 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
754 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
755
756 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
757 ->setMethods(['dummy'])
758 ->disableOriginalConstructor()
759 ->getMock();
760 $backend->setCacheDirectory('vfs://Foo/');
761 $backend->setCache($mockCache);
762
763 $backend->flush();
764 $this->assertFileExists('vfs://Foo/cache/data/UnitTestCache/');
765 }
766
767 /**
768 * @test
769 */
770 public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
771 {
772 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
773 ->setMethods(['findIdentifiersByTag', 'remove'])
774 ->disableOriginalConstructor()
775 ->getMock();
776
777 $backend->expects($this->once())->method('findIdentifiersByTag')->with('UnitTestTag%special')->will($this->returnValue(['foo', 'bar', 'baz']));
778 $backend->expects($this->at(1))->method('remove')->with('foo');
779 $backend->expects($this->at(2))->method('remove')->with('bar');
780 $backend->expects($this->at(3))->method('remove')->with('baz');
781
782 $backend->flushByTag('UnitTestTag%special');
783 }
784
785 /**
786 * @test
787 */
788 public function collectGarbageRemovesExpiredCacheEntries()
789 {
790 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
791 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
792
793 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
794 ->setMethods(['isCacheFileExpired'])
795 ->disableOriginalConstructor()
796 ->getMock();
797 $backend->expects($this->exactly(2))->method('isCacheFileExpired')->will($this->onConsecutiveCalls(true, false));
798 $backend->setCacheDirectory('vfs://Foo/');
799 $backend->setCache($mockCache);
800
801 $data = 'some data';
802 $backend->set('BackendFileTest1', $data);
803 $backend->set('BackendFileTest2', $data);
804
805 $this->assertFileExists('vfs://Foo/cache/data/UnitTestCache/BackendFileTest1');
806 $this->assertFileExists('vfs://Foo/cache/data/UnitTestCache/BackendFileTest2');
807
808 $backend->collectGarbage();
809 $this->assertFileNotExists('vfs://Foo/cache/data/UnitTestCache/BackendFileTest1');
810 $this->assertFileExists('vfs://Foo/cache/data/UnitTestCache/BackendFileTest2');
811 }
812
813 /**
814 * @test
815 */
816 public function flushUnfreezesTheCache()
817 {
818 $mockCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
819 $mockCache->expects($this->atLeastOnce())->method('getIdentifier')->will($this->returnValue('UnitTestCache'));
820
821 $backend = $this->getMockBuilder(\TYPO3\CMS\Core\Cache\Backend\FileBackend::class)
822 ->setMethods(['dummy'])
823 ->disableOriginalConstructor()
824 ->getMock();
825 $backend->setCacheDirectory('vfs://Foo/');
826 $backend->setCache($mockCache);
827
828 $backend->freeze();
829
830 $this->assertTrue($backend->isFrozen());
831 $backend->flush();
832 $this->assertFalse($backend->isFrozen());
833 }
834 }