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