Completed
Push — master ( a8b991...dda2b8 )
by Marco
06:05 queued 02:56
created

BaseFileCacheTest   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3
Metric Value
wmc 14
lcom 1
cbo 3
dl 0
loc 138
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 6 2
B tearDown() 0 18 5
A testFlushAllRemovesBalancingDirectories() 0 12 1
A isSharedStorage() 0 4 1
A getPathLengthsToTest() 0 14 1
A getBasePathForWindowsPathLengthTests() 0 4 1
B getKeyAndPathFittingLength() 0 35 1
B testWindowsPathLengthLimitIsCorrectlyHandled() 0 30 2
1
<?php
2
3
namespace Doctrine\Tests\Common\Cache;
4
5
use RecursiveDirectoryIterator;
6
use RecursiveIteratorIterator;
7
8
abstract class BaseFileCacheTest extends CacheTest
9
{
10
    protected $directory;
11
12
    protected function setUp()
13
    {
14
        do {
15
            $this->directory = sys_get_temp_dir() . '/doctrine_cache_'. uniqid();
16
        } while (file_exists($this->directory));
17
    }
18
19
    protected function tearDown()
20
    {
21
        if ( ! is_dir($this->directory)) {
22
            return;
23
        }
24
25
        $iterator = new RecursiveDirectoryIterator($this->directory);
26
27
        foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file) {
28
            if ($file->isFile()) {
29
                @unlink($file->getRealPath());
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
30
            } elseif ($file->isDir()) {
31
                @rmdir($file->getRealPath());
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
32
            }
33
        }
34
35
        @rmdir($this->directory);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
36
    }
37
38
    public function testFlushAllRemovesBalancingDirectories()
39
    {
40
        $cache = $this->_getCacheDriver();
41
42
        $this->assertTrue($cache->save('key1', 1));
43
        $this->assertTrue($cache->save('key2', 2));
44
        $this->assertTrue($cache->flushAll());
45
46
        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST);
47
48
        $this->assertCount(0, $iterator);
49
    }
50
51
    protected function isSharedStorage()
52
    {
53
        return false;
54
    }
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
    }
145
}
146