TYPO3 CMS  TYPO3_7-6
RedisBackendTest.php
Go to the documentation of this file.
1 <?php
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 
18 
34 {
40  protected $backend = null;
41 
47  protected $redis = null;
48 
52  protected function setUp()
53  {
54  if (!extension_loaded('redis')) {
55  $this->markTestSkipped('redis extension was not available');
56  }
57  if (!getenv('typo3TestingRedisHost')) {
58  $this->markTestSkipped('environment variable "typo3TestingRedisHost" must be set to run this test');
59  }
60  // Note we assume that if that typo3TestingRedisHost env is set, we can use that for testing,
61  // there is no test to see if the daemon is actually up and running. Tests will fail if env
62  // is set but daemon is down.
63  }
64 
70  protected function setUpBackend(array $backendOptions = [])
71  {
72  $mockCache = $this->getMock(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface::class, [], [], '', false);
73  $mockCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('TestCache'));
74  // We know this env is set, otherwise setUp() would skip the tests
75  $backendOptions['hostname'] = getenv('typo3TestingRedisHost');
76  // If typo3TestingRedisPort env is set, use it, otherwise fall back to standard port
77  $env = getenv('typo3TestingRedisPort');
78  $backendOptions['port'] = is_string($env) ? (int)$env : 6379;
79  $this->backend = new \TYPO3\CMS\Core\Cache\Backend\RedisBackend('Testing', $backendOptions);
80  $this->backend->setCache($mockCache);
81  $this->backend->initializeObject();
82  }
83 
87  protected function setUpRedis()
88  {
89  // We know this env is set, otherwise setUp() would skip the tests
90  $redisHost = getenv('typo3TestingRedisHost');
91  // If typo3TestingRedisPort env is set, use it, otherwise fall back to standard port
92  $env = getenv('typo3TestingRedisPort');
93  $redisPort = is_string($env) ? (int)$env : 6379;
94 
95  $this->redis = new \Redis();
96  $this->redis->connect($redisHost, $redisPort);
97  }
98 
102  protected function tearDown()
103  {
104  if ($this->backend instanceof \TYPO3\CMS\Core\Cache\Backend\RedisBackend) {
105  $this->backend->flush();
106  }
107  parent::tearDown();
108  }
109 
114  {
115  try {
116  $this->setUpBackend(['database' => 1]);
117  } catch (Exception $e) {
118  $this->assertTrue();
119  }
120  }
121 
127  {
128  $this->setUpBackend(['database' => 'foo']);
129  }
130 
136  {
137  $this->setUpBackend(['database' => -1]);
138  }
139 
145  {
146  $this->setUpBackend(['compression' => 'foo']);
147  }
148 
154  {
155  $this->setUpBackend(['compressionLevel' => 'foo']);
156  }
157 
163  {
164  $this->setUpBackend(['compressionLevel' => 11]);
165  }
166 
172  {
173  $this->setUpBackend();
174  $this->backend->set([], 'data');
175  }
176 
182  {
183  $this->setUpBackend();
184  $this->backend->set($this->getUniqueId('identifier'), []);
185  }
186 
192  {
193  $this->setUpBackend();
194  $this->backend->set($this->getUniqueId('identifier'), 'data', [], -42);
195  }
196 
202  {
203  $this->setUpBackend();
204  $this->backend->set($this->getUniqueId('identifier'), 'data', [], []);
205  }
206 
211  {
212  $this->setUpRedis();
213  $this->redis->select(1);
214  $this->setUpBackend(['database' => 1]);
215  $identifier = $this->getUniqueId('identifier');
216  $this->backend->set($identifier, 'data');
217  $result = $this->redis->exists('identData:' . $identifier);
218  if (is_int($result)) {
219  // Since 3.1.4 of phpredis/phpredis the return types has been changed
220  $result = (bool)$result;
221  }
222  $this->assertTrue($result);
223  }
224 
229  {
230  $this->setUpBackend();
231  $this->setUpRedis();
232  $identifier = $this->getUniqueId('identifier');
233  $this->backend->set($identifier, 'data');
234  $this->assertSame(\Redis::REDIS_STRING, $this->redis->type('identData:' . $identifier));
235  }
236 
241  {
242  $this->setUpBackend();
243  $this->setUpRedis();
244  $identifier = $this->getUniqueId('identifier');
245  $defaultLifetime = 42;
246  $this->backend->setDefaultLifetime($defaultLifetime);
247  $this->backend->set($identifier, 'data');
248  $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
249  $this->assertSame($defaultLifetime, $lifetimeRegisteredInBackend);
250  }
251 
256  {
257  $this->setUpBackend();
258  $this->setUpRedis();
259  $identifier = $this->getUniqueId('identifier');
260  $lifetime = 43;
261  $this->backend->set($identifier, 'data', [], $lifetime);
262  $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
263  $this->assertSame($lifetime, $lifetimeRegisteredInBackend);
264  }
265 
270  {
271  $this->setUpBackend();
272  $this->setUpRedis();
273  $identifier = $this->getUniqueId('identifier');
274  $this->backend->set($identifier, 'data', [], 0);
275  $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
276  $this->assertSame(31536000, $lifetimeRegisteredInBackend);
277  }
278 
283  {
284  $this->setUpBackend();
285  $data = 'data 1';
286  $identifier = $this->getUniqueId('identifier');
287  $this->backend->set($identifier, $data);
288  $otherData = 'data 2';
289  $this->backend->set($identifier, $otherData);
290  $fetchedData = $this->backend->get($identifier);
291  $this->assertSame($otherData, $fetchedData);
292  }
293 
298  {
299  $this->setUpBackend();
300  $this->setUpRedis();
301  $data = 'data';
302  $identifier = $this->getUniqueId('identifier');
303  $this->backend->set($identifier, $data);
304  $lifetime = 42;
305  $this->backend->set($identifier, $data, [], $lifetime);
306  $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
307  $this->assertSame($lifetime, $lifetimeRegisteredInBackend);
308  }
309 
314  {
315  $this->setUpBackend();
316  $this->setUpRedis();
317  $data = 'data';
318  $identifier = $this->getUniqueId('identifier');
319  $lifetime = 42;
320  $this->backend->set($identifier, $data, [], $lifetime);
321  $newDefaultLifetime = 43;
322  $this->backend->setDefaultLifetime($newDefaultLifetime);
323  $this->backend->set($identifier, $data, [], $newDefaultLifetime);
324  $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
325  $this->assertSame($newDefaultLifetime, $lifetimeRegisteredInBackend);
326  }
327 
332  {
333  $this->setUpBackend();
334  $this->setUpRedis();
335  $data = 'data';
336  $identifier = $this->getUniqueId('identifier');
337  $lifetime = 42;
338  $this->backend->set($identifier, $data, [], $lifetime);
339  $this->backend->set($identifier, $data, [], 0);
340  $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
341  $this->assertSame(31536000, $lifetimeRegisteredInBackend);
342  }
343 
348  {
349  $this->setUpBackend();
350  $this->setUpRedis();
351  $identifier = $this->getUniqueId('identifier');
352  $this->backend->set($identifier, 'data', ['tag']);
353  $this->assertSame(\Redis::REDIS_SET, $this->redis->type('identTags:' . $identifier));
354  }
355 
360  {
361  $this->setUpBackend();
362  $this->setUpRedis();
363  $identifier = $this->getUniqueId('identifier');
364  $tags = ['thatTag', 'thisTag'];
365  $this->backend->set($identifier, 'data', $tags);
366  $savedTags = $this->redis->sMembers('identTags:' . $identifier);
367  sort($savedTags);
368  $this->assertSame($tags, $savedTags);
369  }
370 
375  {
376  $this->setUpBackend();
377  $this->setUpRedis();
378  $identifier = $this->getUniqueId('identifier');
379  $tags = ['fooTag', 'barTag'];
380  $this->backend->set($identifier, 'data', $tags);
381  $this->backend->set($identifier, 'data', []);
382  $this->assertSame([], $this->redis->sMembers('identTags:' . $identifier));
383  }
384 
389  {
390  $this->setUpBackend();
391  $this->setUpRedis();
392  $identifier = $this->getUniqueId('identifier');
393  $firstTagSet = ['tag1', 'tag2', 'tag3', 'tag4'];
394  $this->backend->set($identifier, 'data', $firstTagSet);
395  $secondTagSet = ['tag1', 'tag3'];
396  $this->backend->set($identifier, 'data', $secondTagSet);
397  $actualTagSet = $this->redis->sMembers('identTags:' . $identifier);
398  sort($actualTagSet);
399  $this->assertSame($secondTagSet, $actualTagSet);
400  }
401 
406  {
407  $this->setUpBackend();
408  $this->setUpRedis();
409  $identifier = $this->getUniqueId('identifier');
410  $tag = 'tag';
411  $this->backend->set($identifier, 'data', [$tag]);
412  $this->assertSame(\Redis::REDIS_SET, $this->redis->type('tagIdents:' . $tag));
413  }
414 
419  {
420  $this->setUpBackend();
421  $this->setUpRedis();
422  $identifier = $this->getUniqueId('identifier');
423  $tag = 'thisTag';
424  $this->backend->set($identifier, 'data', [$tag]);
425  $savedTagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
426  $this->assertSame([$identifier], $savedTagToIdentifiersMemberArray);
427  }
428 
433  {
434  $this->setUpBackend();
435  $this->setUpRedis();
436  $firstIdentifier = $this->getUniqueId('identifier1-');
437  $tag = 'thisTag';
438  $this->backend->set($firstIdentifier, 'data', [$tag]);
439  $secondIdentifier = $this->getUniqueId('identifier2-');
440  $this->backend->set($secondIdentifier, 'data', [$tag]);
441  $savedTagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
442  sort($savedTagToIdentifiersMemberArray);
443  $identifierArray = [$firstIdentifier, $secondIdentifier];
444  sort($identifierArray);
445  $this->assertSame([$firstIdentifier, $secondIdentifier], $savedTagToIdentifiersMemberArray);
446  }
447 
452  {
453  $this->setUpBackend();
454  $this->setUpRedis();
455  $identifier = $this->getUniqueId('identifier');
456  $tag = 'thisTag';
457  $this->backend->set($identifier, 'data', [$tag]);
458  $this->backend->set($identifier, 'data', []);
459  $savedTagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
460  $this->assertSame([], $savedTagToIdentifiersMemberArray);
461  }
462 
467  {
468  $this->setUpBackend();
469  $this->setUpRedis();
470  $identifier = $this->getUniqueId('identifier');
471  $this->backend->set($identifier, 'data');
472  $tag = 'thisTag';
473  $this->backend->set($identifier, 'data', [$tag]);
474  $savedTagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
475  $this->assertSame([$identifier], $savedTagToIdentifiersMemberArray);
476  }
477 
482  {
483  $this->setUpBackend([
484  'compression' => true
485  ]);
486  $this->setUpRedis();
487  $identifier = $this->getUniqueId('identifier');
488  $data = 'some data ' . microtime();
489  $this->backend->set($identifier, $data);
490  $uncompresedStoredData = '';
491  try {
492  $uncompresedStoredData = @gzuncompress($this->redis->get(('identData:' . $identifier)));
493  } catch (\Exception $e) {
494  }
495  $this->assertEquals($data, $uncompresedStoredData, 'Original and compressed data don\'t match');
496  }
497 
502  {
503  $this->setUpBackend([
504  'compression' => true,
505  'compressionLevel' => 0
506  ]);
507  $this->setUpRedis();
508  $identifier = $this->getUniqueId('identifier');
509  $data = 'some data ' . microtime();
510  $this->backend->set($identifier, $data);
511  $this->assertGreaterThan(0, substr_count($this->redis->get('identData:' . $identifier), $data), 'Plaintext data not found');
512  }
513 
519  {
520  $this->setUpBackend();
521  $this->backend->has([]);
522  }
523 
528  {
529  $this->setUpBackend();
530  $identifier = $this->getUniqueId('identifier');
531  $this->assertFalse($this->backend->has($identifier));
532  }
533 
538  {
539  $this->setUpBackend();
540  $identifier = $this->getUniqueId('identifier');
541  $this->backend->set($identifier, 'data');
542  $this->assertTrue($this->backend->has($identifier));
543  }
544 
550  {
551  $this->setUpBackend();
552  $this->backend->get([]);
553  }
554 
559  {
560  $this->setUpBackend([
561  'compression' => true
562  ]);
563  $data = 'data';
564  $identifier = $this->getUniqueId('identifier');
565  $this->backend->set($identifier, $data);
566  $fetchedData = $this->backend->get($identifier);
567  $this->assertSame($data, $fetchedData);
568  }
569 
574  {
575  $this->setUpBackend();
576  $data = 'data';
577  $identifier = $this->getUniqueId('identifier');
578  $this->backend->set($identifier, $data);
579  $fetchedData = $this->backend->get($identifier);
580  $this->assertSame($data, $fetchedData);
581  }
582 
588  {
589  $this->setUpBackend();
590  $this->backend->remove([]);
591  }
592 
597  {
598  $this->setUpBackend();
599  $this->assertFalse($this->backend->remove($this->getUniqueId('identifier')));
600  }
601 
606  {
607  $this->setUpBackend();
608  $identifier = $this->getUniqueId('identifier');
609  $this->backend->set($identifier, 'data');
610  $this->assertTrue($this->backend->remove($identifier));
611  }
612 
616  public function removeDeletesEntryFromCache()
617  {
618  $this->setUpBackend();
619  $identifier = $this->getUniqueId('identifier');
620  $this->backend->set($identifier, 'data');
621  $this->backend->remove($identifier);
622  $this->assertFalse($this->backend->has($identifier));
623  }
624 
629  {
630  $this->setUpBackend();
631  $this->setUpRedis();
632  $identifier = $this->getUniqueId('identifier');
633  $tag = 'thisTag';
634  $this->backend->set($identifier, 'data', [$tag]);
635  $this->backend->remove($identifier);
636  $result = $this->redis->exists('identTags:' . $identifier);
637  if (is_int($result)) {
638  // Since 3.1.4 of phpredis/phpredis the return types has been changed
639  $result = (bool)$result;
640  }
641  $this->assertFalse($result);
642  }
643 
648  {
649  $this->setUpBackend();
650  $this->setUpRedis();
651  $identifier = $this->getUniqueId('identifier');
652  $tag = 'thisTag';
653  $this->backend->set($identifier, 'data', [$tag]);
654  $this->backend->remove($identifier);
655  $tagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
656  $this->assertSame([], $tagToIdentifiersMemberArray);
657  }
658 
663  {
664  $this->setUpBackend();
665  $this->setUpRedis();
666  $firstIdentifier = $this->getUniqueId('identifier');
667  $secondIdentifier = $this->getUniqueId('identifier');
668  $tag = 'thisTag';
669  $this->backend->set($firstIdentifier, 'data', [$tag]);
670  $this->backend->set($secondIdentifier, 'data', [$tag]);
671  $this->backend->remove($firstIdentifier);
672  $tagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
673  $this->assertSame([$secondIdentifier], $tagToIdentifiersMemberArray);
674  }
675 
681  {
682  $this->setUpBackend();
683  $this->backend->findIdentifiersByTag([]);
684  }
685 
690  {
691  $this->setUpBackend();
692  $this->assertSame([], $this->backend->findIdentifiersByTag('thisTag'));
693  }
694 
699  {
700  $this->setUpBackend();
701  $firstIdentifier = $this->getUniqueId('identifier1-');
702  $secondIdentifier = $this->getUniqueId('identifier2-');
703  $thirdIdentifier = $this->getUniqueId('identifier3-');
704  $tagsForFirstIdentifier = ['thisTag'];
705  $tagsForSecondIdentifier = ['thatTag'];
706  $tagsForThirdIdentifier = ['thisTag', 'thatTag'];
707  $this->backend->set($firstIdentifier, 'data', $tagsForFirstIdentifier);
708  $this->backend->set($secondIdentifier, 'data', $tagsForSecondIdentifier);
709  $this->backend->set($thirdIdentifier, 'data', $tagsForThirdIdentifier);
710  $expectedResult = [$firstIdentifier, $thirdIdentifier];
711  $actualResult = $this->backend->findIdentifiersByTag('thisTag');
712  sort($actualResult);
713  $this->assertSame($expectedResult, $actualResult);
714  }
715 
720  {
721  $this->setUpBackend();
722  $this->setUpRedis();
723  $identifier = $this->getUniqueId('identifier');
724  $this->backend->set($identifier, 'data');
725  $this->backend->flush();
726  $this->assertSame([], $this->redis->getKeys('*'));
727  }
728 
734  {
735  $this->setUpBackend();
736  $this->backend->flushByTag([]);
737  }
738 
743  {
744  $this->setUpBackend();
745  $identifier = $this->getUniqueId('identifier');
746  $this->backend->set($identifier . 'A', 'data', ['tag1']);
747  $this->backend->set($identifier . 'B', 'data', ['tag2']);
748  $this->backend->set($identifier . 'C', 'data', ['tag1', 'tag2']);
749  $this->backend->flushByTag('tag1');
750  $expectedResult = [false, true, false];
751  $actualResult = [
752  $this->backend->has($identifier . 'A'),
753  $this->backend->has($identifier . 'B'),
754  $this->backend->has($identifier . 'C')
755  ];
756  $this->assertSame($expectedResult, $actualResult);
757  }
758 
763  {
764  $this->setUpBackend();
765  $this->setUpRedis();
766  $identifier = $this->getUniqueId('identifier');
767  $this->backend->set($identifier . 'A', 'data', ['tag1']);
768  $this->backend->set($identifier . 'C', 'data', ['tag1', 'tag2']);
769  $this->backend->flushByTag('tag1');
770  $this->assertSame([], $this->redis->getKeys('temp*'));
771  }
772 
777  {
778  $this->setUpBackend();
779  $this->setUpRedis();
780  $identifier = $this->getUniqueId('identifier');
781  $tag = 'tag1';
782  $this->backend->set($identifier, 'data', [$tag]);
783  $this->backend->flushByTag($tag);
784  $result = $this->redis->exists('identTags:' . $identifier);
785  if (is_int($result)) {
786  // Since 3.1.4 of phpredis/phpredis the return types has been changed
787  $result = (bool)$result;
788  }
789  $this->assertFalse($result);
790  }
791 
796  {
797  $this->setUpBackend();
798  $this->setUpRedis();
799  $identifierToBeRemoved = $this->getUniqueId('identifier');
800  $tagToRemove = 'tag1';
801  $this->backend->set($identifierToBeRemoved, 'data', [$tagToRemove]);
802  $identifierNotToBeRemoved = $this->getUniqueId('identifier');
803  $tagNotToRemove = 'tag2';
804  $this->backend->set($identifierNotToBeRemoved, 'data', [$tagNotToRemove]);
805  $this->backend->flushByTag($tagToRemove);
806  $this->assertSame([$tagNotToRemove], $this->redis->sMembers('identTags:' . $identifierNotToBeRemoved));
807  }
808 
813  {
814  $this->setUpBackend();
815  $this->setUpRedis();
816  $identifier = $this->getUniqueId('identifier');
817  $tag = 'tag1';
818  $this->backend->set($identifier, 'data', [$tag]);
819  $this->backend->flushByTag($tag);
820  $result = $this->redis->exists('tagIdents:' . $tag);
821  if (is_int($result)) {
822  // Since 3.1.4 of phpredis/phpredis the return types has been changed
823  $result = (bool)$result;
824  }
825  $this->assertFalse($result);
826  }
827 
832  {
833  $this->setUpBackend();
834  $this->setUpRedis();
835  $identifier = $this->getUniqueId('identifier');
836  $this->backend->set($identifier . 'A', 'data', ['tag1', 'tag2']);
837  $this->backend->set($identifier . 'B', 'data', ['tag1', 'tag2']);
838  $this->backend->set($identifier . 'C', 'data', ['tag2']);
839  $this->backend->flushByTag('tag1');
840  $this->assertSame([$identifier . 'C'], $this->redis->sMembers('tagIdents:tag2'));
841  }
842 
847  {
848  $this->setUpBackend();
849  $this->setUpRedis();
850  $identifier = $this->getUniqueId('identifier');
851  $this->backend->set($identifier . 'A', 'data', ['tag']);
852  $this->backend->set($identifier . 'B', 'data', ['tag']);
853  $this->redis->delete('identData:' . $identifier . 'A');
854  $this->backend->collectGarbage();
855  $result = $this->redis->exists('identData:' . $identifier . 'B');
856  if (is_int($result)) {
857  // Since 3.1.4 of phpredis/phpredis the return types has been changed
858  $result = (bool)$result;
859  }
860  $this->assertTrue($result);
861  }
862 
867  {
868  $this->setUpBackend();
869  $this->setUpRedis();
870  $identifier = $this->getUniqueId('identifier');
871  $this->backend->set($identifier . 'A', 'data', ['tag']);
872  $this->backend->set($identifier . 'B', 'data', ['tag']);
873  $this->redis->delete('identData:' . $identifier . 'A');
874  $this->backend->collectGarbage();
875  $expectedResult = [false, true];
876  $resultA = $this->redis->exists('identTags:' . $identifier . 'A');
877  $resultB = $this->redis->exists('identTags:' . $identifier . 'B');
878  if (is_int($resultA)) {
879  // Since 3.1.4 of phpredis/phpredis the return types has been changed
880  $resultA = (bool)$resultA;
881  }
882  if (is_int($resultB)) {
883  // Since 3.1.4 of phpredis/phpredis the return types has been changed
884  $resultB = (bool)$resultB;
885  }
886  $actualResult = [
887  $resultA,
888  $resultB
889  ];
890  $this->assertSame($expectedResult, $actualResult);
891  }
892 
897  {
898  $this->setUpBackend();
899  $this->setUpRedis();
900  $identifier = $this->getUniqueId('identifier');
901  $this->backend->set($identifier . 'A', 'data', ['tag1', 'tag2']);
902  $this->backend->set($identifier . 'B', 'data', ['tag2']);
903  $this->redis->delete('identData:' . $identifier . 'A');
904  $this->backend->collectGarbage();
905  $expectedResult = [
906  [],
907  [$identifier . 'B']
908  ];
909  $actualResult = [
910  $this->redis->sMembers('tagIdents:tag1'),
911  $this->redis->sMembers('tagIdents:tag2')
912  ];
913  $this->assertSame($expectedResult, $actualResult);
914  }
915 }