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