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