TYPO3 CMS  TYPO3_8-7
MemcachedBackendTest.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 
19 
25 class MemcachedBackendTest extends UnitTestCase
26 {
30  protected function setUp()
31  {
32  if (!extension_loaded('memcache') && !extension_loaded('memcached')) {
33  $this->markTestSkipped('Neither "memcache" nor "memcached" extension was available');
34  }
35  if (!getenv('typo3TestingMemcachedHost')) {
36  $this->markTestSkipped('environment variable "typo3TestingMemcachedHost" must be set to run this test');
37  }
38  // Note we assume that if that typo3TestingMemcachedHost env is set, we can use that for testing,
39  // there is no test to see if the daemon is actually up and running. Tests will fail if env
40  // is set but daemon is down.
41  }
42 
46  protected function initializeSubject(): MemcachedBackend
47  {
48  // We know this env is set, otherwise setUp() would skip the tests
49  $memcachedHost = getenv('typo3TestingMemcachedHost');
50  // If typo3TestingMemcachedPort env is set, use it, otherwise fall back to standard port
51  $env = getenv('typo3TestingMemcachedPort');
52  $memcachedPort = is_string($env) ? (int)$env : 11211;
53 
55  $cache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface::class);
56 
57  $subject = new MemcachedBackend('Testing', [ 'servers' => [$memcachedHost . ':' . $memcachedPort] ]);
58  $subject->setCache($cache);
59  $subject->initializeObject();
60  return $subject;
61  }
62 
67  {
68  // We know this env is set, otherwise setUp() would skip the tests
69  $memcachedHost = getenv('typo3TestingMemcachedHost');
70  // If typo3TestingMemcachedPort env is set, use it, otherwise fall back to standard port
71  $env = getenv('typo3TestingMemcachedPort');
72  $memcachedPort = is_string($env) ? (int)$env : 11211;
73 
74  $this->expectException(\TYPO3\CMS\Core\Cache\Exception::class);
75  $this->expectExceptionCode(1207149215);
76 
77  $backend = new MemcachedBackend('Testing', [ 'servers' => [$memcachedHost . ':' . $memcachedPort] ]);
78  $backend->initializeObject();
79  $data = 'Some data';
80  $identifier = $this->getUniqueId('MyIdentifier');
81  $backend->set($identifier, $data);
82  }
83 
88  {
89  $this->expectException(\TYPO3\CMS\Core\Cache\Exception::class);
90  $this->expectExceptionCode(1213115903);
91 
92  $backend = new MemcachedBackend('Testing');
93  $backend->initializeObject();
94  }
95 
100  {
101  $backend = $this->initializeSubject();
102  $data = 'Some data';
103  $identifier = $this->getUniqueId('MyIdentifier');
104  $backend->set($identifier, $data);
105  $inCache = $backend->has($identifier);
106  $this->assertTrue($inCache, 'Memcache failed to set and check entry');
107  }
108 
113  {
114  $backend = $this->initializeSubject();
115  $data = 'Some data';
116  $identifier = $this->getUniqueId('MyIdentifier');
117  $backend->set($identifier, $data);
118  $fetchedData = $backend->get($identifier);
119  $this->assertEquals($data, $fetchedData, 'Memcache failed to set and retrieve data');
120  }
121 
126  {
127  $backend = $this->initializeSubject();
128  $data = 'Some data';
129  $identifier = $this->getUniqueId('MyIdentifier');
130  $backend->set($identifier, $data);
131  $backend->remove($identifier);
132  $inCache = $backend->has($identifier);
133  $this->assertFalse($inCache, 'Failed to set and remove data from Memcache');
134  }
135 
140  {
141  $backend = $this->initializeSubject();
142  $data = 'Some data';
143  $identifier = $this->getUniqueId('MyIdentifier');
144  $backend->set($identifier, $data);
145  $otherData = 'some other data';
146  $backend->set($identifier, $otherData);
147  $fetchedData = $backend->get($identifier);
148  $this->assertEquals($otherData, $fetchedData, 'Memcache failed to overwrite and retrieve data');
149  }
150 
155  {
156  $backend = $this->initializeSubject();
157  $data = 'Some data';
158  $identifier = $this->getUniqueId('MyIdentifier');
159  $backend->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tag2']);
160  $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag1');
161  $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
162  $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
163  $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
164  }
165 
170  {
171  $backend = $this->initializeSubject();
172  $data = 'Some data';
173  $identifier = $this->getUniqueId('MyIdentifier');
174  $backend->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tag2']);
175  $backend->set($identifier, $data, ['UnitTestTag%tag3']);
176  $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tagX');
177  $this->assertEquals([], $retrieved, 'Found entry which should no longer exist.');
178  }
179 
184  {
185  $backend = $this->initializeSubject();
186  $identifier = $this->getUniqueId('NonExistingIdentifier');
187  $inCache = $backend->has($identifier);
188  $this->assertFalse($inCache, '"has" did not return FALSE when checking on non existing identifier');
189  }
190 
195  {
196  $backend = $this->initializeSubject();
197  $identifier = $this->getUniqueId('NonExistingIdentifier');
198  $inCache = $backend->remove($identifier);
199  $this->assertFalse($inCache, '"remove" did not return FALSE when checking on non existing identifier');
200  }
201 
206  {
207  $backend = $this->initializeSubject();
208  $data = 'some data' . microtime();
209  $backend->set('BackendMemcacheTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
210  $backend->set('BackendMemcacheTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
211  $backend->set('BackendMemcacheTest3', $data, ['UnitTestTag%test']);
212  $backend->flushByTag('UnitTestTag%special');
213  $this->assertTrue($backend->has('BackendMemcacheTest1'), 'BackendMemcacheTest1');
214  $this->assertFalse($backend->has('BackendMemcacheTest2'), 'BackendMemcacheTest2');
215  $this->assertTrue($backend->has('BackendMemcacheTest3'), 'BackendMemcacheTest3');
216  }
217 
222  {
223  $backend = $this->initializeSubject();
224  $data = 'some data' . microtime();
225  $backend->set('BackendMemcacheTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
226  $backend->set('BackendMemcacheTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
227  $backend->set('BackendMemcacheTest3', $data, ['UnitTestTag%test']);
228  $backend->flushByTags(['UnitTestTag%special', 'UnitTestTag%boring']);
229  $this->assertFalse($backend->has('BackendMemcacheTest1'), 'BackendMemcacheTest1');
230  $this->assertFalse($backend->has('BackendMemcacheTest2'), 'BackendMemcacheTest2');
231  $this->assertTrue($backend->has('BackendMemcacheTest3'), 'BackendMemcacheTest3');
232  }
233 
237  public function flushRemovesAllCacheEntries()
238  {
239  $backend = $this->initializeSubject();
240  $data = 'some data' . microtime();
241  $backend->set('BackendMemcacheTest1', $data);
242  $backend->set('BackendMemcacheTest2', $data);
243  $backend->set('BackendMemcacheTest3', $data);
244  $backend->flush();
245  $this->assertFalse($backend->has('BackendMemcacheTest1'), 'BackendMemcacheTest1');
246  $this->assertFalse($backend->has('BackendMemcacheTest2'), 'BackendMemcacheTest2');
247  $this->assertFalse($backend->has('BackendMemcacheTest3'), 'BackendMemcacheTest3');
248  }
249 
253  public function flushRemovesOnlyOwnEntries()
254  {
255  // We know this env is set, otherwise setUp() would skip the tests
256  $memcachedHost = getenv('typo3TestingMemcachedHost');
257  // If typo3TestingMemcachedPort env is set, use it, otherwise fall back to standard port
258  $env = getenv('typo3TestingMemcachedPort');
259  $memcachedPort = is_string($env) ? (int)$env : 11211;
260 
262  $thisCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
263  $thisCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thisCache'));
264  $thisBackend = new MemcachedBackend('Testing', [ 'servers' => [$memcachedHost . ':' . $memcachedPort] ]);
265  $thisBackend->setCache($thisCache);
266  $thisBackend->initializeObject();
267 
269  $thatCache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\AbstractFrontend::class);
270  $thatCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thatCache'));
271  $thatBackend = new MemcachedBackend('Testing', [ 'servers' => [$memcachedHost . ':' . $memcachedPort] ]);
272  $thatBackend->setCache($thatCache);
273  $thatBackend->initializeObject();
274  $thisBackend->set('thisEntry', 'Hello');
275  $thatBackend->set('thatEntry', 'World!');
276  $thatBackend->flush();
277  $this->assertEquals('Hello', $thisBackend->get('thisEntry'));
278  $this->assertFalse($thatBackend->has('thatEntry'));
279  }
280 
287  public function largeDataIsStored()
288  {
289  $backend = $this->initializeSubject();
290  $data = str_repeat('abcde', 1024 * 1024);
291  $backend->set('tooLargeData', $data);
292  $this->assertTrue($backend->has('tooLargeData'));
293  $this->assertEquals($backend->get('tooLargeData'), $data);
294  }
295 
299  public function setTagsOnlyOnceToIdentifier()
300  {
301  // We know this env is set, otherwise setUp() would skip the tests
302  $memcachedHost = getenv('typo3TestingMemcachedHost');
303  // If typo3TestingMemcachedPort env is set, use it, otherwise fall back to standard port
304  $env = getenv('typo3TestingMemcachedPort');
305  $memcachedPort = is_string($env) ? (int)$env : 11211;
306 
307  $accessibleClassName = $this->buildAccessibleProxy(MemcachedBackend::class);
308  $backend = new $accessibleClassName('Testing', [ 'servers' => [$memcachedHost . ':' . $memcachedPort] ]);
309 
311  $cache = $this->createMock(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface::class);
312  $backend->setCache($cache);
313  $backend->initializeObject();
314 
315  $identifier = $this->getUniqueId('MyIdentifier');
316  $tags = ['UnitTestTag%test', 'UnitTestTag%boring'];
317 
318  $backend->_call('addIdentifierToTags', $identifier, $tags);
319  $this->assertSame(
320  $tags,
321  $backend->_call('findTagsByIdentifier', $identifier)
322  );
323 
324  $backend->_call('addIdentifierToTags', $identifier, $tags);
325  $this->assertSame(
326  $tags,
327  $backend->_call('findTagsByIdentifier', $identifier)
328  );
329  }
330 }