2 namespace TYPO3\CMS\Core\Tests\Functional\Cache\Backend
;
5 * This file is part of the TYPO3 CMS project.
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.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
16 use TYPO3\CMS\Core\Cache\Backend\RedisBackend
;
17 use TYPO3\CMS\Core\Cache\Exception\InvalidDataException
;
18 use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
;
19 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase
;
22 * Test case for the cache to redis backend
25 * These functional tests use and flush redis database numbers 0 and 1 on the
26 * redis host specified by environment variable typo3RedisHost
28 class RedisBackendTest
extends FunctionalTestCase
33 protected function setUp()
35 // Note this functional does NOT call parent::setUp() since it does
36 // not need a full blown instance and database
37 if (!extension_loaded('redis')) {
38 $this->markTestSkipped('redis extension was not available');
40 if (!getenv('typo3TestingRedisHost')) {
41 $this->markTestSkipped('environment variable "typo3TestingRedisHost" must be set to run this test');
43 // Note we assume that if that typo3TestingRedisHost env is set, we can use that for testing,
44 // there is no test to see if the daemon is actually up and running. Tests will fail if env
45 // is set but daemon is down.
49 * Sets up the redis cache backend used for testing
51 protected function setUpSubject(array $backendOptions = []): RedisBackend
53 // We know this env is set, otherwise setUp() would skip the tests
54 $backendOptions['hostname'] = getenv('typo3TestingRedisHost');
55 // If typo3TestingRedisPort env is set, use it, otherwise fall back to standard port
56 $env = getenv('typo3TestingRedisPort');
57 $backendOptions['port'] = is_string($env) ?
(int)$env : 6379;
59 $frontendProphecy = $this->prophesize(FrontendInterface
::class);
60 $frontendProphecy->getIdentifier()->willReturn('cache_pages');
62 $subject = new RedisBackend('Testing', $backendOptions);
63 $subject->setCache($frontendProphecy->reveal());
64 $subject->initializeObject();
70 * Sets up a test-internal redis connection to check implementation details
72 protected function setUpRedis(): \Redis
74 // We know this env is set, otherwise setUp() would skip the tests
75 $redisHost = getenv('typo3TestingRedisHost');
76 // If typo3TestingRedisPort env is set, use it, otherwise fall back to standard port
77 $env = getenv('typo3TestingRedisPort');
78 $redisPort = is_string($env) ?
(int)$env : 6379;
80 $redis = new \
Redis();
81 $redis->connect($redisHost, $redisPort);
88 public function setDatabaseThrowsExceptionIfGivenDatabaseNumberIsNotAnInteger()
90 $this->expectException(\InvalidArgumentException
::class);
91 $this->expectExceptionCode(1279763057);
93 $this->setUpSubject(['database' => 'foo']);
99 public function setDatabaseThrowsExceptionIfGivenDatabaseNumberIsNegative()
101 $this->expectException(\InvalidArgumentException
::class);
102 $this->expectExceptionCode(1279763534);
104 $this->setUpSubject(['database' => -1]);
110 public function setCompressionThrowsExceptionIfCompressionParameterIsNotOfTypeBoolean()
112 $this->expectException(\InvalidArgumentException
::class);
113 $this->expectExceptionCode(1289679153);
115 $this->setUpSubject(['compression' => 'foo']);
121 public function setCompressionLevelThrowsExceptionIfCompressionLevelIsNotInteger()
123 $this->expectException(\InvalidArgumentException
::class);
124 $this->expectExceptionCode(1289679154);
126 $this->setUpSubject(['compressionLevel' => 'foo']);
132 public function setCompressionLevelThrowsExceptionIfCompressionLevelIsNotBetweenMinusOneAndNine()
134 $this->expectException(\InvalidArgumentException
::class);
135 $this->expectExceptionCode(1289679155);
137 $this->setUpSubject(['compressionLevel' => 11]);
143 public function setConnectionTimeoutThrowsExceptionIfConnectionTimeoutIsNotInteger()
145 $this->expectException(\InvalidArgumentException
::class);
146 $this->expectExceptionCode(1487849315);
148 $this->setUpSubject(['connectionTimeout' => 'foo']);
154 public function setConnectionTimeoutThrowsExceptionIfConnectionTimeoutIsNegative()
156 $this->expectException(\InvalidArgumentException
::class);
157 $this->expectExceptionCode(1487849326);
159 $this->setUpSubject(['connectionTimeout' => -1]);
165 public function setThrowsExceptionIfIdentifierIsNotAString()
167 $this->expectException(\InvalidArgumentException
::class);
168 $this->expectExceptionCode(1377006651);
170 $subject = $this->setUpSubject();
171 $subject->set([], 'data');
177 public function setThrowsExceptionIfDataIsNotAString()
179 $this->expectException(InvalidDataException
::class);
180 $this->expectExceptionCode(1279469941);
182 $subject = $this->setUpSubject();
183 $subject->set($this->getUniqueId('identifier'), []);
189 public function setThrowsExceptionIfLifetimeIsNegative()
191 $this->expectException(\InvalidArgumentException
::class);
192 $this->expectExceptionCode(1279487573);
194 $subject = $this->setUpSubject();
195 $subject->set($this->getUniqueId('identifier'), 'data', [], -42);
201 public function setThrowsExceptionIfLifetimeIsNotNullOrAnInteger()
203 $this->expectException(\InvalidArgumentException
::class);
204 $this->expectExceptionCode(1279488008);
206 $subject = $this->setUpSubject();
207 $subject->set($this->getUniqueId('identifier'), 'data', [], []);
213 public function setStoresEntriesInSelectedDatabase()
215 $redis = $this->setUpRedis();
217 $subject = $this->setUpSubject(['database' => 1]);
218 $identifier = $this->getUniqueId('identifier');
219 $subject->set($identifier, 'data');
220 $result = $redis->exists('identData:' . $identifier);
221 if (is_int($result)) {
222 // Since 3.1.4 of phpredis/phpredis the return types has been changed
223 $result = (bool)$result;
225 $this->assertTrue($result);
231 public function setSavesStringDataTypeForIdentifierToDataEntry()
233 $subject = $this->setUpSubject();
234 $redis = $this->setUpRedis();
235 $identifier = $this->getUniqueId('identifier');
236 $subject->set($identifier, 'data');
237 $this->assertSame(\Redis
::REDIS_STRING
, $redis->type('identData:' . $identifier));
243 public function setSavesEntryWithDefaultLifeTime()
245 $subject = $this->setUpSubject();
246 $redis = $this->setUpRedis();
247 $identifier = $this->getUniqueId('identifier');
248 $defaultLifetime = 42;
249 $subject->setDefaultLifetime($defaultLifetime);
250 $subject->set($identifier, 'data');
251 $lifetimeRegisteredInBackend = $redis->ttl('identData:' . $identifier);
252 $this->assertSame($defaultLifetime, $lifetimeRegisteredInBackend);
258 public function setSavesEntryWithSpecifiedLifeTime()
260 $subject = $this->setUpSubject();
261 $redis = $this->setUpRedis();
262 $identifier = $this->getUniqueId('identifier');
264 $subject->set($identifier, 'data', [], $lifetime);
265 $lifetimeRegisteredInBackend = $redis->ttl('identData:' . $identifier);
266 $this->assertSame($lifetime, $lifetimeRegisteredInBackend);
272 public function setSavesEntryWithUnlimitedLifeTime()
274 $subject = $this->setUpSubject();
275 $redis = $this->setUpRedis();
276 $identifier = $this->getUniqueId('identifier');
277 $subject->set($identifier, 'data', [], 0);
278 $lifetimeRegisteredInBackend = $redis->ttl('identData:' . $identifier);
279 $this->assertSame(31536000, $lifetimeRegisteredInBackend);
285 public function setOverwritesExistingEntryWithNewData()
287 $subject = $this->setUpSubject();
289 $identifier = $this->getUniqueId('identifier');
290 $subject->set($identifier, $data);
291 $otherData = 'data 2';
292 $subject->set($identifier, $otherData);
293 $fetchedData = $subject->get($identifier);
294 $this->assertSame($otherData, $fetchedData);
300 public function setOverwritesExistingEntryWithSpecifiedLifetime()
302 $subject = $this->setUpSubject();
303 $redis = $this->setUpRedis();
305 $identifier = $this->getUniqueId('identifier');
306 $subject->set($identifier, $data);
308 $subject->set($identifier, $data, [], $lifetime);
309 $lifetimeRegisteredInBackend = $redis->ttl('identData:' . $identifier);
310 $this->assertSame($lifetime, $lifetimeRegisteredInBackend);
316 public function setOverwritesExistingEntryWithNewDefaultLifetime()
318 $subject = $this->setUpSubject();
319 $redis = $this->setUpRedis();
321 $identifier = $this->getUniqueId('identifier');
323 $subject->set($identifier, $data, [], $lifetime);
324 $newDefaultLifetime = 43;
325 $subject->setDefaultLifetime($newDefaultLifetime);
326 $subject->set($identifier, $data, [], $newDefaultLifetime);
327 $lifetimeRegisteredInBackend = $redis->ttl('identData:' . $identifier);
328 $this->assertSame($newDefaultLifetime, $lifetimeRegisteredInBackend);
334 public function setOverwritesExistingEntryWithNewUnlimitedLifetime()
336 $subject = $this->setUpSubject();
337 $redis = $this->setUpRedis();
339 $identifier = $this->getUniqueId('identifier');
341 $subject->set($identifier, $data, [], $lifetime);
342 $subject->set($identifier, $data, [], 0);
343 $lifetimeRegisteredInBackend = $redis->ttl('identData:' . $identifier);
344 $this->assertSame(31536000, $lifetimeRegisteredInBackend);
350 public function setSavesSetDataTypeForIdentifierToTagsSet()
352 $subject = $this->setUpSubject();
353 $redis = $this->setUpRedis();
354 $identifier = $this->getUniqueId('identifier');
355 $subject->set($identifier, 'data', ['tag']);
356 $this->assertSame(\Redis
::REDIS_SET
, $redis->type('identTags:' . $identifier));
362 public function setSavesSpecifiedTagsInIdentifierToTagsSet()
364 $subject = $this->setUpSubject();
365 $redis = $this->setUpRedis();
366 $identifier = $this->getUniqueId('identifier');
367 $tags = ['thatTag', 'thisTag'];
368 $subject->set($identifier, 'data', $tags);
369 $savedTags = $redis->sMembers('identTags:' . $identifier);
371 $this->assertSame($tags, $savedTags);
377 public function setRemovesAllPreviouslySetTagsFromIdentifierToTagsSet()
379 $subject = $this->setUpSubject();
380 $redis = $this->setUpRedis();
381 $identifier = $this->getUniqueId('identifier');
382 $tags = ['fooTag', 'barTag'];
383 $subject->set($identifier, 'data', $tags);
384 $subject->set($identifier, 'data', []);
385 $this->assertSame([], $redis->sMembers('identTags:' . $identifier));
391 public function setRemovesMultiplePreviouslySetTagsFromIdentifierToTagsSet()
393 $subject = $this->setUpSubject();
394 $redis = $this->setUpRedis();
395 $identifier = $this->getUniqueId('identifier');
396 $firstTagSet = ['tag1', 'tag2', 'tag3', 'tag4'];
397 $subject->set($identifier, 'data', $firstTagSet);
398 $secondTagSet = ['tag1', 'tag3'];
399 $subject->set($identifier, 'data', $secondTagSet);
400 $actualTagSet = $redis->sMembers('identTags:' . $identifier);
402 $this->assertSame($secondTagSet, $actualTagSet);
408 public function setSavesSetDataTypeForTagToIdentifiersSet()
410 $subject = $this->setUpSubject();
411 $redis = $this->setUpRedis();
412 $identifier = $this->getUniqueId('identifier');
414 $subject->set($identifier, 'data', [$tag]);
415 $this->assertSame(\Redis
::REDIS_SET
, $redis->type('tagIdents:' . $tag));
421 public function setSavesIdentifierInTagToIdentifiersSetOfSpecifiedTag()
423 $subject = $this->setUpSubject();
424 $redis = $this->setUpRedis();
425 $identifier = $this->getUniqueId('identifier');
427 $subject->set($identifier, 'data', [$tag]);
428 $savedTagToIdentifiersMemberArray = $redis->sMembers('tagIdents:' . $tag);
429 $this->assertSame([$identifier], $savedTagToIdentifiersMemberArray);
435 public function setAppendsSecondIdentifierInTagToIdentifiersEntry()
437 $subject = $this->setUpSubject();
438 $redis = $this->setUpRedis();
439 $firstIdentifier = $this->getUniqueId('identifier1-');
441 $subject->set($firstIdentifier, 'data', [$tag]);
442 $secondIdentifier = $this->getUniqueId('identifier2-');
443 $subject->set($secondIdentifier, 'data', [$tag]);
444 $savedTagToIdentifiersMemberArray = $redis->sMembers('tagIdents:' . $tag);
445 sort($savedTagToIdentifiersMemberArray);
446 $identifierArray = [$firstIdentifier, $secondIdentifier];
447 sort($identifierArray);
448 $this->assertSame([$firstIdentifier, $secondIdentifier], $savedTagToIdentifiersMemberArray);
454 public function setRemovesIdentifierFromTagToIdentifiersEntryIfTagIsOmittedOnConsecutiveSet()
456 $subject = $this->setUpSubject();
457 $redis = $this->setUpRedis();
458 $identifier = $this->getUniqueId('identifier');
460 $subject->set($identifier, 'data', [$tag]);
461 $subject->set($identifier, 'data', []);
462 $savedTagToIdentifiersMemberArray = $redis->sMembers('tagIdents:' . $tag);
463 $this->assertSame([], $savedTagToIdentifiersMemberArray);
469 public function setAddsIdentifierInTagToIdentifiersEntryIfTagIsAddedOnConsecutiveSet()
471 $subject = $this->setUpSubject();
472 $redis = $this->setUpRedis();
473 $identifier = $this->getUniqueId('identifier');
474 $subject->set($identifier, 'data');
476 $subject->set($identifier, 'data', [$tag]);
477 $savedTagToIdentifiersMemberArray = $redis->sMembers('tagIdents:' . $tag);
478 $this->assertSame([$identifier], $savedTagToIdentifiersMemberArray);
484 public function setSavesCompressedDataWithEnabledCompression()
486 $subject = $this->setUpSubject([
487 'compression' => true
489 $redis = $this->setUpRedis();
490 $identifier = $this->getUniqueId('identifier');
491 $data = 'some data ' . microtime();
492 $subject->set($identifier, $data);
493 $uncompresedStoredData = '';
495 $uncompresedStoredData = @gzuncompress
($redis->get('identData:' . $identifier));
496 } catch (\Exception
$e) {
498 $this->assertEquals($data, $uncompresedStoredData, 'Original and compressed data don\'t match');
504 public function setSavesPlaintextDataWithEnabledCompressionAndCompressionLevel0()
506 $subject = $this->setUpSubject([
507 'compression' => true,
508 'compressionLevel' => 0
510 $redis = $this->setUpRedis();
511 $identifier = $this->getUniqueId('identifier');
512 $data = 'some data ' . microtime();
513 $subject->set($identifier, $data);
514 $this->assertGreaterThan(0, substr_count($redis->get('identData:' . $identifier), $data), 'Plaintext data not found');
520 public function hasThrowsExceptionIfIdentifierIsNotAString()
522 $this->expectException(\InvalidArgumentException
::class);
523 $this->expectExceptionCode(1377006653);
525 $subject = $this->setUpSubject();
532 public function hasReturnsFalseForNotExistingEntry()
534 $subject = $this->setUpSubject();
535 $identifier = $this->getUniqueId('identifier');
536 $this->assertFalse($subject->has($identifier));
542 public function hasReturnsTrueForPreviouslySetEntry()
544 $subject = $this->setUpSubject();
545 $identifier = $this->getUniqueId('identifier');
546 $subject->set($identifier, 'data');
547 $this->assertTrue($subject->has($identifier));
553 public function getThrowsExceptionIfIdentifierIsNotAString()
555 $this->expectException(\InvalidArgumentException
::class);
556 //@todo Add exception code with redis extension
558 $subject = $this->setUpSubject();
565 public function getReturnsPreviouslyCompressedSetEntry()
567 $subject = $this->setUpSubject([
568 'compression' => true
571 $identifier = $this->getUniqueId('identifier');
572 $subject->set($identifier, $data);
573 $fetchedData = $subject->get($identifier);
574 $this->assertSame($data, $fetchedData);
580 public function getReturnsPreviouslySetEntry()
582 $subject = $this->setUpSubject();
584 $identifier = $this->getUniqueId('identifier');
585 $subject->set($identifier, $data);
586 $fetchedData = $subject->get($identifier);
587 $this->assertSame($data, $fetchedData);
593 public function removeThrowsExceptionIfIdentifierIsNotAString()
595 $this->expectException(\InvalidArgumentException
::class);
596 $this->expectExceptionCode(1377006654);
598 $subject = $this->setUpSubject();
599 $subject->remove([]);
605 public function removeReturnsFalseIfNoEntryWasDeleted()
607 $subject = $this->setUpSubject();
608 $this->assertFalse($subject->remove($this->getUniqueId('identifier')));
614 public function removeReturnsTrueIfAnEntryWasDeleted()
616 $subject = $this->setUpSubject();
617 $identifier = $this->getUniqueId('identifier');
618 $subject->set($identifier, 'data');
619 $this->assertTrue($subject->remove($identifier));
625 public function removeDeletesEntryFromCache()
627 $subject = $this->setUpSubject();
628 $identifier = $this->getUniqueId('identifier');
629 $subject->set($identifier, 'data');
630 $subject->remove($identifier);
631 $this->assertFalse($subject->has($identifier));
637 public function removeDeletesIdentifierToTagEntry()
639 $subject = $this->setUpSubject();
640 $redis = $this->setUpRedis();
641 $identifier = $this->getUniqueId('identifier');
643 $subject->set($identifier, 'data', [$tag]);
644 $subject->remove($identifier);
645 $result = $redis->exists('identTags:' . $identifier);
646 if (is_int($result)) {
647 // Since 3.1.4 of phpredis/phpredis the return types has been changed
648 $result = (bool)$result;
650 $this->assertFalse($result);
656 public function removeDeletesIdentifierFromTagToIdentifiersSet()
658 $subject = $this->setUpSubject();
659 $redis = $this->setUpRedis();
660 $identifier = $this->getUniqueId('identifier');
662 $subject->set($identifier, 'data', [$tag]);
663 $subject->remove($identifier);
664 $tagToIdentifiersMemberArray = $redis->sMembers('tagIdents:' . $tag);
665 $this->assertSame([], $tagToIdentifiersMemberArray);
671 public function removeDeletesIdentifierFromTagToIdentifiersSetWithMultipleEntries()
673 $subject = $this->setUpSubject();
674 $redis = $this->setUpRedis();
675 $firstIdentifier = $this->getUniqueId('identifier');
676 $secondIdentifier = $this->getUniqueId('identifier');
678 $subject->set($firstIdentifier, 'data', [$tag]);
679 $subject->set($secondIdentifier, 'data', [$tag]);
680 $subject->remove($firstIdentifier);
681 $tagToIdentifiersMemberArray = $redis->sMembers('tagIdents:' . $tag);
682 $this->assertSame([$secondIdentifier], $tagToIdentifiersMemberArray);
688 public function findIdentifiersByTagThrowsExceptionIfTagIsNotAString()
690 $this->expectException(\InvalidArgumentException
::class);
691 $this->expectExceptionCode(1377006655);
693 $subject = $this->setUpSubject();
694 $subject->findIdentifiersByTag([]);
700 public function findIdentifiersByTagReturnsEmptyArrayForNotExistingTag()
702 $subject = $this->setUpSubject();
703 $this->assertSame([], $subject->findIdentifiersByTag('thisTag'));
709 public function findIdentifiersByTagReturnsAllIdentifiersTagedWithSpecifiedTag()
711 $subject = $this->setUpSubject();
712 $firstIdentifier = $this->getUniqueId('identifier1-');
713 $secondIdentifier = $this->getUniqueId('identifier2-');
714 $thirdIdentifier = $this->getUniqueId('identifier3-');
715 $tagsForFirstIdentifier = ['thisTag'];
716 $tagsForSecondIdentifier = ['thatTag'];
717 $tagsForThirdIdentifier = ['thisTag', 'thatTag'];
718 $subject->set($firstIdentifier, 'data', $tagsForFirstIdentifier);
719 $subject->set($secondIdentifier, 'data', $tagsForSecondIdentifier);
720 $subject->set($thirdIdentifier, 'data', $tagsForThirdIdentifier);
721 $expectedResult = [$firstIdentifier, $thirdIdentifier];
722 $actualResult = $subject->findIdentifiersByTag('thisTag');
724 $this->assertSame($expectedResult, $actualResult);
730 public function flushRemovesAllEntriesFromCache()
732 $subject = $this->setUpSubject();
733 $redis = $this->setUpRedis();
734 $identifier = $this->getUniqueId('identifier');
735 $subject->set($identifier, 'data');
737 $this->assertSame([], $redis->getKeys('*'));
743 public function flushByTagThrowsExceptionIfTagIsNotAString()
745 $this->expectException(\InvalidArgumentException
::class);
746 $this->expectExceptionCode(1377006656);
748 $subject = $this->setUpSubject();
749 $subject->flushByTag([]);
755 public function flushByTagRemovesEntriesTaggedWithSpecifiedTag()
757 $subject = $this->setUpSubject();
758 $identifier = $this->getUniqueId('identifier');
759 $subject->set($identifier . 'A', 'data', ['tag1']);
760 $subject->set($identifier . 'B', 'data', ['tag2']);
761 $subject->set($identifier . 'C', 'data', ['tag1', 'tag2']);
762 $subject->flushByTag('tag1');
763 $expectedResult = [false, true, false];
765 $subject->has($identifier . 'A'),
766 $subject->has($identifier . 'B'),
767 $subject->has($identifier . 'C')
769 $this->assertSame($expectedResult, $actualResult);
775 public function flushByTagsRemovesEntriesTaggedWithSpecifiedTags()
777 $subject = $this->setUpSubject();
778 $identifier = $this->getUniqueId('identifier');
779 $subject->set($identifier . 'A', 'data', ['tag1']);
780 $subject->set($identifier . 'B', 'data', ['tag2']);
781 $subject->set($identifier . 'C', 'data', ['tag1', 'tag2']);
782 $subject->set($identifier . 'D', 'data', ['tag3']);
783 $subject->flushByTags(['tag1', 'tag2']);
784 $expectedResult = [false, false, false, true];
786 $subject->has($identifier . 'A'),
787 $subject->has($identifier . 'B'),
788 $subject->has($identifier . 'C'),
789 $subject->has($identifier . 'D')
791 $this->assertSame($expectedResult, $actualResult);
797 public function flushByTagRemovesTemporarySet()
799 $subject = $this->setUpSubject();
800 $redis = $this->setUpRedis();
801 $identifier = $this->getUniqueId('identifier');
802 $subject->set($identifier . 'A', 'data', ['tag1']);
803 $subject->set($identifier . 'C', 'data', ['tag1', 'tag2']);
804 $subject->flushByTag('tag1');
805 $this->assertSame([], $redis->getKeys('temp*'));
811 public function flushByTagRemovesIdentifierToTagsSetOfEntryTaggedWithGivenTag()
813 $subject = $this->setUpSubject();
814 $redis = $this->setUpRedis();
815 $identifier = $this->getUniqueId('identifier');
817 $subject->set($identifier, 'data', [$tag]);
818 $subject->flushByTag($tag);
819 $result = $redis->exists('identTags:' . $identifier);
820 if (is_int($result)) {
821 // Since 3.1.4 of phpredis/phpredis the return types has been changed
822 $result = (bool)$result;
824 $this->assertFalse($result);
830 public function flushByTagDoesNotRemoveIdentifierToTagsSetOfUnrelatedEntry()
832 $subject = $this->setUpSubject();
833 $redis = $this->setUpRedis();
834 $identifierToBeRemoved = $this->getUniqueId('identifier');
835 $tagToRemove = 'tag1';
836 $subject->set($identifierToBeRemoved, 'data', [$tagToRemove]);
837 $identifierNotToBeRemoved = $this->getUniqueId('identifier');
838 $tagNotToRemove = 'tag2';
839 $subject->set($identifierNotToBeRemoved, 'data', [$tagNotToRemove]);
840 $subject->flushByTag($tagToRemove);
841 $this->assertSame([$tagNotToRemove], $redis->sMembers('identTags:' . $identifierNotToBeRemoved));
847 public function flushByTagRemovesTagToIdentifiersSetOfGivenTag()
849 $subject = $this->setUpSubject();
850 $redis = $this->setUpRedis();
851 $identifier = $this->getUniqueId('identifier');
853 $subject->set($identifier, 'data', [$tag]);
854 $subject->flushByTag($tag);
855 $result = $redis->exists('tagIdents:' . $tag);
856 if (is_int($result)) {
857 // Since 3.1.4 of phpredis/phpredis the return types has been changed
858 $result = (bool)$result;
860 $this->assertFalse($result);
866 public function flushByTagRemovesIdentifiersTaggedWithGivenTagFromTagToIdentifiersSets()
868 $subject = $this->setUpSubject();
869 $redis = $this->setUpRedis();
870 $identifier = $this->getUniqueId('identifier');
871 $subject->set($identifier . 'A', 'data', ['tag1', 'tag2']);
872 $subject->set($identifier . 'B', 'data', ['tag1', 'tag2']);
873 $subject->set($identifier . 'C', 'data', ['tag2']);
874 $subject->flushByTag('tag1');
875 $this->assertSame([$identifier . 'C'], $redis->sMembers('tagIdents:tag2'));
881 public function collectGarbageDoesNotRemoveNotExpiredIdentifierToDataEntry()
883 $subject = $this->setUpSubject();
884 $redis = $this->setUpRedis();
885 $identifier = $this->getUniqueId('identifier');
886 $subject->set($identifier . 'A', 'data', ['tag']);
887 $subject->set($identifier . 'B', 'data', ['tag']);
888 $redis->delete('identData:' . $identifier . 'A');
889 $subject->collectGarbage();
890 $result = $redis->exists('identData:' . $identifier . 'B');
891 if (is_int($result)) {
892 // Since 3.1.4 of phpredis/phpredis the return types has been changed
893 $result = (bool)$result;
895 $this->assertTrue($result);
901 public function collectGarbageRemovesLeftOverIdentifierToTagsSet()
903 $subject = $this->setUpSubject();
904 $redis = $this->setUpRedis();
905 $identifier = $this->getUniqueId('identifier');
906 $subject->set($identifier . 'A', 'data', ['tag']);
907 $subject->set($identifier . 'B', 'data', ['tag']);
908 $redis->delete('identData:' . $identifier . 'A');
909 $subject->collectGarbage();
910 $expectedResult = [false, true];
911 $resultA = $redis->exists('identTags:' . $identifier . 'A');
912 $resultB = $redis->exists('identTags:' . $identifier . 'B');
913 if (is_int($resultA)) {
914 // Since 3.1.4 of phpredis/phpredis the return types has been changed
915 $resultA = (bool)$resultA;
917 if (is_int($resultB)) {
918 // Since 3.1.4 of phpredis/phpredis the return types has been changed
919 $resultB = (bool)$resultB;
925 $this->assertSame($expectedResult, $actualResult);
931 public function collectGarbageRemovesExpiredIdentifierFromTagsToIdentifierSet()
933 $subject = $this->setUpSubject();
934 $redis = $this->setUpRedis();
935 $identifier = $this->getUniqueId('identifier');
936 $subject->set($identifier . 'A', 'data', ['tag1', 'tag2']);
937 $subject->set($identifier . 'B', 'data', ['tag2']);
938 $redis->delete('identData:' . $identifier . 'A');
939 $subject->collectGarbage();
945 $redis->sMembers('tagIdents:tag1'),
946 $redis->sMembers('tagIdents:tag2')
948 $this->assertSame($expectedResult, $actualResult);