[TASK] Re-work/simplify copyright header in PHP files - Part 4
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Cache / Backend / RedisBackendTest.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 /**
18 * Testcase for the cache to redis backend
19 *
20 * This class has functional tests as well as implementation tests:
21 * - The functional tests make API calls to the backend and check expected behaviour
22 * - The implementation tests make additional calls with an own redis instance to
23 * check stored data structures in the redis server, which can not be checked
24 * by functional tests alone. Those tests will fail if any changes
25 * to the internal data structure are done.
26 *
27 * Warning:
28 * The unit tests use and flush redis database numbers 0 and 1!
29 *
30 * @author Christian Kuhn <lolli@schwarzbu.ch>
31 */
32 class RedisBackendTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
33
34 /**
35 * If set, the tearDown() method will flush the cache used by this unit test.
36 *
37 * @var \TYPO3\CMS\Core\Cache\Backend\RedisBackend
38 */
39 protected $backend = NULL;
40
41 /**
42 * Own redis instance used in implementation tests
43 *
44 * @var Redis
45 */
46 protected $redis = NULL;
47
48 /**
49 * Set up this testcase
50 */
51 public function setUp() {
52 if (!extension_loaded('redis')) {
53 $this->markTestSkipped('redis extension was not available');
54 }
55 try {
56 if (!@fsockopen('127.0.0.1', 6379)) {
57 $this->markTestSkipped('redis server not reachable');
58 }
59 } catch (\Exception $e) {
60 $this->markTestSkipped('redis server not reachable');
61 }
62 }
63
64 /**
65 * Sets up the redis backend used for testing
66 *
67 * @param array $backendOptions Options for the redis backend
68 */
69 protected function setUpBackend(array $backendOptions = array()) {
70 $mockCache = $this->getMock('TYPO3\\CMS\\Core\\Cache\\Frontend\\FrontendInterface', array(), array(), '', FALSE);
71 $mockCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('TestCache'));
72 $this->backend = new \TYPO3\CMS\Core\Cache\Backend\RedisBackend('Testing', $backendOptions);
73 $this->backend->setCache($mockCache);
74 $this->backend->initializeObject();
75 }
76
77 /**
78 * Sets up an own redis instance for implementation tests
79 */
80 protected function setUpRedis() {
81 $this->redis = new \Redis();
82 $this->redis->connect('127.0.0.1', 6379);
83 }
84
85 /**
86 * Tear down this testcase
87 */
88 public function tearDown() {
89 if ($this->backend instanceof \TYPO3\CMS\Core\Cache\Backend\RedisBackend) {
90 $this->backend->flush();
91 }
92 parent::tearDown();
93 }
94
95 /**
96 * @test Functional
97 */
98 public function initializeObjectThrowsNoExceptionIfGivenDatabaseWasSuccessfullySelected() {
99 try {
100 $this->setUpBackend(array('database' => 1));
101 } catch (Exception $e) {
102 $this->assertTrue();
103 }
104 }
105
106 /**
107 * @test Functional
108 * @expectedException \InvalidArgumentException
109 */
110 public function setDatabaseThrowsExceptionIfGivenDatabaseNumberIsNotAnInteger() {
111 $this->setUpBackend(array('database' => 'foo'));
112 }
113
114 /**
115 * @test Functional
116 * @expectedException \InvalidArgumentException
117 */
118 public function setDatabaseThrowsExceptionIfGivenDatabaseNumberIsNegative() {
119 $this->setUpBackend(array('database' => -1));
120 }
121
122 /**
123 * @test Functional
124 * @expectedException \InvalidArgumentException
125 */
126 public function setCompressionThrowsExceptionIfCompressionParameterIsNotOfTypeBoolean() {
127 $this->setUpBackend(array('compression' => 'foo'));
128 }
129
130 /**
131 * @test Functional
132 * @expectedException \InvalidArgumentException
133 */
134 public function setCompressionLevelThrowsExceptionIfCompressionLevelIsNotInteger() {
135 $this->setUpBackend(array('compressionLevel' => 'foo'));
136 }
137
138 /**
139 * @test Functional
140 * @expectedException \InvalidArgumentException
141 */
142 public function setCompressionLevelThrowsExceptionIfCompressionLevelIsNotBetweenMinusOneAndNine() {
143 $this->setUpBackend(array('compressionLevel' => 11));
144 }
145
146 /**
147 * @test Functional
148 * @expectedException \InvalidArgumentException
149 */
150 public function setThrowsExceptionIfIdentifierIsNotAString() {
151 $this->setUpBackend();
152 $this->backend->set(array(), 'data');
153 }
154
155 /**
156 * @test Functional
157 * @expectedException \TYPO3\CMS\Core\Cache\Exception\InvalidDataException
158 */
159 public function setThrowsExceptionIfDataIsNotAString() {
160 $this->setUpBackend();
161 $this->backend->set('identifier' . uniqid(), array());
162 }
163
164 /**
165 * @test Functional
166 * @expectedException \InvalidArgumentException
167 */
168 public function setThrowsExceptionIfLifetimeIsNegative() {
169 $this->setUpBackend();
170 $this->backend->set('identifier' . uniqid(), 'data', array(), -42);
171 }
172
173 /**
174 * @test Functional
175 * @expectedException \InvalidArgumentException
176 */
177 public function setThrowsExceptionIfLifetimeIsNotNullOrAnInteger() {
178 $this->setUpBackend();
179 $this->backend->set('identifier' . uniqid(), 'data', array(), array());
180 }
181
182 /**
183 * @test Implementation
184 */
185 public function setStoresEntriesInSelectedDatabase() {
186 $this->setUpRedis();
187 $this->redis->select(1);
188 $this->setUpBackend(array('database' => 1));
189 $identifier = 'identifier' . uniqid();
190 $this->backend->set($identifier, 'data');
191 $this->assertTrue($this->redis->exists('identData:' . $identifier));
192 }
193
194 /**
195 * @test Implementation
196 */
197 public function setSavesStringDataTypeForIdentifierToDataEntry() {
198 $this->setUpBackend();
199 $this->setUpRedis();
200 $identifier = 'identifier' . uniqid();
201 $this->backend->set($identifier, 'data');
202 $this->assertSame(\Redis::REDIS_STRING, $this->redis->type('identData:' . $identifier));
203 }
204
205 /**
206 * @test Implementation
207 */
208 public function setSavesEntryWithDefaultLifeTime() {
209 $this->setUpBackend();
210 $this->setUpRedis();
211 $identifier = 'identifier' . uniqid();
212 $defaultLifetime = 42;
213 $this->backend->setDefaultLifetime($defaultLifetime);
214 $this->backend->set($identifier, 'data');
215 $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
216 $this->assertSame($defaultLifetime, $lifetimeRegisteredInBackend);
217 }
218
219 /**
220 * @test Implementation
221 */
222 public function setSavesEntryWithSpecifiedLifeTime() {
223 $this->setUpBackend();
224 $this->setUpRedis();
225 $identifier = 'identifier' . uniqid();
226 $lifetime = 43;
227 $this->backend->set($identifier, 'data', array(), $lifetime);
228 $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
229 $this->assertSame($lifetime, $lifetimeRegisteredInBackend);
230 }
231
232 /**
233 * @test Implementation
234 */
235 public function setSavesEntryWithUnlimitedLifeTime() {
236 $this->setUpBackend();
237 $this->setUpRedis();
238 $identifier = 'identifier' . uniqid();
239 $this->backend->set($identifier, 'data', array(), 0);
240 $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
241 $this->assertSame(31536000, $lifetimeRegisteredInBackend);
242 }
243
244 /**
245 * @test Functional
246 */
247 public function setOverwritesExistingEntryWithNewData() {
248 $this->setUpBackend();
249 $data = 'data 1';
250 $identifier = 'identifier' . uniqid();
251 $this->backend->set($identifier, $data);
252 $otherData = 'data 2';
253 $this->backend->set($identifier, $otherData);
254 $fetchedData = $this->backend->get($identifier);
255 $this->assertSame($otherData, $fetchedData);
256 }
257
258 /**
259 * @test Implementation
260 */
261 public function setOverwritesExistingEntryWithSpecifiedLifetime() {
262 $this->setUpBackend();
263 $this->setUpRedis();
264 $data = 'data';
265 $identifier = 'identifier' . uniqid();
266 $this->backend->set($identifier, $data);
267 $lifetime = 42;
268 $this->backend->set($identifier, $data, array(), $lifetime);
269 $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
270 $this->assertSame($lifetime, $lifetimeRegisteredInBackend);
271 }
272
273 /**
274 * @test Implementation
275 */
276 public function setOverwritesExistingEntryWithNewDefaultLifetime() {
277 $this->setUpBackend();
278 $this->setUpRedis();
279 $data = 'data';
280 $identifier = 'identifier' . uniqid();
281 $lifetime = 42;
282 $this->backend->set($identifier, $data, array(), $lifetime);
283 $newDefaultLifetime = 43;
284 $this->backend->setDefaultLifetime($newDefaultLifetime);
285 $this->backend->set($identifier, $data, array(), $newDefaultLifetime);
286 $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
287 $this->assertSame($newDefaultLifetime, $lifetimeRegisteredInBackend);
288 }
289
290 /**
291 * @test Implementation
292 */
293 public function setOverwritesExistingEntryWithNewUnlimitedLifetime() {
294 $this->setUpBackend();
295 $this->setUpRedis();
296 $data = 'data';
297 $identifier = 'identifier' . uniqid();
298 $lifetime = 42;
299 $this->backend->set($identifier, $data, array(), $lifetime);
300 $this->backend->set($identifier, $data, array(), 0);
301 $lifetimeRegisteredInBackend = $this->redis->ttl('identData:' . $identifier);
302 $this->assertSame(31536000, $lifetimeRegisteredInBackend);
303 }
304
305 /**
306 * @test Implementation
307 */
308 public function setSavesSetDataTypeForIdentifierToTagsSet() {
309 $this->setUpBackend();
310 $this->setUpRedis();
311 $identifier = 'identifier' . uniqid();
312 $this->backend->set($identifier, 'data', array('tag'));
313 $this->assertSame(\Redis::REDIS_SET, $this->redis->type('identTags:' . $identifier));
314 }
315
316 /**
317 * @test Implementation
318 */
319 public function setSavesSpecifiedTagsInIdentifierToTagsSet() {
320 $this->setUpBackend();
321 $this->setUpRedis();
322 $identifier = 'identifier' . uniqid();
323 $tags = array('thatTag', 'thisTag');
324 $this->backend->set($identifier, 'data', $tags);
325 $savedTags = $this->redis->sMembers('identTags:' . $identifier);
326 sort($savedTags);
327 $this->assertSame($tags, $savedTags);
328 }
329
330 /**
331 * @test Implementation
332 */
333 public function setRemovesAllPreviouslySetTagsFromIdentifierToTagsSet() {
334 $this->setUpBackend();
335 $this->setUpRedis();
336 $identifier = 'identifier' . uniqid();
337 $tags = array('fooTag', 'barTag');
338 $this->backend->set($identifier, 'data', $tags);
339 $this->backend->set($identifier, 'data', array());
340 $this->assertSame(array(), $this->redis->sMembers('identTags:' . $identifier));
341 }
342
343 /**
344 * @test Implementation
345 */
346 public function setRemovesMultiplePreviouslySetTagsFromIdentifierToTagsSet() {
347 $this->setUpBackend();
348 $this->setUpRedis();
349 $identifier = 'identifier' . uniqid();
350 $firstTagSet = array('tag1', 'tag2', 'tag3', 'tag4');
351 $this->backend->set($identifier, 'data', $firstTagSet);
352 $secondTagSet = array('tag1', 'tag3');
353 $this->backend->set($identifier, 'data', $secondTagSet);
354 $actualTagSet = $this->redis->sMembers('identTags:' . $identifier);
355 sort($actualTagSet);
356 $this->assertSame($secondTagSet, $actualTagSet);
357 }
358
359 /**
360 * @test Implementation
361 */
362 public function setSavesSetDataTypeForTagToIdentifiersSet() {
363 $this->setUpBackend();
364 $this->setUpRedis();
365 $identifier = 'identifier' . uniqid();
366 $tag = 'tag';
367 $this->backend->set($identifier, 'data', array($tag));
368 $this->assertSame(\Redis::REDIS_SET, $this->redis->type('tagIdents:' . $tag));
369 }
370
371 /**
372 * @test Implementation
373 */
374 public function setSavesIdentifierInTagToIdentifiersSetOfSpecifiedTag() {
375 $this->setUpBackend();
376 $this->setUpRedis();
377 $identifier = 'identifier' . uniqid();
378 $tag = 'thisTag';
379 $this->backend->set($identifier, 'data', array($tag));
380 $savedTagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
381 $this->assertSame(array($identifier), $savedTagToIdentifiersMemberArray);
382 }
383
384 /**
385 * @test Implementation
386 */
387 public function setAppendsSecondIdentifierInTagToIdentifiersEntry() {
388 $this->setUpBackend();
389 $this->setUpRedis();
390 $firstIdentifier = 'identifier' . uniqid();
391 $tag = 'thisTag';
392 $this->backend->set($firstIdentifier, 'data', array($tag));
393 $secondIdentifier = 'identifier' . uniqid();
394 $this->backend->set($secondIdentifier, 'data', array($tag));
395 $savedTagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
396 sort($savedTagToIdentifiersMemberArray);
397 $identifierArray = array($firstIdentifier, $secondIdentifier);
398 sort($identifierArray);
399 $this->assertSame(array($firstIdentifier, $secondIdentifier), $savedTagToIdentifiersMemberArray);
400 }
401
402 /**
403 * @test Implementation
404 */
405 public function setRemovesIdentifierFromTagToIdentifiersEntryIfTagIsOmittedOnConsecutiveSet() {
406 $this->setUpBackend();
407 $this->setUpRedis();
408 $identifier = 'identifier' . uniqid();
409 $tag = 'thisTag';
410 $this->backend->set($identifier, 'data', array($tag));
411 $this->backend->set($identifier, 'data', array());
412 $savedTagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
413 $this->assertSame(array(), $savedTagToIdentifiersMemberArray);
414 }
415
416 /**
417 * @test Implementation
418 */
419 public function setAddsIdentifierInTagToIdentifiersEntryIfTagIsAddedOnConsecutiveSet() {
420 $this->setUpBackend();
421 $this->setUpRedis();
422 $identifier = 'identifier' . uniqid();
423 $this->backend->set($identifier, 'data');
424 $tag = 'thisTag';
425 $this->backend->set($identifier, 'data', array($tag));
426 $savedTagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
427 $this->assertSame(array($identifier), $savedTagToIdentifiersMemberArray);
428 }
429
430 /**
431 * @test Implementation
432 */
433 public function setSavesCompressedDataWithEnabledCompression() {
434 $this->setUpBackend(array(
435 'compression' => TRUE
436 ));
437 $this->setUpRedis();
438 $identifier = 'identifier' . uniqid();
439 $data = 'some data ' . microtime();
440 $this->backend->set($identifier, $data);
441 $uncompresedStoredData = '';
442 try {
443 $uncompresedStoredData = @gzuncompress($this->redis->get(('identData:' . $identifier)));
444 } catch (\Exception $e) {
445
446 }
447 $this->assertEquals($data, $uncompresedStoredData, 'Original and compressed data don\'t match');
448 }
449
450 /**
451 * @test Implementation
452 */
453 public function setSavesPlaintextDataWithEnabledCompressionAndCompressionLevel0() {
454 $this->setUpBackend(array(
455 'compression' => TRUE,
456 'compressionLevel' => 0
457 ));
458 $this->setUpRedis();
459 $identifier = 'identifier' . uniqid();
460 $data = 'some data ' . microtime();
461 $this->backend->set($identifier, $data);
462 $this->assertGreaterThan(0, substr_count($this->redis->get('identData:' . $identifier), $data), 'Plaintext data not found');
463 }
464
465 /**
466 * @test Functional
467 * @expectedException \InvalidArgumentException
468 */
469 public function hasThrowsExceptionIfIdentifierIsNotAString() {
470 $this->setUpBackend();
471 $this->backend->has(array());
472 }
473
474 /**
475 * @test Functional
476 */
477 public function hasReturnsFalseForNotExistingEntry() {
478 $this->setUpBackend();
479 $identifier = 'identifier' . uniqid();
480 $this->assertFalse($this->backend->has($identifier));
481 }
482
483 /**
484 * @test Functional
485 */
486 public function hasReturnsTrueForPreviouslySetEntry() {
487 $this->setUpBackend();
488 $identifier = 'identifier' . uniqid();
489 $this->backend->set($identifier, 'data');
490 $this->assertTrue($this->backend->has($identifier));
491 }
492
493 /**
494 * @test Functional
495 * @expectedException \InvalidArgumentException
496 */
497 public function getThrowsExceptionIfIdentifierIsNotAString() {
498 $this->setUpBackend();
499 $this->backend->get(array());
500 }
501
502 /**
503 * @test Functional
504 */
505 public function getReturnsPreviouslyCompressedSetEntry() {
506 $this->setUpBackend(array(
507 'compression' => TRUE
508 ));
509 $data = 'data';
510 $identifier = 'identifier' . uniqid();
511 $this->backend->set($identifier, $data);
512 $fetchedData = $this->backend->get($identifier);
513 $this->assertSame($data, $fetchedData);
514 }
515
516 /**
517 * @test Functional
518 */
519 public function getReturnsPreviouslySetEntry() {
520 $this->setUpBackend();
521 $data = 'data';
522 $identifier = 'identifier' . uniqid();
523 $this->backend->set($identifier, $data);
524 $fetchedData = $this->backend->get($identifier);
525 $this->assertSame($data, $fetchedData);
526 }
527
528 /**
529 * @test Functional
530 * @expectedException \InvalidArgumentException
531 */
532 public function removeThrowsExceptionIfIdentifierIsNotAString() {
533 $this->setUpBackend();
534 $this->backend->remove(array());
535 }
536
537 /**
538 * @test Functional
539 */
540 public function removeReturnsFalseIfNoEntryWasDeleted() {
541 $this->setUpBackend();
542 $this->assertFalse($this->backend->remove('identifier' . uniqid()));
543 }
544
545 /**
546 * @test Functional
547 */
548 public function removeReturnsTrueIfAnEntryWasDeleted() {
549 $this->setUpBackend();
550 $identifier = 'identifier' . uniqid();
551 $this->backend->set($identifier, 'data');
552 $this->assertTrue($this->backend->remove($identifier));
553 }
554
555 /**
556 * @test Functional
557 */
558 public function removeDeletesEntryFromCache() {
559 $this->setUpBackend();
560 $identifier = 'identifier' . uniqid();
561 $this->backend->set($identifier, 'data');
562 $this->backend->remove($identifier);
563 $this->assertFalse($this->backend->has($identifier));
564 }
565
566 /**
567 * @test Implementation
568 */
569 public function removeDeletesIdentifierToTagEntry() {
570 $this->setUpBackend();
571 $this->setUpRedis();
572 $identifier = 'identifier' . uniqid();
573 $tag = 'thisTag';
574 $this->backend->set($identifier, 'data', array($tag));
575 $this->backend->remove($identifier);
576 $this->assertFalse($this->redis->exists('identTags:' . $identifier));
577 }
578
579 /**
580 * @test Implementation
581 */
582 public function removeDeletesIdentifierFromTagToIdentifiersSet() {
583 $this->setUpBackend();
584 $this->setUpRedis();
585 $identifier = 'identifier' . uniqid();
586 $tag = 'thisTag';
587 $this->backend->set($identifier, 'data', array($tag));
588 $this->backend->remove($identifier);
589 $tagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
590 $this->assertSame(array(), $tagToIdentifiersMemberArray);
591 }
592
593 /**
594 * @test Implementation
595 */
596 public function removeDeletesIdentifierFromTagToIdentifiersSetWithMultipleEntries() {
597 $this->setUpBackend();
598 $this->setUpRedis();
599 $firstIdentifier = 'identifier' . uniqid();
600 $secondIdentifier = 'identifier' . uniqid();
601 $tag = 'thisTag';
602 $this->backend->set($firstIdentifier, 'data', array($tag));
603 $this->backend->set($secondIdentifier, 'data', array($tag));
604 $this->backend->remove($firstIdentifier);
605 $tagToIdentifiersMemberArray = $this->redis->sMembers('tagIdents:' . $tag);
606 $this->assertSame(array($secondIdentifier), $tagToIdentifiersMemberArray);
607 }
608
609 /**
610 * @test Functional
611 * @expectedException \InvalidArgumentException
612 */
613 public function findIdentifiersByTagThrowsExceptionIfTagIsNotAString() {
614 $this->setUpBackend();
615 $this->backend->findIdentifiersByTag(array());
616 }
617
618 /**
619 * @test Functional
620 */
621 public function findIdentifiersByTagReturnsEmptyArrayForNotExistingTag() {
622 $this->setUpBackend();
623 $this->assertSame(array(), $this->backend->findIdentifiersByTag('thisTag'));
624 }
625
626 /**
627 * @test Functional
628 */
629 public function findIdentifiersByTagReturnsAllIdentifiersTagedWithSpecifiedTag() {
630 $this->setUpBackend();
631 $firstIdentifier = 'identifier' . uniqid();
632 $secondIdentifier = 'identifier' . uniqid();
633 $thirdIdentifier = 'identifier' . uniqid();
634 $tagsForFirstIdentifier = array('thisTag');
635 $tagsForSecondIdentifier = array('thatTag');
636 $tagsForThirdIdentifier = array('thisTag', 'thatTag');
637 $this->backend->set($firstIdentifier, 'data', $tagsForFirstIdentifier);
638 $this->backend->set($secondIdentifier, 'data', $tagsForSecondIdentifier);
639 $this->backend->set($thirdIdentifier, 'data', $tagsForThirdIdentifier);
640 $expectedResult = array($firstIdentifier, $thirdIdentifier);
641 $actualResult = $this->backend->findIdentifiersByTag('thisTag');
642 sort($actualResult);
643 $this->assertSame($expectedResult, $actualResult);
644 }
645
646 /**
647 * @test Implementation
648 */
649 public function flushRemovesAllEntriesFromCache() {
650 $this->setUpBackend();
651 $this->setUpRedis();
652 $identifier = 'identifier' . uniqid();
653 $this->backend->set($identifier, 'data');
654 $this->backend->flush();
655 $this->assertSame(array(), $this->redis->getKeys('*'));
656 }
657
658 /**
659 * @test Functional
660 * @expectedException \InvalidArgumentException
661 */
662 public function flushByTagThrowsExceptionIfTagIsNotAString() {
663 $this->setUpBackend();
664 $this->backend->flushByTag(array());
665 }
666
667 /**
668 * @test Functional
669 */
670 public function flushByTagRemovesEntriesTaggedWithSpecifiedTag() {
671 $this->setUpBackend();
672 $identifier = 'identifier' . uniqid();
673 $this->backend->set($identifier . 'A', 'data', array('tag1'));
674 $this->backend->set($identifier . 'B', 'data', array('tag2'));
675 $this->backend->set($identifier . 'C', 'data', array('tag1', 'tag2'));
676 $this->backend->flushByTag('tag1');
677 $expectedResult = array(FALSE, TRUE, FALSE);
678 $actualResult = array(
679 $this->backend->has($identifier . 'A'),
680 $this->backend->has($identifier . 'B'),
681 $this->backend->has($identifier . 'C')
682 );
683 $this->assertSame($expectedResult, $actualResult);
684 }
685
686 /**
687 * @test Implementation
688 */
689 public function flushByTagRemovesTemporarySet() {
690 $this->setUpBackend();
691 $this->setUpRedis();
692 $identifier = 'identifier' . uniqid();
693 $this->backend->set($identifier . 'A', 'data', array('tag1'));
694 $this->backend->set($identifier . 'C', 'data', array('tag1', 'tag2'));
695 $this->backend->flushByTag('tag1');
696 $this->assertSame(array(), $this->redis->getKeys('temp*'));
697 }
698
699 /**
700 * @test Implementation
701 */
702 public function flushByTagRemovesIdentifierToTagsSetOfEntryTaggedWithGivenTag() {
703 $this->setUpBackend();
704 $this->setUpRedis();
705 $identifier = 'identifier' . uniqid();
706 $tag = 'tag1';
707 $this->backend->set($identifier, 'data', array($tag));
708 $this->backend->flushByTag($tag);
709 $this->assertFalse($this->redis->exists('identTags:' . $identifier));
710 }
711
712 /**
713 * @test Implementation
714 */
715 public function flushByTagDoesNotRemoveIdentifierToTagsSetOfUnrelatedEntry() {
716 $this->setUpBackend();
717 $this->setUpRedis();
718 $identifierToBeRemoved = 'identifier' . uniqid();
719 $tagToRemove = 'tag1';
720 $this->backend->set($identifierToBeRemoved, 'data', array($tagToRemove));
721 $identifierNotToBeRemoved = 'identifier' . uniqid();
722 $tagNotToRemove = 'tag2';
723 $this->backend->set($identifierNotToBeRemoved, 'data', array($tagNotToRemove));
724 $this->backend->flushByTag($tagToRemove);
725 $this->assertSame(array($tagNotToRemove), $this->redis->sMembers('identTags:' . $identifierNotToBeRemoved));
726 }
727
728 /**
729 * @test Implementation
730 */
731 public function flushByTagRemovesTagToIdentifiersSetOfGivenTag() {
732 $this->setUpBackend();
733 $this->setUpRedis();
734 $identifier = 'identifier' . uniqid();
735 $tag = 'tag1';
736 $this->backend->set($identifier, 'data', array($tag));
737 $this->backend->flushByTag($tag);
738 $this->assertFalse($this->redis->exists('tagIdents:' . $tag));
739 }
740
741 /**
742 * @test Implementation
743 */
744 public function flushByTagRemovesIdentifiersTaggedWithGivenTagFromTagToIdentifiersSets() {
745 $this->setUpBackend();
746 $this->setUpRedis();
747 $identifier = 'identifier' . uniqid();
748 $this->backend->set($identifier . 'A', 'data', array('tag1', 'tag2'));
749 $this->backend->set($identifier . 'B', 'data', array('tag1', 'tag2'));
750 $this->backend->set($identifier . 'C', 'data', array('tag2'));
751 $this->backend->flushByTag('tag1');
752 $this->assertSame(array($identifier . 'C'), $this->redis->sMembers('tagIdents:tag2'));
753 }
754
755 /**
756 * @test Implementation
757 */
758 public function collectGarbageDoesNotRemoveNotExpiredIdentifierToDataEntry() {
759 $this->setUpBackend();
760 $this->setUpRedis();
761 $identifier = 'identifier' . uniqid();
762 $this->backend->set($identifier . 'A', 'data', array('tag'));
763 $this->backend->set($identifier . 'B', 'data', array('tag'));
764 $this->redis->delete('identData:' . $identifier . 'A');
765 $this->backend->collectGarbage();
766 $this->assertTrue($this->redis->exists('identData:' . $identifier . 'B'));
767 }
768
769 /**
770 * @test Implementation
771 */
772 public function collectGarbageRemovesLeftOverIdentifierToTagsSet() {
773 $this->setUpBackend();
774 $this->setUpRedis();
775 $identifier = 'identifier' . uniqid();
776 $this->backend->set($identifier . 'A', 'data', array('tag'));
777 $this->backend->set($identifier . 'B', 'data', array('tag'));
778 $this->redis->delete('identData:' . $identifier . 'A');
779 $this->backend->collectGarbage();
780 $expectedResult = array(FALSE, TRUE);
781 $actualResult = array(
782 $this->redis->exists('identTags:' . $identifier . 'A'),
783 $this->redis->exists('identTags:' . $identifier . 'B')
784 );
785 $this->assertSame($expectedResult, $actualResult);
786 }
787
788 /**
789 * @test Implementation
790 */
791 public function collectGarbageRemovesExpiredIdentifierFromTagsToIdentifierSet() {
792 $this->setUpBackend();
793 $this->setUpRedis();
794 $identifier = 'identifier' . uniqid();
795 $this->backend->set($identifier . 'A', 'data', array('tag1', 'tag2'));
796 $this->backend->set($identifier . 'B', 'data', array('tag2'));
797 $this->redis->delete('identData:' . $identifier . 'A');
798 $this->backend->collectGarbage();
799 $expectedResult = array(
800 array(),
801 array($identifier . 'B')
802 );
803 $actualResult = array(
804 $this->redis->sMembers('tagIdents:tag1'),
805 $this->redis->sMembers('tagIdents:tag2')
806 );
807 $this->assertSame($expectedResult, $actualResult);
808 }
809
810 }