/vendor/doctrine/cache/tests/Doctrine/Tests/Common/Cache/FileCacheTest.php |
@@ -0,0 +1,268 @@ |
<?php |
|
namespace Doctrine\Tests\Common\Cache; |
|
use Doctrine\Common\Cache\Cache; |
|
/** |
* @group DCOM-101 |
*/ |
class FileCacheTest extends \Doctrine\Tests\DoctrineTestCase |
{ |
/** |
* @var \Doctrine\Common\Cache\FileCache |
*/ |
private $driver; |
|
protected function setUp() |
{ |
$this->driver = $this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array(), '', false |
); |
} |
|
public function testFilenameShouldCreateThePathWithOneSubDirectory() |
{ |
$cache = $this->driver; |
$method = new \ReflectionMethod($cache, 'getFilename'); |
$key = 'item-key'; |
$expectedDir = array( |
'84', |
); |
$expectedDir = implode(DIRECTORY_SEPARATOR, $expectedDir); |
|
$method->setAccessible(true); |
|
$path = $method->invoke($cache, $key); |
$dirname = pathinfo($path, PATHINFO_DIRNAME); |
|
$this->assertEquals(DIRECTORY_SEPARATOR . $expectedDir, $dirname); |
} |
|
public function testFileExtensionCorrectlyEscaped() |
{ |
$driver1 = $this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array(__DIR__, '.*') |
); |
$driver2 = $this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array(__DIR__, '.php') |
); |
|
$doGetStats = new \ReflectionMethod($driver1, 'doGetStats'); |
|
$doGetStats->setAccessible(true); |
|
$stats1 = $doGetStats->invoke($driver1); |
$stats2 = $doGetStats->invoke($driver2); |
|
$this->assertSame(0, $stats1[Cache::STATS_MEMORY_USAGE]); |
$this->assertGreaterThan(0, $stats2[Cache::STATS_MEMORY_USAGE]); |
} |
|
/** |
* @group DCOM-266 |
*/ |
public function testFileExtensionSlashCorrectlyEscaped() |
{ |
$driver = $this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array(__DIR__ . '/../', DIRECTORY_SEPARATOR . basename(__FILE__)) |
); |
|
$doGetStats = new \ReflectionMethod($driver, 'doGetStats'); |
|
$doGetStats->setAccessible(true); |
|
$stats = $doGetStats->invoke($driver); |
|
$this->assertGreaterThan(0, $stats[Cache::STATS_MEMORY_USAGE]); |
} |
|
public function testNonIntUmaskThrowsInvalidArgumentException() |
{ |
$this->setExpectedException('InvalidArgumentException'); |
|
$this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array('', '', 'invalid') |
); |
} |
|
public function testGetDirectoryReturnsRealpathDirectoryString() |
{ |
$directory = __DIR__ . '/../'; |
$driver = $this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array($directory) |
); |
|
$doGetDirectory = new \ReflectionMethod($driver, 'getDirectory'); |
|
$actualDirectory = $doGetDirectory->invoke($driver); |
$expectedDirectory = realpath($directory); |
|
$this->assertEquals($expectedDirectory, $actualDirectory); |
} |
|
public function testGetExtensionReturnsExtensionString() |
{ |
$directory = __DIR__ . '/../'; |
$extension = DIRECTORY_SEPARATOR . basename(__FILE__); |
$driver = $this->getMock( |
'Doctrine\Common\Cache\FileCache', |
array('doFetch', 'doContains', 'doSave'), |
array($directory, $extension) |
); |
|
$doGetExtension = new \ReflectionMethod($driver, 'getExtension'); |
|
$actualExtension = $doGetExtension->invoke($driver); |
|
$this->assertEquals($extension, $actualExtension); |
} |
|
const WIN_MAX_PATH_LEN = 258; |
|
public static function getBasePathForWindowsPathLengthTests($pathLength) |
{ |
// Not using __DIR__ because it can get screwed up when xdebug debugger is attached. |
$basePath = realpath(sys_get_temp_dir()) . '/' . uniqid('doctrine-cache', true); |
|
/** @noinspection MkdirRaceConditionInspection */ |
@mkdir($basePath); |
|
$basePath = realpath($basePath); |
|
// Test whether the desired path length is odd or even. |
$desiredPathLengthIsOdd = ($pathLength % 2) == 1; |
|
// If the cache key is not too long, the filecache codepath will add |
// a slash and bin2hex($key). The length of the added portion will be an odd number. |
// len(desired) = len(base path) + len(slash . bin2hex($key)) |
// odd = even + odd |
// even = odd + odd |
$basePathLengthShouldBeOdd = !$desiredPathLengthIsOdd; |
|
$basePathLengthIsOdd = (strlen($basePath) % 2) == 1; |
|
// If the base path needs to be odd or even where it is not, we add an odd number of |
// characters as a pad. In this case, we're adding '\aa' (or '/aa' depending on platform) |
// This is all to make it so that the key we're testing would result in |
// a path that is exactly the length we want to test IF the path length limit |
// were not in place in FileCache. |
if ($basePathLengthIsOdd != $basePathLengthShouldBeOdd) { |
$basePath .= DIRECTORY_SEPARATOR . "aa"; |
} |
|
return $basePath; |
} |
|
/** |
* @param int $length |
* @param string $basePath |
* |
* @return array |
*/ |
public static function getKeyAndPathFittingLength($length, $basePath) |
{ |
$baseDirLength = strlen($basePath); |
$extensionLength = strlen('.doctrine.cache'); |
$directoryLength = strlen(DIRECTORY_SEPARATOR . 'aa' . DIRECTORY_SEPARATOR); |
$keyLength = $length - ($baseDirLength + $extensionLength + $directoryLength); // - 1 because of slash |
|
$key = str_repeat('a', floor($keyLength / 2)); |
|
$keyHash = hash('sha256', $key); |
|
$keyPath = $basePath |
. DIRECTORY_SEPARATOR |
. substr($keyHash, 0, 2) |
. DIRECTORY_SEPARATOR |
. bin2hex($key) |
. '.doctrine.cache'; |
|
$hashedKeyPath = $basePath |
. DIRECTORY_SEPARATOR |
. substr($keyHash, 0, 2) |
. DIRECTORY_SEPARATOR |
. '_' . $keyHash |
. '.doctrine.cache'; |
|
return array($key, $keyPath, $hashedKeyPath); |
} |
|
public function getPathLengthsToTest() |
{ |
// Windows officially supports 260 bytes including null terminator |
// 259 characters is too large due to PHP bug (https://bugs.php.net/bug.php?id=70943) |
// 260 characters is too large - null terminator is included in allowable length |
return array( |
array(257, false), |
array(258, false), |
array(259, true), |
array(260, true) |
); |
} |
|
/** |
* @runInSeparateProcess |
* @dataProvider getPathLengthsToTest |
* |
* @covers \Doctrine\Common\Cache\FileCache::getFilename |
* |
* @param int $length |
* @param bool $pathShouldBeHashed |
*/ |
public function testWindowsPathLengthLimitationsAreCorrectlyRespected($length, $pathShouldBeHashed) |
{ |
if (! defined('PHP_WINDOWS_VERSION_BUILD')) { |
define('PHP_WINDOWS_VERSION_BUILD', 'Yes, this is the "usual suspect", with the usual limitations'); |
} |
|
$basePath = self::getBasePathForWindowsPathLengthTests($length); |
|
$fileCache = $this->getMockForAbstractClass( |
'Doctrine\Common\Cache\FileCache', |
array($basePath, '.doctrine.cache') |
); |
|
list($key, $keyPath, $hashedKeyPath) = self::getKeyAndPathFittingLength($length, $basePath); |
|
$getFileName = new \ReflectionMethod($fileCache, 'getFilename'); |
|
$getFileName->setAccessible(true); |
|
$this->assertEquals( |
$length, |
strlen($keyPath), |
sprintf('Path expected to be %d characters long is %d characters long', $length, strlen($keyPath)) |
); |
|
if ($pathShouldBeHashed) { |
$keyPath = $hashedKeyPath; |
} |
|
if ($pathShouldBeHashed) { |
$this->assertSame( |
$hashedKeyPath, |
$getFileName->invoke($fileCache, $key), |
'Keys should be hashed correctly if they are over the limit.' |
); |
} else { |
$this->assertSame( |
$keyPath, |
$getFileName->invoke($fileCache, $key), |
'Keys below limit of the allowed length are used directly, unhashed' |
); |
} |
} |
} |