f27d54283a6520951b62fc246f7527065536b304
[yaffs-website] / vendor / doctrine / cache / tests / Doctrine / Tests / Common / Cache / FileCacheTest.php
1 <?php
2
3 namespace Doctrine\Tests\Common\Cache;
4
5 use Doctrine\Common\Cache\Cache;
6
7 /**
8  * @group DCOM-101
9  */
10 class FileCacheTest extends \Doctrine\Tests\DoctrineTestCase
11 {
12     /**
13      * @var \Doctrine\Common\Cache\FileCache
14      */
15     private $driver;
16
17     protected function setUp()
18     {
19         $this->driver = $this->getMock(
20             'Doctrine\Common\Cache\FileCache',
21             array('doFetch', 'doContains', 'doSave'),
22             array(), '', false
23         );
24     }
25
26     public function testFilenameShouldCreateThePathWithOneSubDirectory()
27     {
28         $cache          = $this->driver;
29         $method         = new \ReflectionMethod($cache, 'getFilename');
30         $key            = 'item-key';
31         $expectedDir    = array(
32             '84',
33         );
34         $expectedDir    = implode(DIRECTORY_SEPARATOR, $expectedDir);
35
36         $method->setAccessible(true);
37
38         $path       = $method->invoke($cache, $key);
39         $dirname    = pathinfo($path, PATHINFO_DIRNAME);
40
41         $this->assertEquals(DIRECTORY_SEPARATOR . $expectedDir, $dirname);
42     }
43
44     public function testFileExtensionCorrectlyEscaped()
45     {
46         $driver1 = $this->getMock(
47             'Doctrine\Common\Cache\FileCache',
48             array('doFetch', 'doContains', 'doSave'),
49             array(__DIR__, '.*')
50         );
51         $driver2 = $this->getMock(
52             'Doctrine\Common\Cache\FileCache',
53             array('doFetch', 'doContains', 'doSave'),
54             array(__DIR__, '.php')
55         );
56
57         $doGetStats = new \ReflectionMethod($driver1, 'doGetStats');
58
59         $doGetStats->setAccessible(true);
60
61         $stats1 = $doGetStats->invoke($driver1);
62         $stats2 = $doGetStats->invoke($driver2);
63
64         $this->assertSame(0, $stats1[Cache::STATS_MEMORY_USAGE]);
65         $this->assertGreaterThan(0, $stats2[Cache::STATS_MEMORY_USAGE]);
66     }
67
68     /**
69      * @group DCOM-266
70      */
71     public function testFileExtensionSlashCorrectlyEscaped()
72     {
73         $driver = $this->getMock(
74             'Doctrine\Common\Cache\FileCache',
75             array('doFetch', 'doContains', 'doSave'),
76             array(__DIR__ . '/../', DIRECTORY_SEPARATOR . basename(__FILE__))
77         );
78
79         $doGetStats = new \ReflectionMethod($driver, 'doGetStats');
80
81         $doGetStats->setAccessible(true);
82
83         $stats = $doGetStats->invoke($driver);
84
85         $this->assertGreaterThan(0, $stats[Cache::STATS_MEMORY_USAGE]);
86     }
87
88     public function testNonIntUmaskThrowsInvalidArgumentException()
89     {
90         $this->setExpectedException('InvalidArgumentException');
91
92         $this->getMock(
93             'Doctrine\Common\Cache\FileCache',
94             array('doFetch', 'doContains', 'doSave'),
95             array('', '', 'invalid')
96         );
97     }
98
99     public function testGetDirectoryReturnsRealpathDirectoryString()
100     {
101         $directory = __DIR__ . '/../';
102         $driver = $this->getMock(
103             'Doctrine\Common\Cache\FileCache',
104             array('doFetch', 'doContains', 'doSave'),
105             array($directory)
106         );
107
108         $doGetDirectory = new \ReflectionMethod($driver, 'getDirectory');
109
110         $actualDirectory = $doGetDirectory->invoke($driver);
111         $expectedDirectory = realpath($directory);
112
113         $this->assertEquals($expectedDirectory, $actualDirectory);
114     }
115
116     public function testGetExtensionReturnsExtensionString()
117     {
118         $directory = __DIR__ . '/../';
119         $extension = DIRECTORY_SEPARATOR . basename(__FILE__);
120         $driver = $this->getMock(
121             'Doctrine\Common\Cache\FileCache',
122             array('doFetch', 'doContains', 'doSave'),
123             array($directory, $extension)
124         );
125
126         $doGetExtension = new \ReflectionMethod($driver, 'getExtension');
127
128         $actualExtension = $doGetExtension->invoke($driver);
129
130         $this->assertEquals($extension, $actualExtension);
131     }
132
133     const WIN_MAX_PATH_LEN = 258;
134
135     public static function getBasePathForWindowsPathLengthTests($pathLength)
136     {
137         // Not using __DIR__ because it can get screwed up when xdebug debugger is attached.
138         $basePath = realpath(sys_get_temp_dir()) . '/' . uniqid('doctrine-cache', true);
139
140         /** @noinspection MkdirRaceConditionInspection */
141         @mkdir($basePath);
142
143         $basePath = realpath($basePath);
144
145         // Test whether the desired path length is odd or even.
146         $desiredPathLengthIsOdd = ($pathLength % 2) == 1;
147
148         // If the cache key is not too long, the filecache codepath will add
149         // a slash and bin2hex($key). The length of the added portion will be an odd number.
150         // len(desired) = len(base path) + len(slash . bin2hex($key))
151         //          odd = even           + odd
152         //         even = odd            + odd
153         $basePathLengthShouldBeOdd = !$desiredPathLengthIsOdd;
154
155         $basePathLengthIsOdd = (strlen($basePath) % 2) == 1;
156
157         // If the base path needs to be odd or even where it is not, we add an odd number of
158         // characters as a pad. In this case, we're adding '\aa' (or '/aa' depending on platform)
159         // This is all to make it so that the key we're testing would result in
160         // a path that is exactly the length we want to test IF the path length limit
161         // were not in place in FileCache.
162         if ($basePathLengthIsOdd != $basePathLengthShouldBeOdd) {
163             $basePath .= DIRECTORY_SEPARATOR . "aa";
164         }
165
166         return $basePath;
167     }
168
169     /**
170      * @param int    $length
171      * @param string $basePath
172      *
173      * @return array
174      */
175     public static function getKeyAndPathFittingLength($length, $basePath)
176     {
177         $baseDirLength = strlen($basePath);
178         $extensionLength = strlen('.doctrine.cache');
179         $directoryLength = strlen(DIRECTORY_SEPARATOR . 'aa' . DIRECTORY_SEPARATOR);
180         $keyLength = $length - ($baseDirLength + $extensionLength + $directoryLength); // - 1 because of slash
181
182         $key = str_repeat('a', floor($keyLength / 2));
183
184         $keyHash = hash('sha256', $key);
185
186         $keyPath = $basePath
187             . DIRECTORY_SEPARATOR
188             . substr($keyHash, 0, 2)
189             . DIRECTORY_SEPARATOR
190             . bin2hex($key)
191             . '.doctrine.cache';
192
193         $hashedKeyPath = $basePath
194             . DIRECTORY_SEPARATOR
195             . substr($keyHash, 0, 2)
196             . DIRECTORY_SEPARATOR
197             . '_' . $keyHash
198             . '.doctrine.cache';
199
200         return array($key, $keyPath, $hashedKeyPath);
201     }
202
203     public function getPathLengthsToTest()
204     {
205         // Windows officially supports 260 bytes including null terminator
206         // 259 characters is too large due to PHP bug (https://bugs.php.net/bug.php?id=70943)
207         // 260 characters is too large - null terminator is included in allowable length
208         return array(
209             array(257, false),
210             array(258, false),
211             array(259, true),
212             array(260, true)
213         );
214     }
215
216     /**
217      * @runInSeparateProcess
218      * @dataProvider getPathLengthsToTest
219      *
220      * @covers \Doctrine\Common\Cache\FileCache::getFilename
221      *
222      * @param int  $length
223      * @param bool $pathShouldBeHashed
224      */
225     public function testWindowsPathLengthLimitationsAreCorrectlyRespected($length, $pathShouldBeHashed)
226     {
227         if (! defined('PHP_WINDOWS_VERSION_BUILD')) {
228             define('PHP_WINDOWS_VERSION_BUILD', 'Yes, this is the "usual suspect", with the usual limitations');
229         }
230
231         $basePath = self::getBasePathForWindowsPathLengthTests($length);
232
233         $fileCache = $this->getMockForAbstractClass(
234             'Doctrine\Common\Cache\FileCache',
235             array($basePath, '.doctrine.cache')
236         );
237
238         list($key, $keyPath, $hashedKeyPath) = self::getKeyAndPathFittingLength($length, $basePath);
239
240         $getFileName = new \ReflectionMethod($fileCache, 'getFilename');
241
242         $getFileName->setAccessible(true);
243
244         $this->assertEquals(
245             $length,
246             strlen($keyPath),
247             sprintf('Path expected to be %d characters long is %d characters long', $length, strlen($keyPath))
248         );
249
250         if ($pathShouldBeHashed) {
251             $keyPath = $hashedKeyPath;
252         }
253
254         if ($pathShouldBeHashed) {
255             $this->assertSame(
256                 $hashedKeyPath,
257                 $getFileName->invoke($fileCache, $key),
258                 'Keys should be hashed correctly if they are over the limit.'
259             );
260         } else {
261             $this->assertSame(
262                 $keyPath,
263                 $getFileName->invoke($fileCache, $key),
264                 'Keys below limit of the allowed length are used directly, unhashed'
265             );
266         }
267     }
268 }