[TASK] Raise PHP version requirement to 5.3.7
[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 * Copyright notice
6 *
7 * (c) 2010-2013 Christian Kuhn <lolli@schwarzbu.ch>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26
27 /**
28 * Testcase for \TYPO3\CMS\Core\Locking\Locker
29 *
30 * @author Christian Kuhn <lolli@schwarzbu.ch>
31 */
32 class LockerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
33
34 ///////////////////////////////
35 // tests concerning __construct
36 ///////////////////////////////
37 /**
38 * @test
39 */
40 public function constructorUsesDefaultLockingMethodSimple() {
41 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999');
42 $this->assertSame('simple', $instance->getMethod());
43 }
44
45 /**
46 * @test
47 */
48 public function constructorSetsMethodToGivenParameter() {
49 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'flock');
50 $this->assertSame('flock', $instance->getMethod());
51 }
52
53 /**
54 * @test
55 */
56 public function constructorDoesNotThrowExceptionIfUsingDisableMethod() {
57 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'disable');
58 }
59
60 /**
61 * @test
62 * @expectedException \InvalidArgumentException
63 */
64 public function constructorThrowsExceptionForNotExistingLockingMethod() {
65 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'foo');
66 }
67
68 /**
69 * @test
70 */
71 public function constructorUsesDefaultValueForLoops() {
72 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999');
73 $instance->setEnableLogging(FALSE);
74 $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
75 $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('loops');
76 $t3libLockReflectionResourceProperty->setAccessible(TRUE);
77 $this->assertSame(150, $t3libLockReflectionResourceProperty->getValue($instance));
78 }
79
80 /**
81 * @test
82 */
83 public function constructorSetsLoopsToGivenNumberOfLoops() {
84 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple', 10);
85 $instance->setEnableLogging(FALSE);
86 $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
87 $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('loops');
88 $t3libLockReflectionResourceProperty->setAccessible(TRUE);
89 $this->assertSame(10, $t3libLockReflectionResourceProperty->getValue($instance));
90 }
91
92 /**
93 * @test
94 */
95 public function constructorUsesDefaultValueForSteps() {
96 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999');
97 $instance->setEnableLogging(FALSE);
98 $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
99 $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('step');
100 $t3libLockReflectionResourceProperty->setAccessible(TRUE);
101 $this->assertSame(200, $t3libLockReflectionResourceProperty->getValue($instance));
102 }
103
104 /**
105 * @test
106 */
107 public function constructorSetsStepToGivenNumberOfStep() {
108 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple', 0, 10);
109 $instance->setEnableLogging(FALSE);
110 $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
111 $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('step');
112 $t3libLockReflectionResourceProperty->setAccessible(TRUE);
113 $this->assertSame(10, $t3libLockReflectionResourceProperty->getValue($instance));
114 }
115
116 /**
117 * @test
118 */
119 public function constructorCreatesLockDirectoryIfNotExisting() {
120 \TYPO3\CMS\Core\Utility\GeneralUtility::rmdir(PATH_site . 'typo3temp/locks/', TRUE);
121 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple');
122 $this->assertTrue(is_dir(PATH_site . 'typo3temp/locks/'));
123 }
124
125 /**
126 * @test
127 */
128 public function constructorSetsIdToMd5OfStringIfUsingSimleLocking() {
129 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple');
130 $this->assertSame(md5('999999999'), $instance->getId());
131 }
132
133 /**
134 * @test
135 */
136 public function constructorSetsResourceToPathWithIdIfUsingSimpleLocking() {
137 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'simple');
138 $this->assertSame(PATH_site . 'typo3temp/locks/' . md5('999999999'), $instance->getResource());
139 }
140
141 /**
142 * @test
143 */
144 public function constructorSetsIdToAbsCrc32OfIdStringIfUsingSemaphoreLocking() {
145 if (!function_exists('sem_get')) {
146 $this->markTestSkipped('The system does not support semaphore base locking.');
147 }
148 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'semaphore');
149 $this->assertSame(abs(crc32('999999999')), $instance->getId());
150 }
151
152 /**
153 * @test
154 */
155 public function constructorSetsResourceToSemaphoreResourceIfUsingSemaphoreLocking() {
156 if (!function_exists('sem_get')) {
157 $this->markTestSkipped('The system does not support semaphore base locking.');
158 }
159 $instance = new \TYPO3\CMS\Core\Locking\Locker('999999999', 'semaphore');
160 $this->assertTrue(is_resource($instance->getResource()));
161 }
162
163 ///////////////////////////////
164 // tests concerning acquire
165 ///////////////////////////////
166 /**
167 * @test
168 */
169 public function acquireFixesPermissionsOnLockFileIfUsingSimpleLogging() {
170 if (TYPO3_OS == 'WIN') {
171 $this->markTestSkipped('acquireFixesPermissionsOnLockFileIfUsingSimpleLogging() test not available on Windows.');
172 }
173 // Use a very high id to be unique
174 $instance = new \TYPO3\CMS\Core\Locking\Locker(999999999, 'simple');
175 $pathOfLockFile = $instance->getResource();
176 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
177 // Acquire lock, get actual file permissions and clean up
178 $instance->acquire();
179 clearstatcache();
180 $resultFilePermissions = substr(decoct(fileperms($pathOfLockFile)), 2);
181 $instance->__destruct();
182 $this->assertEquals($resultFilePermissions, '0777');
183 }
184
185 ///////////////////////////////
186 // tests concerning release
187 ///////////////////////////////
188 /**
189 * Dataprovider for releaseRemovesLockfileInTypo3TempLocks
190 */
191 public function fileBasedLockMethods() {
192 return array(
193 'simple' => array('simple'),
194 'flock' => array('flock')
195 );
196 }
197
198 /**
199 * @test
200 * @dataProvider fileBasedLockMethods
201 */
202 public function releaseRemovesLockfileInTypo3TempLocks($lockMethod) {
203 // Use a very high id to be unique
204 $instance = new \TYPO3\CMS\Core\Locking\Locker(999999999, $lockMethod);
205 // Disable logging
206 $instance->setEnableLogging(FALSE);
207 // File pointer to current lock file
208 $lockFile = $instance->getResource();
209 $instance->acquire();
210 $instance->release();
211 $this->assertFalse(is_file($lockFile));
212 }
213
214 /**
215 * Dataprovider for releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory
216 */
217 public function invalidFileReferences() {
218 return array(
219 'simple not within PATH_site' => array('simple', '/tmp/TYPO3-Lock-Test'),
220 'flock not withing PATH_site' => array('flock', '/tmp/TYPO3-Lock-Test'),
221 'simple directory traversal' => array('simple', PATH_site . 'typo3temp/../typo3temp/locks/foo'),
222 'flock directory traversal' => array('flock', PATH_site . 'typo3temp/../typo3temp/locks/foo'),
223 'simple directory traversal 2' => array('simple', PATH_site . 'typo3temp/locks/../locks/foo'),
224 'flock directory traversal 2' => array('flock', PATH_site . 'typo3temp/locks/../locks/foo'),
225 'simple within uploads' => array('simple', PATH_site . 'uploads/TYPO3-Lock-Test'),
226 'flock within uploads' => array('flock', PATH_site . 'uploads/TYPO3-Lock-Test')
227 );
228 }
229
230 /**
231 * @test
232 * @dataProvider invalidFileReferences
233 */
234 public function releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory($lockMethod, $file) {
235 if (TYPO3_OS === 'WIN') {
236 $this->markTestSkipped('releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory() test not available on Windows.');
237 }
238 // Create test file
239 touch($file);
240 if (!is_file($file)) {
241 $this->markTestSkipped('releaseDoesNotRemoveFilesNotWithinTypo3TempLocksDirectory() skipped: Test file could not be created');
242 }
243 // Create instance, set lockfile to invalid path
244 $instance = new \TYPO3\CMS\Core\Locking\Locker(999999999, $lockMethod);
245 $instance->setEnableLogging(FALSE);
246 $t3libLockReflection = new \ReflectionClass('TYPO3\\CMS\\Core\\Locking\\Locker');
247 $t3libLockReflectionResourceProperty = $t3libLockReflection->getProperty('resource');
248 $t3libLockReflectionResourceProperty->setAccessible(TRUE);
249 $t3libLockReflectionResourceProperty->setValue($instance, $file);
250 $t3libLockReflectionAcquiredProperty = $t3libLockReflection->getProperty('isAcquired');
251 $t3libLockReflectionAcquiredProperty->setAccessible(TRUE);
252 $t3libLockReflectionAcquiredProperty->setValue($instance, TRUE);
253 // Call release method
254 $instance->release();
255 // Check if file is still there and clean up
256 $fileExists = is_file($file);
257 if (is_file($file)) {
258 unlink($file);
259 }
260 $this->assertTrue($fileExists);
261 }
262
263 }
264
265 ?>