[TASK] Clean up unit tests on Windows
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Configuration / ConfigurationManagerTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Configuration;
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 /**
18 * Test case
19 */
20 class ConfigurationManagerTest extends \TYPO3\CMS\Core\Tests\UnitTestCase
21 {
22 /**
23 * @var \TYPO3\CMS\Core\Configuration\ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject
24 */
25 protected $subject;
26
27 protected function setUp()
28 {
29 $this->createSubjectWithMockedMethods(
30 array(
31 'getDefaultConfigurationFileLocation',
32 'getLocalConfigurationFileLocation',
33 )
34 );
35 }
36
37 /**
38 * @param array $methods
39 */
40 protected function createSubjectWithMockedMethods(array $methods)
41 {
42 $this->subject = $this->getMock(
43 \TYPO3\CMS\Core\Configuration\ConfigurationManager::class,
44 $methods
45 );
46 }
47
48 /**
49 * @test
50 * @expectedException \RuntimeException
51 */
52 public function getDefaultConfigurationExecutesDefinedDefaultConfigurationFile()
53 {
54 $defaultConfigurationFile = PATH_site . 'typo3temp/var/tests/' . $this->getUniqueId('defaultConfiguration');
55 file_put_contents(
56 $defaultConfigurationFile,
57 '<?php throw new \RuntimeException(\'foo\', 1310203814); ?>'
58 );
59 $this->testFilesToDelete[] = $defaultConfigurationFile;
60
61 $this->subject
62 ->expects($this->once())
63 ->method('getDefaultConfigurationFileLocation')
64 ->will($this->returnValue($defaultConfigurationFile));
65 $this->subject->getDefaultConfiguration();
66 }
67
68 /**
69 * @test
70 * @expectedException \RuntimeException
71 */
72 public function getLocalConfigurationExecutesDefinedConfigurationFile()
73 {
74 $configurationFile = PATH_site . 'typo3temp/var/tests/' . $this->getUniqueId('localConfiguration');
75 file_put_contents(
76 $configurationFile,
77 '<?php throw new \RuntimeException(\'foo\', 1310203815); ?>'
78 );
79 $this->testFilesToDelete[] = $configurationFile;
80
81 $this->subject
82 ->expects($this->once())
83 ->method('getLocalConfigurationFileLocation')
84 ->will($this->returnValue($configurationFile));
85 $this->subject->getLocalConfiguration();
86 }
87
88 /**
89 * @test
90 */
91 public function updateLocalConfigurationWritesNewMergedLocalConfigurationArray()
92 {
93 $currentLocalConfiguration = array(
94 'notChanged' => 23,
95 'changed' => 'unChanged',
96 );
97 $overrideConfiguration = array(
98 'changed' => 'changed',
99 'new' => 'new'
100 );
101 $expectedConfiguration = array(
102 'notChanged' => 23,
103 'changed' => 'changed',
104 'new' => 'new',
105 );
106
107 $this->createSubjectWithMockedMethods(
108 array(
109 'getLocalConfiguration',
110 'writeLocalConfiguration',
111 )
112 );
113 $this->subject->expects($this->once())
114 ->method('getLocalConfiguration')
115 ->will($this->returnValue($currentLocalConfiguration));
116 $this->subject->expects($this->once())
117 ->method('writeLocalConfiguration')
118 ->with($expectedConfiguration);
119
120 $this->subject->updateLocalConfiguration($overrideConfiguration);
121 }
122
123 /**
124 * @test
125 */
126 public function getDefaultConfigurationValueByPathReturnsCorrectValue()
127 {
128 $this->createSubjectWithMockedMethods(
129 array(
130 'getDefaultConfiguration',
131 )
132 );
133 $this->subject->expects($this->once())
134 ->method('getDefaultConfiguration')
135 ->will($this->returnValue(array(
136 'path' => 'value',
137 )
138 ));
139
140 $this->assertSame('value', $this->subject->getDefaultConfigurationValueByPath('path'));
141 }
142
143 /**
144 * @test
145 */
146 public function getLocalConfigurationValueByPathReturnsCorrectValue()
147 {
148 $this->createSubjectWithMockedMethods(
149 array(
150 'getLocalConfiguration',
151 )
152 );
153 $this->subject->expects($this->once())
154 ->method('getLocalConfiguration')
155 ->will($this->returnValue(array(
156 'path' => 'value',
157 )
158 ));
159
160 $this->assertSame('value', $this->subject->getLocalConfigurationValueByPath('path'));
161 }
162
163 /**
164 * @test
165 */
166 public function getConfigurationValueByPathReturnsCorrectValue()
167 {
168 $this->createSubjectWithMockedMethods(
169 array(
170 'getDefaultConfiguration',
171 'getLocalConfiguration',
172 )
173 );
174 $this->subject->expects($this->once())
175 ->method('getDefaultConfiguration')
176 ->will($this->returnValue(array(
177 'path' => 'value',
178 )
179 ));
180 $this->subject->expects($this->once())
181 ->method('getLocalConfiguration')
182 ->will($this->returnValue(array(
183 'path' => 'valueOverride',
184 )
185 ));
186
187 $this->assertSame('valueOverride', $this->subject->getConfigurationValueByPath('path'));
188 }
189
190 /**
191 * @test
192 */
193 public function setLocalConfigurationValueByPathReturnFalseIfPathIsNotValid()
194 {
195 $this->createSubjectWithMockedMethods(array(
196 'isValidLocalConfigurationPath',
197 ));
198 $this->subject->expects($this->once())
199 ->method('isValidLocalConfigurationPath')
200 ->will($this->returnValue(false));
201
202 $this->assertFalse($this->subject->setLocalConfigurationValueByPath('path', 'value'));
203 }
204
205 /**
206 * @test
207 */
208 public function setLocalConfigurationValueByPathUpdatesValueDefinedByPath()
209 {
210 $currentLocalConfiguration = array(
211 'notChanged' => 23,
212 'toUpdate' => 'notUpdated',
213 );
214 $expectedConfiguration = array(
215 'notChanged' => 23,
216 'toUpdate' => 'updated',
217 );
218
219 $this->createSubjectWithMockedMethods(
220 array(
221 'isValidLocalConfigurationPath',
222 'getLocalConfiguration',
223 'writeLocalConfiguration',
224 )
225 );
226 $this->subject->expects($this->once())
227 ->method('isValidLocalConfigurationPath')
228 ->will($this->returnValue(true));
229 $this->subject->expects($this->once())
230 ->method('getLocalConfiguration')
231 ->will($this->returnValue($currentLocalConfiguration));
232 $this->subject->expects($this->once())
233 ->method('writeLocalConfiguration')
234 ->with($expectedConfiguration);
235
236 $this->subject->setLocalConfigurationValueByPath('toUpdate', 'updated');
237 }
238
239 /**
240 * @test
241 */
242 public function setLocalConfigurationValuesByPathValuePairsSetsPathValuePairs()
243 {
244 $currentLocalConfiguration = array(
245 'notChanged' => 23,
246 'toUpdate' => 'notUpdated',
247 );
248 $expectedConfiguration = array(
249 'notChanged' => 23,
250 'toUpdate' => 'updated',
251 'new' => 'new',
252 );
253
254 $this->createSubjectWithMockedMethods(
255 array(
256 'isValidLocalConfigurationPath',
257 'getLocalConfiguration',
258 'writeLocalConfiguration',
259 )
260 );
261 $this->subject->expects($this->any())
262 ->method('isValidLocalConfigurationPath')
263 ->will($this->returnValue(true));
264 $this->subject->expects($this->once())
265 ->method('getLocalConfiguration')
266 ->will($this->returnValue($currentLocalConfiguration));
267 $this->subject->expects($this->once())
268 ->method('writeLocalConfiguration')
269 ->with($expectedConfiguration);
270
271 $pairs = array(
272 'toUpdate' => 'updated',
273 'new' => 'new'
274 );
275 $this->subject->setLocalConfigurationValuesByPathValuePairs($pairs);
276 }
277
278 /**
279 * @test
280 */
281 public function removeLocalConfigurationKeysByPathRemovesGivenPathsFromConfigurationAndReturnsTrue()
282 {
283 $currentLocalConfiguration = array(
284 'toRemove1' => 'foo',
285 'notChanged' => 23,
286 'toRemove2' => 'bar',
287 );
288 $expectedConfiguration = array(
289 'notChanged' => 23,
290 );
291
292 $this->createSubjectWithMockedMethods(
293 array(
294 'getLocalConfiguration',
295 'writeLocalConfiguration',
296 )
297 );
298 $this->subject->expects($this->once())
299 ->method('getLocalConfiguration')
300 ->will($this->returnValue($currentLocalConfiguration));
301 $this->subject->expects($this->once())
302 ->method('writeLocalConfiguration')
303 ->with($expectedConfiguration);
304
305 $removePaths = array(
306 'toRemove1',
307 'toRemove2',
308 );
309 $this->assertTrue($this->subject->removeLocalConfigurationKeysByPath($removePaths));
310 }
311
312 /**
313 * @test
314 */
315 public function removeLocalConfigurationKeysByPathReturnsFalseIfNothingIsRemoved()
316 {
317 $currentLocalConfiguration = array(
318 'notChanged' => 23,
319 );
320 $this->createSubjectWithMockedMethods(
321 array(
322 'getLocalConfiguration',
323 'writeLocalConfiguration',
324 )
325 );
326 $this->subject->expects($this->once())
327 ->method('getLocalConfiguration')
328 ->will($this->returnValue($currentLocalConfiguration));
329 $this->subject->expects($this->never())
330 ->method('writeLocalConfiguration');
331
332 $removeNothing = array();
333 $this->assertFalse($this->subject->removeLocalConfigurationKeysByPath($removeNothing));
334 }
335
336 /**
337 * @test
338 */
339 public function removeLocalConfigurationKeysByPathReturnsFalseIfSomethingInexistentIsRemoved()
340 {
341 $currentLocalConfiguration = array(
342 'notChanged' => 23,
343 );
344 $this->createSubjectWithMockedMethods(
345 array(
346 'getLocalConfiguration',
347 'writeLocalConfiguration',
348 )
349 );
350 $this->subject->expects($this->once())
351 ->method('getLocalConfiguration')
352 ->will($this->returnValue($currentLocalConfiguration));
353 $this->subject->expects($this->never())
354 ->method('writeLocalConfiguration');
355
356 $removeNonExisting = array('notPresent');
357 $this->assertFalse($this->subject->removeLocalConfigurationKeysByPath($removeNonExisting));
358 }
359
360 /**
361 * @test
362 */
363 public function canWriteConfigurationReturnsFalseIfDirectoryIsNotWritable()
364 {
365 if (function_exists('posix_getegid') && posix_getegid() === 0) {
366 $this->markTestSkipped('Test skipped if run on linux as root');
367 } elseif (TYPO3_OS === 'WIN') {
368 $this->markTestSkipped('Not available on Windows as folders are always writable');
369 }
370 /** @var $subject \TYPO3\CMS\Core\Configuration\ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface */
371 $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, array('dummy'));
372
373 $directory = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
374 $absoluteDirectory = PATH_site . $directory;
375 mkdir($absoluteDirectory);
376 chmod($absoluteDirectory, 0544);
377 clearstatcache();
378
379 $subject->_set('pathTypo3Conf', $directory);
380
381 $result = $subject->canWriteConfiguration();
382
383 chmod($absoluteDirectory, 0755);
384 rmdir($absoluteDirectory);
385
386 $this->assertFalse($result);
387 }
388
389 /**
390 * @test
391 */
392 public function canWriteConfigurationReturnsFalseIfLocalConfigurationFileIsNotWritable()
393 {
394 if (function_exists('posix_getegid') && posix_getegid() === 0) {
395 $this->markTestSkipped('Test skipped if run on linux as root');
396 }
397 /** @var $subject \TYPO3\CMS\Core\Configuration\ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface */
398 $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, array('dummy'));
399
400 $file = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
401 $absoluteFile = PATH_site . $file;
402 touch($absoluteFile);
403 $this->testFilesToDelete[] = $absoluteFile;
404 chmod($absoluteFile, 0444);
405 clearstatcache();
406
407 $subject->_set('localConfigurationFile', $file);
408
409 $result = $subject->canWriteConfiguration();
410
411 chmod($absoluteFile, 0644);
412
413 $this->assertFalse($result);
414 }
415
416 /**
417 * @test
418 */
419 public function canWriteConfigurationReturnsTrueIfDirectoryAndFilesAreWritable()
420 {
421 /** @var $subject \TYPO3\CMS\Core\Configuration\ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface */
422 $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, array('dummy'));
423
424 $directory = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
425 $absoluteDirectory = PATH_site . $directory;
426 mkdir($absoluteDirectory);
427 $subject->_set('pathTypo3Conf', $absoluteDirectory);
428
429 $file1 = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
430 $absoluteFile1 = PATH_site . $file1;
431 touch($absoluteFile1);
432 $this->testFilesToDelete[] = $absoluteFile1;
433 $subject->_set('localConfigurationFile', $absoluteFile1);
434
435 $file2 = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
436 $absoluteFile2 = PATH_site . $file2;
437 touch($absoluteFile2);
438 $this->testFilesToDelete[] = $absoluteFile2;
439 $subject->_set('localconfFile', $absoluteFile2);
440
441 clearstatcache();
442
443 $result = $subject->canWriteConfiguration();
444
445 $this->assertTrue($result);
446 $this->testFilesToDelete[] = $absoluteDirectory;
447 }
448
449 /**
450 * @test
451 */
452 public function writeLocalConfigurationWritesSortedContentToConfigurationFile()
453 {
454 $configurationFile = PATH_site . 'typo3temp/var/tests/' . $this->getUniqueId('localConfiguration');
455 if (!is_file($configurationFile)) {
456 if (!$fh = fopen($configurationFile, 'wb')) {
457 $this->markTestSkipped('Can not create file ' . $configurationFile . '. Please check your write permissions.');
458 }
459 fclose($fh);
460 }
461
462 if (!@is_file($configurationFile)) {
463 throw new \RuntimeException('File ' . $configurationFile . ' could not be found. Please check your write permissions', 1346364362);
464 }
465 $this->testFilesToDelete[] = $configurationFile;
466
467 $this->subject
468 ->expects($this->any())
469 ->method('getLocalConfigurationFileLocation')
470 ->will($this->returnValue($configurationFile));
471
472 $pairs = array(
473 'foo' => 42,
474 'bar' => 23
475 );
476 $expectedContent =
477 '<?php' . LF .
478 'return [' . LF .
479 ' \'bar\' => 23,' . LF .
480 ' \'foo\' => 42,' . LF .
481 '];' . LF;
482
483 $this->subject->writeLocalConfiguration($pairs);
484 $this->assertSame($expectedContent, file_get_contents($configurationFile));
485 }
486
487 /**
488 * @test
489 * @expectedException \RuntimeException
490 */
491 public function createLocalConfigurationFromFactoryConfigurationThrowsExceptionIfFileExists()
492 {
493 /** @var $subject \TYPO3\CMS\Core\Configuration\ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface */
494 $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, array('dummy'));
495
496 $file = 'typo3temp/var/tests/' . $this->getUniqueId('test_');
497 $absoluteFile = PATH_site . $file;
498 touch($absoluteFile);
499 $this->testFilesToDelete[] = $absoluteFile;
500 $subject->_set('localConfigurationFile', $file);
501
502 $subject->createLocalConfigurationFromFactoryConfiguration();
503 }
504
505 /**
506 * @test
507 */
508 public function createLocalConfigurationFromFactoryConfigurationWritesContentFromFactoryFile()
509 {
510 /** @var $subject \TYPO3\CMS\Core\Configuration\ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface */
511 $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, array('writeLocalConfiguration'));
512 $subject->_set('localConfigurationFile', 'typo3temp/var/tests/' . $this->getUniqueId('dummy_'));
513
514 $factoryConfigurationFile = 'typo3temp/var/tests/' . $this->getUniqueId('test_') . '.php';
515 $factoryConfigurationAbsoluteFile = PATH_site . $factoryConfigurationFile;
516 $uniqueContentString = $this->getUniqueId('string_');
517 $validFactoryConfigurationFileContent =
518 '<?php' . LF .
519 'return array(' . LF .
520 $uniqueContentString . ' => foo,' . LF .
521 ');' . LF;
522 file_put_contents(
523 $factoryConfigurationAbsoluteFile,
524 $validFactoryConfigurationFileContent
525 );
526 $this->testFilesToDelete[] = $factoryConfigurationAbsoluteFile;
527
528 $subject->_set('factoryConfigurationFile', $factoryConfigurationFile);
529
530 $subject
531 ->expects($this->once())
532 ->method('writeLocalConfiguration')
533 ->with($this->arrayHasKey($uniqueContentString));
534 $subject->createLocalConfigurationFromFactoryConfiguration();
535 }
536
537 /**
538 * @test
539 */
540 public function createLocalConfigurationFromFactoryConfigurationMergesConfigurationWithAdditionalFactoryFile()
541 {
542 /** @var $subject \TYPO3\CMS\Core\Configuration\ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface */
543 $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, array('writeLocalConfiguration'));
544 $subject->_set('localConfigurationFile', 'typo3temp/var/tests/' . $this->getUniqueId('dummy_'));
545
546 $factoryConfigurationFile = 'typo3temp/var/tests/' . $this->getUniqueId('test_') . '.php';
547 $factoryConfigurationAbsoluteFile = PATH_site . $factoryConfigurationFile;
548 $validFactoryConfigurationFileContent =
549 '<?php' . LF .
550 'return [];' . LF;
551 file_put_contents(
552 $factoryConfigurationAbsoluteFile,
553 $validFactoryConfigurationFileContent
554 );
555 $this->testFilesToDelete[] = $factoryConfigurationAbsoluteFile;
556 $subject->_set('factoryConfigurationFile', $factoryConfigurationFile);
557
558 $additionalFactoryConfigurationFile = 'typo3temp/var/tests/' . $this->getUniqueId('test_') . '.php';
559 $additionalFactoryConfigurationAbsoluteFile = PATH_site . $additionalFactoryConfigurationFile;
560 $uniqueContentString = $this->getUniqueId('string_');
561 $validAdditionalFactoryConfigurationFileContent =
562 '<?php' . LF .
563 'return [' . LF .
564 $uniqueContentString . ' => foo,' . LF .
565 '];' . LF;
566 file_put_contents(
567 $additionalFactoryConfigurationAbsoluteFile,
568 $validAdditionalFactoryConfigurationFileContent
569 );
570 $this->testFilesToDelete[] = $additionalFactoryConfigurationAbsoluteFile;
571 $subject->_set('additionalFactoryConfigurationFile', $additionalFactoryConfigurationFile);
572
573 $subject
574 ->expects($this->once())
575 ->method('writeLocalConfiguration')
576 ->with($this->arrayHasKey($uniqueContentString));
577 $subject->createLocalConfigurationFromFactoryConfiguration();
578 }
579
580 /**
581 * @test
582 */
583 public function isValidLocalConfigurationPathAcceptsWhitelistedPath()
584 {
585 /** @var $subject \TYPO3\CMS\Core\Configuration\ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface */
586 $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, array('dummy'));
587 $subject->_set('whiteListedLocalConfigurationPaths', array('foo/bar'));
588 $this->assertTrue($subject->_call('isValidLocalConfigurationPath', 'foo/bar/baz'));
589 }
590
591 /**
592 * @test
593 */
594 public function isValidLocalConfigurationPathDeniesNotWhitelistedPath()
595 {
596 /** @var $subject \TYPO3\CMS\Core\Configuration\ConfigurationManager|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface */
597 $subject = $this->getAccessibleMock(\TYPO3\CMS\Core\Configuration\ConfigurationManager::class, array('dummy'));
598 $subject->_set('whiteListedLocalConfigurationPaths', array('foo/bar'));
599 $this->assertFalse($subject->_call('isValidLocalConfigurationPath', 'bar/baz'));
600 }
601 }