BaseFileCacheTest.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. namespace Doctrine\Tests\Common\Cache;
  3. use Doctrine\Common\Cache\FileCache;
  4. use RecursiveDirectoryIterator;
  5. use RecursiveIteratorIterator;
  6. abstract class BaseFileCacheTest extends CacheTest
  7. {
  8. protected $directory;
  9. protected function setUp()
  10. {
  11. do {
  12. $this->directory = sys_get_temp_dir() . '/doctrine_cache_'. uniqid();
  13. } while (file_exists($this->directory));
  14. }
  15. protected function tearDown()
  16. {
  17. if ( ! is_dir($this->directory)) {
  18. return;
  19. }
  20. $iterator = new RecursiveDirectoryIterator($this->directory);
  21. foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file) {
  22. if ($file->isFile()) {
  23. @unlink($file->getRealPath());
  24. } elseif ($file->isDir()) {
  25. @rmdir($file->getRealPath());
  26. }
  27. }
  28. @rmdir($this->directory);
  29. }
  30. public function testFlushAllRemovesBalancingDirectories()
  31. {
  32. $cache = $this->_getCacheDriver();
  33. $this->assertTrue($cache->save('key1', 1));
  34. $this->assertTrue($cache->save('key2', 2));
  35. $this->assertTrue($cache->flushAll());
  36. $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST);
  37. $this->assertCount(0, $iterator);
  38. }
  39. protected function isSharedStorage()
  40. {
  41. return false;
  42. }
  43. public function getPathLengthsToTest()
  44. {
  45. // Windows officially supports 260 bytes including null terminator
  46. // 258 bytes available to use due to php bug #70943
  47. // Windows officially supports 260 bytes including null terminator
  48. // 259 characters is too large due to PHP bug (https://bugs.php.net/bug.php?id=70943)
  49. // 260 characters is too large - null terminator is included in allowable length
  50. return array(
  51. array(257, false),
  52. array(258, false),
  53. array(259, true),
  54. array(260, true)
  55. );
  56. }
  57. private static function getBasePathForWindowsPathLengthTests($pathLength)
  58. {
  59. return FileCacheTest::getBasePathForWindowsPathLengthTests($pathLength);
  60. }
  61. /**
  62. * @param int $length
  63. * @param string $basePath
  64. *
  65. * @return array
  66. */
  67. private static function getKeyAndPathFittingLength($length, $basePath)
  68. {
  69. $baseDirLength = strlen($basePath);
  70. $extensionLength = strlen('.doctrine.cache');
  71. $directoryLength = strlen(DIRECTORY_SEPARATOR . 'aa' . DIRECTORY_SEPARATOR);
  72. $namespaceAndBracketLength = strlen(bin2hex("[][1]"));
  73. $keyLength = $length
  74. - ($baseDirLength
  75. + $extensionLength
  76. + $directoryLength
  77. + $namespaceAndBracketLength);
  78. $key = str_repeat('a', floor($keyLength / 2));
  79. $namespacedKey = '[' . $key . '][1]';
  80. $keyHash = hash('sha256', $namespacedKey);
  81. $keyPath = $basePath
  82. . DIRECTORY_SEPARATOR
  83. . substr($keyHash, 0, 2)
  84. . DIRECTORY_SEPARATOR
  85. . bin2hex($namespacedKey)
  86. . '.doctrine.cache';
  87. $hashedKeyPath = $basePath
  88. . DIRECTORY_SEPARATOR
  89. . substr($keyHash, 0, 2)
  90. . DIRECTORY_SEPARATOR
  91. . '_' . $keyHash
  92. . '.doctrine.cache';
  93. return array($key, $keyPath, $hashedKeyPath);
  94. }
  95. /**
  96. * @dataProvider getPathLengthsToTest
  97. *
  98. * @param int $length
  99. * @param bool $pathShouldBeHashed
  100. */
  101. public function testWindowsPathLengthLimitIsCorrectlyHandled($length, $pathShouldBeHashed)
  102. {
  103. $this->directory = self::getBasePathForWindowsPathLengthTests($length);
  104. list($key, $keyPath, $hashedKeyPath) = self::getKeyAndPathFittingLength($length, $this->directory);
  105. $this->assertEquals($length, strlen($keyPath), 'Unhashed path should be of correct length.');
  106. $cacheClass = get_class($this->_getCacheDriver());
  107. /* @var $cache \Doctrine\Common\Cache\FileCache */
  108. $cache = new $cacheClass($this->directory, '.doctrine.cache');
  109. // Trick it into thinking this is windows.
  110. $reflClass = new \ReflectionClass(FileCache::class);
  111. $reflProp = $reflClass->getProperty('isRunningOnWindows');
  112. $reflProp->setAccessible(true);
  113. $reflProp->setValue($cache, true);
  114. $reflProp->setAccessible(false);
  115. $value = uniqid('value', true);
  116. $cache->save($key, $value);
  117. $this->assertEquals($value, $cache->fetch($key));
  118. if ($pathShouldBeHashed) {
  119. $this->assertFileExists($hashedKeyPath, 'Path generated for key should be hashed.');
  120. unlink($hashedKeyPath);
  121. } else {
  122. $this->assertFileExists($keyPath, 'Path generated for key should not be hashed.');
  123. unlink($keyPath);
  124. }
  125. }
  126. }