3 namespace Drupal\Tests\Core\Cache;
5 use Drupal\Core\Cache\BackendChain;
6 use Drupal\Core\Cache\Cache;
7 use Drupal\Core\Cache\MemoryBackend;
8 use Drupal\Tests\UnitTestCase;
11 * Unit test of backend chain implementation specifics.
15 class BackendChainImplementationUnitTest extends UnitTestCase {
18 * Chain that will be heavily tested.
20 * @var \Drupal\Core\Cache\BackendChain
25 * First backend in the chain.
27 * @var \Drupal\Core\Cache\CacheBackendInterface
29 protected $firstBackend;
32 * Second backend in the chain.
34 * @var \Drupal\Core\Cache\CacheBackendInterface
36 protected $secondBackend;
39 * Third backend in the chain.
41 * @var \Drupal\Core\Cache\CacheBackendInterface
43 protected $thirdBackend;
45 protected function setUp() {
48 // Set up three memory backends to be used in the chain.
49 $this->firstBackend = new MemoryBackend();
50 $this->secondBackend = new MemoryBackend();
51 $this->thirdBackend = new MemoryBackend();
53 // Set an initial fixed dataset for all testing. The next three data
54 // collections will test two edge cases (last backend has the data, and
55 // first backend has the data) and will test a normal use case (middle
56 // backend has the data). We should have a complete unit test with those.
57 // Note that in all cases, when the same key is set on more than one
58 // backend, the values are voluntarily different, this ensures in which
59 // backend we actually fetched the key when doing get calls.
61 // Set a key present on all backends (for delete).
62 $this->firstBackend->set('t123', 1231);
63 $this->secondBackend->set('t123', 1232);
64 $this->thirdBackend->set('t123', 1233);
66 // Set a key present on the second and the third (for get), those two will
67 // be different, this will ensure from where we get the key.
68 $this->secondBackend->set('t23', 232);
69 $this->thirdBackend->set('t23', 233);
71 // Set a key on only the third, we will ensure propagation using this one.
72 $this->thirdBackend->set('t3', 33);
75 $this->chain = new BackendChain('foobarbaz');
77 ->appendBackend($this->firstBackend)
78 ->appendBackend($this->secondBackend)
79 ->appendBackend($this->thirdBackend);
83 * Test the get feature.
85 public function testGet() {
86 $cached = $this->chain->get('t123');
87 $this->assertNotSame(FALSE, $cached, 'Got key that is on all backends');
88 $this->assertSame(1231, $cached->data, 'Got the key from the backend 1');
90 $cached = $this->chain->get('t23');
91 $this->assertNotSame(FALSE, $cached, 'Got key that is on backends 2 and 3');
92 $this->assertSame(232, $cached->data, 'Got the key from the backend 2');
94 $cached = $this->chain->get('t3');
95 $this->assertNotSame(FALSE, $cached, 'Got key that is on the backend 3');
96 $this->assertSame(33, $cached->data, 'Got the key from the backend 3');
100 * Test the get multiple feature.
102 public function testGetMultiple() {
103 $cids = ['t123', 't23', 't3', 't4'];
105 $ret = $this->chain->getMultiple($cids);
106 $this->assertSame($ret['t123']->data, 1231, 'Got key 123 and value is from the first backend');
107 $this->assertSame($ret['t23']->data, 232, 'Got key 23 and value is from the second backend');
108 $this->assertSame($ret['t3']->data, 33, 'Got key 3 and value is from the third backend');
109 $this->assertFalse(array_key_exists('t4', $ret), "Didn't get the nonexistent key");
111 $this->assertFalse(in_array('t123', $cids), "Existing key 123 has been removed from &\$cids");
112 $this->assertFalse(in_array('t23', $cids), "Existing key 23 has been removed from &\$cids");
113 $this->assertFalse(in_array('t3', $cids), "Existing key 3 has been removed from &\$cids");
114 $this->assertTrue(in_array('t4', $cids), "Non existing key 4 is still in &\$cids");
118 * Test that set will propagate.
120 public function testSet() {
121 $this->chain->set('test', 123);
123 $cached = $this->firstBackend->get('test');
124 $this->assertNotSame(FALSE, $cached, 'Test key is in the first backend');
125 $this->assertSame(123, $cached->data, 'Test key has the right value');
127 $cached = $this->secondBackend->get('test');
128 $this->assertNotSame(FALSE, $cached, 'Test key is in the second backend');
129 $this->assertSame(123, $cached->data, 'Test key has the right value');
131 $cached = $this->thirdBackend->get('test');
132 $this->assertNotSame(FALSE, $cached, 'Test key is in the third backend');
133 $this->assertSame(123, $cached->data, 'Test key has the right value');
137 * Test that delete will propagate.
139 public function testDelete() {
140 $this->chain->set('test', 5);
142 $cached = $this->firstBackend->get('test');
143 $this->assertNotSame(FALSE, $cached, 'Test key has been added to the first backend');
144 $cached = $this->secondBackend->get('test');
145 $this->assertNotSame(FALSE, $cached, 'Test key has been added to the first backend');
146 $cached = $this->thirdBackend->get('test');
147 $this->assertNotSame(FALSE, $cached, 'Test key has been added to the first backend');
149 $this->chain->delete('test');
151 $cached = $this->firstBackend->get('test');
152 $this->assertSame(FALSE, $cached, 'Test key is removed from the first backend');
153 $cached = $this->secondBackend->get('test');
154 $this->assertSame(FALSE, $cached, 'Test key is removed from the second backend');
155 $cached = $this->thirdBackend->get('test');
156 $this->assertSame(FALSE, $cached, 'Test key is removed from the third backend');
160 * Ensure get values propagation to previous backends.
162 public function testGetHasPropagated() {
163 $this->chain->get('t23');
164 $cached = $this->firstBackend->get('t23');
165 $this->assertNotSame(FALSE, $cached, 'Test 2 has been propagated to the first backend');
167 $this->chain->get('t3');
168 $cached = $this->firstBackend->get('t3');
169 $this->assertNotSame(FALSE, $cached, 'Test 3 has been propagated to the first backend');
170 $cached = $this->secondBackend->get('t3');
171 $this->assertNotSame(FALSE, $cached, 'Test 3 has been propagated to the second backend');
175 * Ensure get multiple values propagation to previous backends.
177 public function testGetMultipleHasPropagated() {
178 $cids = ['t3', 't23'];
179 $this->chain->getMultiple($cids);
181 $cached = $this->firstBackend->get('t3');
182 $this->assertNotSame(FALSE, $cached, 'Test 3 has been propagated to the first backend');
183 $this->assertSame(33, $cached->data, 'And value has been kept');
184 $cached = $this->secondBackend->get('t3');
185 $this->assertNotSame(FALSE, $cached, 'Test 3 has been propagated to the second backend');
186 $this->assertSame(33, $cached->data, 'And value has been kept');
188 $cached = $this->firstBackend->get('t23');
189 $this->assertNotSame(FALSE, $cached, 'Test 2 has been propagated to the first backend');
190 $this->assertSame(232, $cached->data, 'And value has been kept');
194 * Test that the delete all operation is propagated to all backends in the chain.
196 public function testDeleteAllPropagation() {
197 // Set both expiring and permanent keys.
198 $this->chain->set('test1', 1, Cache::PERMANENT);
199 $this->chain->set('test2', 3, time() + 1000);
200 $this->chain->deleteAll();
202 $this->assertFalse($this->firstBackend->get('test1'), 'First key has been deleted in first backend.');
203 $this->assertFalse($this->firstBackend->get('test2'), 'Second key has been deleted in first backend.');
204 $this->assertFalse($this->secondBackend->get('test1'), 'First key has been deleted in second backend.');
205 $this->assertFalse($this->secondBackend->get('test2'), 'Second key has been deleted in second backend.');
206 $this->assertFalse($this->thirdBackend->get('test1'), 'First key has been deleted in third backend.');
207 $this->assertFalse($this->thirdBackend->get('test2'), 'Second key has been deleted in third backend.');
211 * Test that the delete tags operation is propagated to all backends
214 public function testDeleteTagsPropagation() {
215 // Create two cache entries with the same tag and tag value.
216 $this->chain->set('test_cid_clear1', 'foo', Cache::PERMANENT, ['test_tag:2']);
217 $this->chain->set('test_cid_clear2', 'foo', Cache::PERMANENT, ['test_tag:2']);
218 $this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
219 && $this->firstBackend->get('test_cid_clear2')
220 && $this->secondBackend->get('test_cid_clear1')
221 && $this->secondBackend->get('test_cid_clear2')
222 && $this->thirdBackend->get('test_cid_clear1')
223 && $this->thirdBackend->get('test_cid_clear2'),
224 'Two cache items were created in all backends.');
226 // Invalidate test_tag of value 1. This should invalidate both entries.
227 $this->chain->invalidateTags(['test_tag:2']);
228 $this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear1')
229 && $this->firstBackend->get('test_cid_clear2')
230 && $this->secondBackend->get('test_cid_clear1')
231 && $this->secondBackend->get('test_cid_clear2')
232 && $this->thirdBackend->get('test_cid_clear1')
233 && $this->thirdBackend->get('test_cid_clear2'),
234 'Two caches removed from all backends after clearing a cache tag.');
236 // Create two cache entries with the same tag and an array tag value.
237 $this->chain->set('test_cid_clear1', 'foo', Cache::PERMANENT, ['test_tag:1']);
238 $this->chain->set('test_cid_clear2', 'foo', Cache::PERMANENT, ['test_tag:1']);
239 $this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
240 && $this->firstBackend->get('test_cid_clear2')
241 && $this->secondBackend->get('test_cid_clear1')
242 && $this->secondBackend->get('test_cid_clear2')
243 && $this->thirdBackend->get('test_cid_clear1')
244 && $this->thirdBackend->get('test_cid_clear2'),
245 'Two cache items were created in all backends.');
247 // Invalidate test_tag of value 1. This should invalidate both entries.
248 $this->chain->invalidateTags(['test_tag:1']);
249 $this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear1')
250 && $this->firstBackend->get('test_cid_clear2')
251 && $this->secondBackend->get('test_cid_clear1')
252 && $this->secondBackend->get('test_cid_clear2')
253 && $this->thirdBackend->get('test_cid_clear1')
254 && $this->thirdBackend->get('test_cid_clear2'),
255 'Two caches removed from all backends after clearing a cache tag.');
257 // Create three cache entries with a mix of tags and tag values.
258 $this->chain->set('test_cid_clear1', 'foo', Cache::PERMANENT, ['test_tag:1']);
259 $this->chain->set('test_cid_clear2', 'foo', Cache::PERMANENT, ['test_tag:2']);
260 $this->chain->set('test_cid_clear3', 'foo', Cache::PERMANENT, ['test_tag_foo:3']);
261 $this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
262 && $this->firstBackend->get('test_cid_clear2')
263 && $this->firstBackend->get('test_cid_clear3')
264 && $this->secondBackend->get('test_cid_clear1')
265 && $this->secondBackend->get('test_cid_clear2')
266 && $this->secondBackend->get('test_cid_clear3')
267 && $this->thirdBackend->get('test_cid_clear1')
268 && $this->thirdBackend->get('test_cid_clear2')
269 && $this->thirdBackend->get('test_cid_clear3'),
270 'Three cached items were created in all backends.');
272 $this->chain->invalidateTags(['test_tag_foo:3']);
273 $this->assertNotSame(FALSE, $this->firstBackend->get('test_cid_clear1')
274 && $this->firstBackend->get('test_cid_clear2')
275 && $this->secondBackend->get('test_cid_clear1')
276 && $this->secondBackend->get('test_cid_clear2')
277 && $this->thirdBackend->get('test_cid_clear1')
278 && $this->thirdBackend->get('test_cid_clear2'),
279 'Cached items not matching the tag were not cleared from any of the backends.');
281 $this->assertSame(FALSE, $this->firstBackend->get('test_cid_clear3')
282 && $this->secondBackend->get('test_cid_clear3')
283 && $this->thirdBackend->get('test_cid_clear3'),
284 'Cached item matching the tag was removed from all backends.');
288 * Test that removing bin propagates to all backends.
290 public function testRemoveBin() {
291 $chain = new BackendChain('foo');
292 for ($i = 0; $i < 3; $i++) {
293 $backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
294 $backend->expects($this->once())->method('removeBin');
295 $chain->appendBackend($backend);