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