Skip to content

Commit 69fab03

Browse files
author
Bill Schaller
committed
Add rigorous functional test for windows path length limit handling
1 parent e699bf4 commit 69fab03

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

tests/Doctrine/Tests/Common/Cache/BaseFileCacheTest.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,94 @@ protected function isSharedStorage()
5252
{
5353
return false;
5454
}
55+
56+
public function getPathLengthsToTest()
57+
{
58+
// Windows officially supports 260 bytes including null terminator
59+
// 258 bytes available to use due to php bug #70943
60+
// Windows officially supports 260 bytes including null terminator
61+
// 259 characters is too large due to PHP bug (https://bugs.php.net/bug.php?id=70943)
62+
// 260 characters is too large - null terminator is included in allowable length
63+
return array(
64+
array(257, false),
65+
array(258, false),
66+
array(259, true),
67+
array(260, true)
68+
);
69+
}
70+
71+
private static function getBasePathForWindowsPathLengthTests($pathLength)
72+
{
73+
return FileCacheTest::getBasePathForWindowsPathLengthTests($pathLength);
74+
}
75+
76+
private static function getKeyAndPathFittingLength($length)
77+
{
78+
$basePath = self::getBasePathForWindowsPathLengthTests($length);
79+
80+
$baseDirLength = strlen($basePath);
81+
$extensionLength = strlen('.doctrine.cache');
82+
$directoryLength = strlen(DIRECTORY_SEPARATOR . 'aa' . DIRECTORY_SEPARATOR);
83+
$namespaceAndBracketLength = strlen(bin2hex("[][1]"));
84+
$keyLength = $length
85+
- ($baseDirLength
86+
+ $extensionLength
87+
+ $directoryLength
88+
+ $namespaceAndBracketLength);
89+
90+
$key = str_repeat('a', floor($keyLength / 2));
91+
$namespacedKey = '[' . $key . '][1]';
92+
93+
$keyHash = hash('sha256', $namespacedKey);
94+
95+
$keyPath = $basePath
96+
. DIRECTORY_SEPARATOR
97+
. substr($keyHash, 0, 2)
98+
. DIRECTORY_SEPARATOR
99+
. bin2hex($namespacedKey)
100+
. '.doctrine.cache';
101+
102+
$hashedKeyPath = $basePath
103+
. DIRECTORY_SEPARATOR
104+
. substr($keyHash, 0, 2)
105+
. DIRECTORY_SEPARATOR
106+
. '_' . $keyHash
107+
. '.doctrine.cache';
108+
109+
return array($key, $keyPath, $hashedKeyPath);
110+
}
111+
112+
/**
113+
* @dataProvider getPathLengthsToTest
114+
*/
115+
public function testWindowsPathLengthLimitIsCorrectlyHandled($length, $pathShouldBeHashed)
116+
{
117+
$this->directory = self::getBasePathForWindowsPathLengthTests($length);
118+
119+
list($key, $keyPath, $hashedKeyPath) = self::getKeyAndPathFittingLength($length);
120+
121+
$this->assertEquals($length, strlen($keyPath), "Unhashed path should be of correct length.");
122+
123+
$cacheClass = get_class($this->_getCacheDriver());
124+
$cache = new $cacheClass($this->directory, '.doctrine.cache');
125+
126+
// Trick it into thinking this is windows.
127+
$reflClass = new \ReflectionClass('\Doctrine\Common\Cache\FileCache');
128+
$reflProp = $reflClass->getProperty('isRunningOnWindows');
129+
$reflProp->setAccessible(true);
130+
$reflProp->setValue($cache, true);
131+
$reflProp->setAccessible(false);
132+
133+
$cache->save($key, $length);
134+
$fetched = $cache->fetch($key);
135+
$this->assertEquals($length, $fetched);
136+
137+
if ($pathShouldBeHashed) {
138+
$this->assertFileExists($hashedKeyPath, "Path generated for key should be hashed.");
139+
unlink($hashedKeyPath);
140+
} else {
141+
$this->assertFileExists($keyPath, "Path generated for key should not be hashed.");
142+
unlink($keyPath);
143+
}
144+
}
55145
}

0 commit comments

Comments
 (0)