@@ -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