[TASK] Move access right parameters from BE to SYS configuration
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Locking / LockerTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Locking;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Locking\Locker;
18
19 /**
20 * Testcase for \TYPO3\CMS\Core\Locking\Locker
21 */
22 class LockerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
23 {
24 ///////////////////////////////
25 // tests concerning __construct
26 ///////////////////////////////
27 /**
28 * @test
29 */
30 public function constructorUsesDefaultLockingMethodSimple()
31 {
32 $instance = new Locker('999999999');
33 $this->assertSame(Locker::LOCKING_METHOD_SIMPLE, $instance->getMethod());
34 }
35
36 /**
37 * @test
38 */
39 public function constructorSetsMethodToGivenParameter()
40 {
41 $instance = new Locker('999999999', Locker::LOCKING_METHOD_FLOCK);
42 $this->assertSame(Locker::LOCKING_METHOD_FLOCK, $instance->getMethod());
43 }
44
45 /**
46 * @test
47 * @expectedException \InvalidArgumentException
48 */
49 public function constructorThrowsExceptionForNotExistingLockingMethod()
50 {
51 new Locker('999999999', 'foo');
52 }
53
54 /**
55 * @test
56 */
57 public function constructorFetchesInstallToolConfigurationIfEmptyMethod()
58 {
59 $GLOBALS['TYPO3_CONF_VARS']['SYS']['lockingMode'] = Locker::LOCKING_METHOD_SIMPLE;
60 $instance = new Locker('999999999', '');
61 $this->assertSame(Locker::LOCKING_METHOD_SIMPLE, $instance->getMethod());
62 }
63
64 /**
65 * @test
66 */
67 public function constructorUsesDefaultValueForLoops()
68 {
69 $instance = $this->getAccessibleMock(\TYPO3\CMS\Core\Locking\Locker::class, array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED));
70 $this->assertSame(150, $instance->_get('loops'));
71 }
72
73 /**
74 * @test
75 */
76 public function constructorSetsLoopsToGivenNumberOfLoops()
77 {
78 $instance = $this->getAccessibleMock(\TYPO3\CMS\Core\Locking\Locker::class, array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED, 10));
79 $this->assertSame(10, $instance->_get('loops'));
80 }
81
82 /**
83 * @test
84 */
85 public function constructorUsesDefaultValueForSteps()
86 {
87 $instance = $this->getAccessibleMock(\TYPO3\CMS\Core\Locking\Locker::class, array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED));
88 $this->assertSame(200, $instance->_get('step'));
89 }
90
91 /**
92 * @test
93 */
94 public function constructorSetsStepToGivenNumberOfStep()
95 {
96 $instance = $this->getAccessibleMock(\TYPO3\CMS\Core\Locking\Locker::class, array('dummy'), array('999999999', Locker::LOCKING_METHOD_DISABLED, 0, 10));
97 $this->assertSame(10, $instance->_get('step'));
98 }
99
100 /**
101 * @test
102 */
103 public function constructorCreatesLockDirectoryIfNotExisting()
104 {
105 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir(PATH_site . Locker::FILE_LOCK_FOLDER, true);
106 new Locker('999999999', Locker::LOCKING_METHOD_SIMPLE);
107 $this->assertTrue(is_dir(PATH_site . Locker::FILE_LOCK_FOLDER));
108 }
109
110 /**
111 * @test
112 */
113 public function constructorSetsIdToMd5OfStringIfUsingSimpleLocking()
114 {
115 $instance = new Locker('999999999', Locker::LOCKING_METHOD_SIMPLE);
116 $this->assertSame(md5('999999999'), $instance->getId());
117 }
118
119 /**
120 * @test
121 */
122 public function constructorSetsResourceToPathWithIdIfUsingSimpleLocking()
123 {
124 $instance = new Locker('999999999', Locker::LOCKING_METHOD_SIMPLE);
125 $this->assertSame(PATH_site . Locker::FILE_LOCK_FOLDER . md5('999999999'), $instance->getResource());
126 }
127
128 /**
129 * @test
130 */
131 public function constructorSetsIdToAbsCrc32OfIdStringIfUsingSemaphoreLocking()
132 {
133 if (!function_exists('sem_get')) {
134 $this->markTestSkipped('The system does not support semaphore base locking.');
135 }
136 $instance = new Locker('999999999', Locker::LOCKING_METHOD_SEMAPHORE);
137 $this->assertSame(abs(crc32('999999999')), $instance->getId());
138 }
139
140 ///////////////////////////////
141 // tests concerning acquire
142 ///////////////////////////////
143 /**
144 * @test
145 */
146 public function acquireFixesPermissionsOnLockFileIfUsingSimpleLogging()
147 {
148 if (TYPO3_OS == 'WIN') {
149 $this->markTestSkipped('acquireFixesPermissionsOnLockFileIfUsingSimpleLogging() test not available on Windows.');
150 }
151 // Use a very high id to be unique
152 $instance = new Locker(999999999, Locker::LOCKING_METHOD_SIMPLE);
153 $instance->setEnableLogging(false);
154 $pathOfLockFile = $instance->getResource();
155 $GLOBALS['TYPO3_CONF_VARS']['SYS']['fileCreateMask'] = '0777';
156 // Acquire lock, get actual file permissions and clean up
157 $instance->acquireExclusiveLock();
158 clearstatcache();
159 $resultFilePermissions = substr(decoct(fileperms($pathOfLockFile)), 2);
160 $instance->release();
161 $this->assertEquals($resultFilePermissions, '0777');
162 }
163
164 ///////////////////////////////
165 // tests concerning release
166 ///////////////////////////////
167
168 /**
169 * @test
170 */
171 public function releaseRemovesLockfileInTypo3TempLocks()
172 {
173 // Use a very high id to be unique
174 $instance = new Locker(999999999, Locker::LOCKING_METHOD_SIMPLE);
175 // Disable logging
176 $instance->setEnableLogging(false);
177 // File pointer to current lock file
178 $lockFile = $instance->getResource();
179 $instance->acquireExclusiveLock();
180 $instance->release();
181 $this->assertFalse(is_file($lockFile));
182 }
183
184 /**
185 * Dataprovider for releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory
186 */
187 public function invalidFileReferences()
188 {
189 return array(
190 'simple not within PATH_site' => array('simple', '/tmp/TYPO3-Lock-Test'),
191 'flock not withing PATH_site' => array('flock', '/tmp/TYPO3-Lock-Test'),
192 'simple directory traversal' => array('simple', PATH_site . 'typo3temp/../typo3temp/locks/foo'),
193 'flock directory traversal' => array('flock', PATH_site . 'typo3temp/../typo3temp/locks/foo'),
194 'simple directory traversal 2' => array('simple', PATH_site . 'typo3temp/locks/../locks/foo'),
195 'flock directory traversal 2' => array('flock', PATH_site . 'typo3temp/locks/../locks/foo'),
196 'simple within uploads' => array('simple', PATH_site . 'uploads/TYPO3-Lock-Test'),
197 'flock within uploads' => array('flock', PATH_site . 'uploads/TYPO3-Lock-Test')
198 );
199 }
200
201 /**
202 * @test
203 * @dataProvider invalidFileReferences
204 */
205 public function releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory($lockMethod, $file)
206 {
207 if (TYPO3_OS === 'WIN') {
208 $this->markTestSkipped('releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory() test not available on Windows.');
209 }
210 // Create test file
211 touch($file);
212 if (!is_file($file)) {
213 $this->markTestSkipped('releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory() skipped: Test file could not be created');
214 }
215 // Create instance, set lockfile to invalid path
216 $instance = new Locker(999999999, $lockMethod);
217 $instance->setEnableLogging(false);
218 $t3libLockReflection = new \ReflectionClass(\TYPO3\CMS\Core\Locking\Locker::class);
219 $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('resource');
220 $t3libLockReflectionResourceProperty->setAccessible(true);
221 $t3libLockReflectionResourceProperty->setValue($instance, $file);
222 $t3libLockReflectionAcquiredProperty = $t3libLockReflection->getProperty('isAcquired');
223 $t3libLockReflectionAcquiredProperty->setAccessible(true);
224 $t3libLockReflectionAcquiredProperty->setValue($instance, true);
225 // Call release method
226 $instance->release();
227 // Check if file is still there and clean up
228 $fileExists = is_file($file);
229 if (is_file($file)) {
230 unlink($file);
231 }
232 $this->assertTrue($fileExists);
233 }
234 }