[!!!][TASK] Remove obsolete APC Cache Backend 88/59588/11
authorJosef Glatz <josefglatz@gmail.com>
Wed, 30 Jan 2019 11:02:50 +0000 (12:02 +0100)
committerBenni Mack <benni@typo3.org>
Tue, 5 Feb 2019 18:54:30 +0000 (19:54 +0100)
All occurrences of APC (without suffix "u") are removed from the
TYPO3 core since APC is discontinued and does not work with
PHP 7.x.

This changes does not affect the PHP OPcache related area.

Releases: master
Resolves: #87583
Change-Id: Ie724f8343dae9bdc4721d35c6d384c1de51f365e
Reviewed-on: https://review.typo3.org/59588
Tested-by: TYPO3com <noreply@typo3.com>
Reviewed-by: Alexander Opitz <opitz.alexander@googlemail.com>
Tested-by: Alexander Opitz <opitz.alexander@googlemail.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Classes/Cache/Backend/ApcBackend.php [deleted file]
typo3/sysext/core/Documentation/Changelog/master/Breaking-87583-RemoveObsoleteAPCCacheBackendImplementation.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Cache/Backend/ApcBackendTest.php [deleted file]

diff --git a/typo3/sysext/core/Classes/Cache/Backend/ApcBackend.php b/typo3/sysext/core/Classes/Cache/Backend/ApcBackend.php
deleted file mode 100644 (file)
index 65d181c..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\Cache\Backend;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Cache\Exception;
-use TYPO3\CMS\Core\Cache\Exception\InvalidDataException;
-use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
-use TYPO3\CMS\Core\Core\Environment;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * A caching backend which stores cache entries by using APC.
- *
- * This backend uses the following types of keys:
- * - tag_xxx
- * xxx is tag name, value is array of associated identifiers identifier. This
- * is "forward" tag index. It is mainly used for obtaining content by tag
- * (get identifier by tag -> get content by identifier)
- * - ident_xxx
- * xxx is identifier, value is array of associated tags. This is "reverse" tag
- * index. It provides quick access for all tags associated with this identifier
- * and used when removing the identifier
- *
- * Each key is prepended with a prefix. By default prefix consists from two parts
- * separated by underscore character and ends in yet another underscore character:
- * - "TYPO3"
- * - MD5 of path to TYPO3 project folder and user running TYPO3
- * This prefix makes sure that keys from the different installations do not
- * conflict.
- */
-class ApcBackend extends AbstractBackend implements TaggableBackendInterface
-{
-    /**
-     * A prefix to separate stored data from other data possible stored in the APC
-     *
-     * @var string
-     */
-    protected $identifierPrefix;
-
-    /**
-     * Set the cache identifier prefix.
-     *
-     * @param string $identifierPrefix
-     */
-    protected function setIdentifierPrefix($identifierPrefix)
-    {
-        $this->identifierPrefix = $identifierPrefix;
-    }
-
-    /**
-     * Retrieves the cache identifier prefix.
-     *
-     * @return string
-     */
-    protected function getIdentifierPrefix()
-    {
-        return $this->identifierPrefix;
-    }
-
-    /**
-     * Constructs this backend
-     *
-     * @param string $context Unused, for backward compatibility only
-     * @param array $options Configuration options - unused here
-     * @throws Exception
-     */
-    public function __construct($context, array $options = [])
-    {
-        if (!extension_loaded('apc')) {
-            throw new Exception('The PHP extension "apc" or "apcu" must be installed and loaded in order to use the APC backend.', 1232985414);
-        }
-        if (PHP_SAPI === 'cli' && ini_get('apc.enable_cli') == 0) {
-            throw new Exception('The APC backend cannot be used because apc is disabled on CLI.', 1232985415);
-        }
-        parent::__construct($context, $options);
-    }
-
-    /**
-     * Initializes the identifier prefix when setting the cache.
-     *
-     * @param FrontendInterface $cache
-     */
-    public function setCache(FrontendInterface $cache)
-    {
-        parent::setCache($cache);
-        $processUser = $this->getCurrentUserData();
-        $pathHash = GeneralUtility::shortMD5(Environment::getProjectPath() . $processUser['name'] . $this->context . $cache->getIdentifier(), 12);
-        $this->setIdentifierPrefix('TYPO3_' . $pathHash);
-    }
-
-    /**
-     * Returns the current user data with posix_getpwuid or a default structure when
-     * posix_getpwuid is not available.
-     *
-     * @return array
-     */
-    protected function getCurrentUserData()
-    {
-        return extension_loaded('posix') ? posix_getpwuid(posix_geteuid()) : ['name' => 'default'];
-    }
-
-    /**
-     * Saves data in the cache.
-     *
-     * @param string $entryIdentifier An identifier for this specific cache entry
-     * @param string $data The data to be stored
-     * @param array $tags Tags to associate with this cache entry
-     * @param int $lifetime Lifetime of this cache entry in seconds. If NULL is specified, the default lifetime is used. "0" means unlimited lifetime.
-     * @throws Exception if no cache frontend has been set.
-     * @throws InvalidDataException if $data is not a string
-     */
-    public function set($entryIdentifier, $data, array $tags = [], $lifetime = null)
-    {
-        if (!$this->cache instanceof FrontendInterface) {
-            throw new Exception('No cache frontend has been set yet via setCache().', 1232986818);
-        }
-        if (!is_string($data)) {
-            throw new InvalidDataException('The specified data is of type "' . gettype($data) . '" but a string is expected.', 1232986825);
-        }
-        $tags[] = '%APCBE%' . $this->cacheIdentifier;
-        $expiration = $lifetime ?? $this->defaultLifetime;
-        $success = apc_store($this->getIdentifierPrefix() . $entryIdentifier, $data, $expiration);
-        if ($success === true) {
-            $this->removeIdentifierFromAllTags($entryIdentifier);
-            $this->addIdentifierToTags($entryIdentifier, $tags);
-        } else {
-            $this->logger->alert('Error using APCu: Could not save data in the cache.');
-        }
-    }
-
-    /**
-     * Loads data from the cache.
-     *
-     * @param string $entryIdentifier An identifier which describes the cache entry to load
-     * @return mixed The cache entry's content as a string or FALSE if the cache entry could not be loaded
-     */
-    public function get($entryIdentifier)
-    {
-        $success = false;
-        $value = apc_fetch($this->getIdentifierPrefix() . $entryIdentifier, $success);
-        return $success ? $value : $success;
-    }
-
-    /**
-     * Checks if a cache entry with the specified identifier exists.
-     *
-     * @param string $entryIdentifier An identifier specifying the cache entry
-     * @return bool TRUE if such an entry exists, FALSE if not
-     */
-    public function has($entryIdentifier)
-    {
-        $success = false;
-        apc_fetch($this->getIdentifierPrefix() . $entryIdentifier, $success);
-        return $success;
-    }
-
-    /**
-     * Removes all cache entries matching the specified identifier.
-     * Usually this only affects one entry but if - for what reason ever -
-     * old entries for the identifier still exist, they are removed as well.
-     *
-     * @param string $entryIdentifier Specifies the cache entry to remove
-     * @return bool TRUE if (at least) an entry could be removed or FALSE if no entry was found
-     */
-    public function remove($entryIdentifier)
-    {
-        $this->removeIdentifierFromAllTags($entryIdentifier);
-        return apc_delete($this->getIdentifierPrefix() . $entryIdentifier);
-    }
-
-    /**
-     * Finds and returns all cache entry identifiers which are tagged by the
-     * specified tag.
-     *
-     * @param string $tag The tag to search for
-     * @return array An array with identifiers of all matching entries. An empty array if no entries matched
-     */
-    public function findIdentifiersByTag($tag)
-    {
-        $success = false;
-        $identifiers = apc_fetch($this->getIdentifierPrefix() . 'tag_' . $tag, $success);
-        if ($success === false) {
-            return [];
-        }
-        return (array)$identifiers;
-    }
-
-    /**
-     * Finds all tags for the given identifier. This function uses reverse tag
-     * index to search for tags.
-     *
-     * @param string $identifier Identifier to find tags by
-     * @return array Array with tags
-     */
-    protected function findTagsByIdentifier($identifier)
-    {
-        $success = false;
-        $tags = apc_fetch($this->getIdentifierPrefix() . 'ident_' . $identifier, $success);
-        return $success ? (array)$tags : [];
-    }
-
-    /**
-     * Removes all cache entries of this cache.
-     *
-     * @throws Exception
-     */
-    public function flush()
-    {
-        if (!$this->cache instanceof FrontendInterface) {
-            throw new Exception('Yet no cache frontend has been set via setCache().', 1232986971);
-        }
-        $this->flushByTag('%APCBE%' . $this->cacheIdentifier);
-    }
-
-    /**
-     * Removes all cache entries of this cache which are tagged by the specified tag.
-     *
-     * @param string $tag The tag the entries must have
-     */
-    public function flushByTag($tag)
-    {
-        $identifiers = $this->findIdentifiersByTag($tag);
-        foreach ($identifiers as $identifier) {
-            $this->remove($identifier);
-        }
-    }
-
-    /**
-     * Associates the identifier with the given tags
-     *
-     * @param string $entryIdentifier
-     * @param array $tags
-     */
-    protected function addIdentifierToTags($entryIdentifier, array $tags)
-    {
-        // Get identifier-to-tag index to look for updates
-        $existingTags = $this->findTagsByIdentifier($entryIdentifier);
-        $existingTagsUpdated = false;
-
-        foreach ($tags as $tag) {
-            // Update tag-to-identifier index
-            $identifiers = $this->findIdentifiersByTag($tag);
-            if (!in_array($entryIdentifier, $identifiers, true)) {
-                $identifiers[] = $entryIdentifier;
-                apc_store($this->getIdentifierPrefix() . 'tag_' . $tag, $identifiers);
-            }
-            // Test if identifier-to-tag index needs update
-            if (!in_array($tag, $existingTags, true)) {
-                $existingTags[] = $tag;
-                $existingTagsUpdated = true;
-            }
-        }
-
-        // Update identifier-to-tag index if needed
-        if ($existingTagsUpdated) {
-            apc_store($this->getIdentifierPrefix() . 'ident_' . $entryIdentifier, $existingTags);
-        }
-    }
-
-    /**
-     * Removes association of the identifier with the given tags
-     *
-     * @param string $entryIdentifier
-     */
-    protected function removeIdentifierFromAllTags($entryIdentifier)
-    {
-        // Get tags for this identifier
-        $tags = $this->findTagsByIdentifier($entryIdentifier);
-        // Deassociate tags with this identifier
-        foreach ($tags as $tag) {
-            $identifiers = $this->findIdentifiersByTag($tag);
-            // Formally array_search() below should never return FALSE due to
-            // the behavior of findTagsByIdentifier(). But if reverse index is
-            // corrupted, we still can get 'FALSE' from array_search(). This is
-            // not a problem because we are removing this identifier from
-            // anywhere.
-            if (($key = array_search($entryIdentifier, $identifiers)) !== false) {
-                unset($identifiers[$key]);
-                if (!empty($identifiers)) {
-                    apc_store($this->getIdentifierPrefix() . 'tag_' . $tag, $identifiers);
-                } else {
-                    apc_delete($this->getIdentifierPrefix() . 'tag_' . $tag);
-                }
-            }
-        }
-        // Clear reverse tag index for this identifier
-        apc_delete($this->getIdentifierPrefix() . 'ident_' . $entryIdentifier);
-    }
-
-    /**
-     * Does nothing, as APC does GC itself
-     */
-    public function collectGarbage()
-    {
-    }
-}
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-87583-RemoveObsoleteAPCCacheBackendImplementation.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-87583-RemoveObsoleteAPCCacheBackendImplementation.rst
new file mode 100644 (file)
index 0000000..4e5685f
--- /dev/null
@@ -0,0 +1,43 @@
+.. include:: ../../Includes.txt
+
+===================================================================
+Breaking: #87583 - Remove obsolete APC Cache Backend implementation
+===================================================================
+
+See :issue:`87583`
+
+Description
+===========
+
+The Caching framework backend implementation :php:`\TYPO3\CMS\Core\Cache\Backend\ApcBackend` has
+been removed. The APCu PHP extension has superseded in PHP 7.x.
+
+Impact
+======
+
+The PHP APC extension works until PHP 5.x. APCu can be used as "drop-in" replacement since TYPO3 8
+LTS which supports PHP 7.0+.
+
+Affected Installations
+======================
+
+Any installation which has been updated, and any legacy APC cache backend is configured (see
+LocalConfiguration).
+
+Migration
+=========
+
+Use APCu implementation, which is implented via :php:`\TYPO3\CMS\Core\Cache\Backend\ApcuBackend`
+instead of :php:`\TYPO3\CMS\Core\Cache\Backend\ApcBackend` in your caching framework
+configuration.
+
+Example before:
+
+:php:`$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_rootline']['backend'] = \TYPO3\CMS\Core\Cache\Backend\ApcBackend::class;`
+
+Example after:
+
+:php:`$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['cache_rootline']['backend'] = \TYPO3\CMS\Core\Cache\Backend\ApcuBackend::class;`
+
+
+.. index:: Backend, PHP-API, ext:core, NotScanned
diff --git a/typo3/sysext/core/Tests/Unit/Cache/Backend/ApcBackendTest.php b/typo3/sysext/core/Tests/Unit/Cache/Backend/ApcBackendTest.php
deleted file mode 100644 (file)
index 6f5131b..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-<?php
-namespace TYPO3\CMS\Core\Tests\Unit\Cache\Backend;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Cache\Backend\ApcBackend;
-use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
-use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
-
-/**
- * Testcase for the APC cache backend.
- *
- * NOTE: If you want to execute these tests you need to enable apc in
- * cli context (apc.enable_cli = 1)
- */
-class ApcBackendTest extends UnitTestCase
-{
-    /**
-     * Sets up this testcase
-     */
-    protected function setUp()
-    {
-        // Currently APCu identifies itself both as "apcu" and "apc" (for compatibility) although it doesn't provide the APC-opcache functionality
-        if (!extension_loaded('apc') || ini_get('apc.enabled') == 0 || ini_get('apc.enable_cli') == 0) {
-            $this->markTestSkipped('APC/APCu extension was not available, or it was disabled for CLI.');
-        }
-        if (ini_get('apc.slam_defense') == 1) {
-            $this->markTestSkipped('This testcase can only be executed with apc.slam_defense = Off');
-        }
-    }
-
-    /**
-     * @test
-     */
-    public function setThrowsExceptionIfNoFrontEndHasBeenSet()
-    {
-        $backend = new ApcBackend('Testing');
-        $data = 'Some data';
-        $identifier = $this->getUniqueId('MyIdentifier');
-        $this->expectException(\TYPO3\CMS\Core\Cache\Exception::class);
-        $this->expectExceptionCode(1232986818);
-        $backend->set($identifier, $data);
-    }
-
-    /**
-     * @test
-     */
-    public function itIsPossibleToSetAndCheckExistenceInCache()
-    {
-        $backend = $this->setUpBackend();
-        $data = 'Some data';
-        $identifier = $this->getUniqueId('MyIdentifier');
-        $backend->set($identifier, $data);
-        $inCache = $backend->has($identifier);
-        $this->assertTrue($inCache, 'APC backend failed to set and check entry');
-    }
-
-    /**
-     * @test
-     */
-    public function itIsPossibleToSetAndGetEntry()
-    {
-        $backend = $this->setUpBackend();
-        $data = 'Some data';
-        $identifier = $this->getUniqueId('MyIdentifier');
-        $backend->set($identifier, $data);
-        $fetchedData = $backend->get($identifier);
-        $this->assertEquals($data, $fetchedData, 'APC backend failed to set and retrieve data');
-    }
-
-    /**
-     * @test
-     */
-    public function itIsPossibleToRemoveEntryFromCache()
-    {
-        $backend = $this->setUpBackend();
-        $data = 'Some data';
-        $identifier = $this->getUniqueId('MyIdentifier');
-        $backend->set($identifier, $data);
-        $backend->remove($identifier);
-        $inCache = $backend->has($identifier);
-        $this->assertFalse($inCache, 'Failed to set and remove data from APC backend');
-    }
-
-    /**
-     * @test
-     */
-    public function itIsPossibleToOverwriteAnEntryInTheCache()
-    {
-        $backend = $this->setUpBackend();
-        $data = 'Some data';
-        $identifier = $this->getUniqueId('MyIdentifier');
-        $backend->set($identifier, $data);
-        $otherData = 'some other data';
-        $backend->set($identifier, $otherData);
-        $fetchedData = $backend->get($identifier);
-        $this->assertEquals($otherData, $fetchedData, 'APC backend failed to overwrite and retrieve data');
-    }
-
-    /**
-     * @test
-     */
-    public function findIdentifiersByTagFindsSetEntries()
-    {
-        $backend = $this->setUpBackend();
-        $data = 'Some data';
-        $identifier = $this->getUniqueId('MyIdentifier');
-        $backend->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tag2']);
-        $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag1');
-        $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
-        $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tag2');
-        $this->assertEquals($identifier, $retrieved[0], 'Could not retrieve expected entry by tag.');
-    }
-
-    /**
-     * @test
-     */
-    public function setRemovesTagsFromPreviousSet()
-    {
-        $backend = $this->setUpBackend();
-        $data = 'Some data';
-        $identifier = $this->getUniqueId('MyIdentifier');
-        $backend->set($identifier, $data, ['UnitTestTag%tag1', 'UnitTestTag%tagX']);
-        $backend->set($identifier, $data, ['UnitTestTag%tag3']);
-        $retrieved = $backend->findIdentifiersByTag('UnitTestTag%tagX');
-        $this->assertEquals([], $retrieved, 'Found entry which should no longer exist.');
-    }
-
-    /**
-     * @test
-     */
-    public function hasReturnsFalseIfTheEntryDoesNotExist()
-    {
-        $backend = $this->setUpBackend();
-        $identifier = $this->getUniqueId('NonExistingIdentifier');
-        $inCache = $backend->has($identifier);
-        $this->assertFalse($inCache, '"has" did not return FALSE when checking on non existing identifier');
-    }
-
-    /**
-     * @test
-     */
-    public function removeReturnsFalseIfTheEntryDoesntExist()
-    {
-        $backend = $this->setUpBackend();
-        $identifier = $this->getUniqueId('NonExistingIdentifier');
-        $inCache = $backend->remove($identifier);
-        $this->assertFalse($inCache, '"remove" did not return FALSE when checking on non existing identifier');
-    }
-
-    /**
-     * @test
-     */
-    public function flushByTagRemovesCacheEntriesWithSpecifiedTag()
-    {
-        $backend = $this->setUpBackend();
-        $data = 'some data' . microtime();
-        $backend->set('BackendAPCTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
-        $backend->set('BackendAPCTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
-        $backend->set('BackendAPCTest3', $data, ['UnitTestTag%test']);
-        $backend->flushByTag('UnitTestTag%special');
-        $this->assertTrue($backend->has('BackendAPCTest1'), 'BackendAPCTest1');
-        $this->assertFalse($backend->has('BackendAPCTest2'), 'BackendAPCTest2');
-        $this->assertTrue($backend->has('BackendAPCTest3'), 'BackendAPCTest3');
-    }
-
-    /**
-     * @test
-     */
-    public function flushByTagsRemovesCacheEntriesWithSpecifiedTags()
-    {
-        $backend = $this->setUpBackend();
-        $data = 'some data' . microtime();
-        $backend->set('BackendAPCTest1', $data, ['UnitTestTag%test', 'UnitTestTag%boring']);
-        $backend->set('BackendAPCTest2', $data, ['UnitTestTag%test', 'UnitTestTag%special']);
-        $backend->set('BackendAPCTest3', $data, ['UnitTestTag%test']);
-        $backend->flushByTags(['UnitTestTag%special', 'UnitTestTag%boring']);
-        $this->assertFalse($backend->has('BackendAPCTest1'), 'BackendAPCTest1');
-        $this->assertFalse($backend->has('BackendAPCTest2'), 'BackendAPCTest2');
-        $this->assertTrue($backend->has('BackendAPCTest3'), 'BackendAPCTest3');
-    }
-
-    /**
-     * @test
-     */
-    public function flushRemovesAllCacheEntries()
-    {
-        $backend = $this->setUpBackend();
-        $data = 'some data' . microtime();
-        $backend->set('BackendAPCTest1', $data);
-        $backend->set('BackendAPCTest2', $data);
-        $backend->set('BackendAPCTest3', $data);
-        $backend->flush();
-        $this->assertFalse($backend->has('BackendAPCTest1'), 'BackendAPCTest1');
-        $this->assertFalse($backend->has('BackendAPCTest2'), 'BackendAPCTest2');
-        $this->assertFalse($backend->has('BackendAPCTest3'), 'BackendAPCTest3');
-    }
-
-    /**
-     * @test
-     */
-    public function flushRemovesOnlyOwnEntries()
-    {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|FrontendInterface $thisCache */
-        $thisCache = $this->createMock(FrontendInterface::class);
-        $thisCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thisCache'));
-        $thisBackend = new ApcBackend('Testing');
-        $thisBackend->setCache($thisCache);
-
-        /** @var \PHPUnit_Framework_MockObject_MockObject|FrontendInterface $thatCache */
-        $thatCache = $this->createMock(FrontendInterface::class);
-        $thatCache->expects($this->any())->method('getIdentifier')->will($this->returnValue('thatCache'));
-        $thatBackend = new ApcBackend('Testing');
-        $thatBackend->setCache($thatCache);
-        $thisBackend->set('thisEntry', 'Hello');
-        $thatBackend->set('thatEntry', 'World!');
-        $thatBackend->flush();
-        $this->assertEquals('Hello', $thisBackend->get('thisEntry'));
-        $this->assertFalse($thatBackend->has('thatEntry'));
-    }
-
-    /**
-     * Check if we can store ~5 MB of data
-     *
-     * @test
-     */
-    public function largeDataIsStored()
-    {
-        $backend = $this->setUpBackend();
-        $data = str_repeat('abcde', 1024 * 1024);
-        $identifier = $this->getUniqueId('tooLargeData');
-        $backend->set($identifier, $data);
-        $this->assertTrue($backend->has($identifier));
-        $this->assertEquals($backend->get($identifier), $data);
-    }
-
-    /**
-     * @test
-     */
-    public function setTagsOnlyOnceToIdentifier()
-    {
-        $identifier = $this->getUniqueId('MyIdentifier');
-        $tags = ['UnitTestTag%test', 'UnitTestTag%boring'];
-
-        $backend = $this->setUpBackend(true);
-        $backend->_call('addIdentifierToTags', $identifier, $tags);
-        $this->assertSame(
-            $tags,
-            $backend->_call('findTagsByIdentifier', $identifier)
-        );
-
-        $backend->_call('addIdentifierToTags', $identifier, $tags);
-        $this->assertSame(
-            $tags,
-            $backend->_call('findTagsByIdentifier', $identifier)
-        );
-    }
-
-    /**
-     * Sets up the APC backend used for testing
-     *
-     * @param bool $accessible TRUE if backend should be encapsulated in accessible proxy otherwise FALSE.
-     * @return \TYPO3\TestingFramework\Core\AccessibleObjectInterface|ApcBackend
-     */
-    protected function setUpBackend($accessible = false)
-    {
-        /** @var \PHPUnit_Framework_MockObject_MockObject|FrontendInterface $cache */
-        $cache = $this->createMock(FrontendInterface::class);
-        if ($accessible) {
-            $accessibleClassName = $this->buildAccessibleProxy(ApcBackend::class);
-            $backend = new $accessibleClassName('Testing');
-        } else {
-            $backend = new ApcBackend('Testing');
-        }
-        $backend->setCache($cache);
-        return $backend;
-    }
-}