[TASK] Release installation procedure from LocalConfiguration file
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Utility / GeneralUtilityTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Utility;
3 use TYPO3\CMS\Core\Utility;
4
5 /***************************************************************
6 * Copyright notice
7 *
8 * (c) 2009-2013 Ingo Renner <ingo@typo3.org>
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 * Testcase for class \TYPO3\CMS\Core\Utility\GeneralUtility
30 *
31 * @author Ingo Renner <ingo@typo3.org>
32 * @author Oliver Klee <typo3-coding@oliverklee.de>
33 */
34 class GeneralUtilityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
35
36 /**
37 * Absolute path to files that must be removed
38 * after a test - handled in tearDown
39 *
40 * @var array
41 */
42 protected $testFilesToDelete = array();
43
44 /**
45 * @var array A backup of registered singleton instances
46 */
47 protected $singletonInstances = array();
48
49 public function setUp() {
50 $this->singletonInstances = Utility\GeneralUtility::getSingletonInstances();
51 }
52
53 public function tearDown() {
54 Utility\GeneralUtility::resetSingletonInstances($this->singletonInstances);
55 foreach ($this->testFilesToDelete as $absoluteFileName) {
56 Utility\GeneralUtility::unlink_tempfile($absoluteFileName);
57 }
58 }
59
60 ///////////////////////////
61 // Tests concerning _GP
62 ///////////////////////////
63 /**
64 * @test
65 * @dataProvider gpDataProvider
66 */
67 public function canRetrieveValueWithGP($key, $get, $post, $expected) {
68 $_GET = $get;
69 $_POST = $post;
70 $this->assertSame($expected, Utility\GeneralUtility::_GP($key));
71 }
72
73 /**
74 * Data provider for canRetrieveValueWithGP.
75 * All test values also check whether slashes are stripped properly.
76 *
77 * @return array
78 */
79 public function gpDataProvider() {
80 return array(
81 'No key parameter' => array(NULL, array(), array(), NULL),
82 'Key not found' => array('cake', array(), array(), NULL),
83 'Value only in GET' => array('cake', array('cake' => 'li\\e'), array(), 'lie'),
84 'Value only in POST' => array('cake', array(), array('cake' => 'l\\ie'), 'lie'),
85 'Value from POST preferred over GET' => array('cake', array('cake' => 'is a'), array('cake' => '\\lie'), 'lie'),
86 'Value can be an array' => array(
87 'cake',
88 array('cake' => array('is a' => 'l\\ie')),
89 array(),
90 array('is a' => 'lie')
91 )
92 );
93 }
94
95 ///////////////////////////
96 // Tests concerning _GPmerged
97 ///////////////////////////
98 /**
99 * @test
100 * @dataProvider gpMergedDataProvider
101 */
102 public function gpMergedWillMergeArraysFromGetAndPost($get, $post, $expected) {
103 $_POST = $post;
104 $_GET = $get;
105 $this->assertEquals($expected, Utility\GeneralUtility::_GPmerged('cake'));
106 }
107
108 /**
109 * Data provider for gpMergedWillMergeArraysFromGetAndPost
110 *
111 * @return array
112 */
113 public function gpMergedDataProvider() {
114 $fullDataArray = array('cake' => array('a' => 'is a', 'b' => 'lie'));
115 $postPartData = array('cake' => array('b' => 'lie'));
116 $getPartData = array('cake' => array('a' => 'is a'));
117 $getPartDataModified = array('cake' => array('a' => 'is not a'));
118 return array(
119 'Key doesn\' exist' => array(array('foo'), array('bar'), array()),
120 'No POST data' => array($fullDataArray, array(), $fullDataArray['cake']),
121 'No GET data' => array(array(), $fullDataArray, $fullDataArray['cake']),
122 'POST and GET are merged' => array($getPartData, $postPartData, $fullDataArray['cake']),
123 'POST is preferred over GET' => array($getPartDataModified, $fullDataArray, $fullDataArray['cake'])
124 );
125 }
126
127 ///////////////////////////////
128 // Tests concerning _GET / _POST
129 ///////////////////////////////
130 /**
131 * Data provider for canRetrieveGlobalInputsThroughGet
132 * and canRetrieveGlobalInputsThroughPost
133 *
134 * @return array
135 */
136 public function getAndPostDataProvider() {
137 return array(
138 'Requested input data doesn\'t exist' => array('cake', array(), NULL),
139 'No key will return entire input data' => array(NULL, array('cake' => 'l\\ie'), array('cake' => 'lie')),
140 'Can retrieve specific input' => array('cake', array('cake' => 'li\\e', 'foo'), 'lie'),
141 'Can retrieve nested input data' => array('cake', array('cake' => array('is a' => 'l\\ie')), array('is a' => 'lie'))
142 );
143 }
144
145 /**
146 * @test
147 * @dataProvider getAndPostDataProvider
148 */
149 public function canRetrieveGlobalInputsThroughGet($key, $get, $expected) {
150 $_GET = $get;
151 $this->assertSame($expected, Utility\GeneralUtility::_GET($key));
152 }
153
154 /**
155 * @test
156 * @dataProvider getAndPostDataProvider
157 */
158 public function canRetrieveGlobalInputsThroughPost($key, $post, $expected) {
159 $_POST = $post;
160 $this->assertSame($expected, Utility\GeneralUtility::_POST($key));
161 }
162
163 ///////////////////////////////
164 // Tests concerning _GETset
165 ///////////////////////////////
166 /**
167 * @test
168 * @dataProvider getSetDataProvider
169 */
170 public function canSetNewGetInputValues($input, $key, $expected, $getPreset = array()) {
171 $_GET = $getPreset;
172 Utility\GeneralUtility::_GETset($input, $key);
173 $this->assertSame($expected, $_GET);
174 }
175
176 /**
177 * Data provider for canSetNewGetInputValues
178 *
179 * @return array
180 */
181 public function getSetDataProvider() {
182 return array(
183 'No input data used without target key' => array(NULL, NULL, array()),
184 'No input data used with target key' => array(NULL, 'cake', array('cake' => '')),
185 'No target key used with string input data' => array('data', NULL, array()),
186 'No target key used with array input data' => array(array('cake' => 'lie'), NULL, array('cake' => 'lie')),
187 'Target key and string input data' => array('lie', 'cake', array('cake' => 'lie')),
188 'Replace existing GET data' => array('lie', 'cake', array('cake' => 'lie'), array('cake' => 'is a lie')),
189 'Target key pointing to sublevels and string input data' => array('lie', 'cake|is', array('cake' => array('is' => 'lie'))),
190 'Target key pointing to sublevels and array input data' => array(array('a' => 'lie'), 'cake|is', array('cake' => array('is' => array('a' => 'lie'))))
191 );
192 }
193
194 ///////////////////////////////
195 // Tests concerning gif_compress
196 ///////////////////////////////
197 /**
198 * @test
199 */
200 public function gifCompressFixesPermissionOfConvertedFileIfUsingImagemagick() {
201 if (TYPO3_OS == 'WIN') {
202 $this->markTestSkipped('gifCompressFixesPermissionOfConvertedFileIfUsingImagemagick() test not available on Windows.');
203 }
204 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] || !$GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']) {
205 $this->markTestSkipped('gifCompressFixesPermissionOfConvertedFileIfUsingImagemagick() test not available without imagemagick setup.');
206 }
207 $fixtureGifFile = __DIR__ . '/Fixtures/clear.gif';
208 $GLOBALS['TYPO3_CONF_VARS']['GFX']['gif_compress'] = TRUE;
209 // Copy file to unique filename in typo3temp, set target permissions and run method
210 $testFilename = PATH_site . 'typo3temp/' . uniqid('test_') . '.gif';
211 @copy($fixtureGifFile, $testFilename);
212 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
213 Utility\GeneralUtility::gif_compress($testFilename, 'IM');
214 // Get actual permissions and clean up
215 clearstatcache();
216 $resultFilePermissions = substr(decoct(fileperms($testFilename)), 2);
217 Utility\GeneralUtility::unlink_tempfile($testFilename);
218 $this->assertEquals($resultFilePermissions, '0777');
219 }
220
221 /**
222 * @test
223 */
224 public function gifCompressFixesPermissionOfConvertedFileIfUsingGd() {
225 if (TYPO3_OS == 'WIN') {
226 $this->markTestSkipped('gifCompressFixesPermissionOfConvertedFileIfUsingImagemagick() test not available on Windows.');
227 }
228 $fixtureGifFile = __DIR__ . '/Fixtures/clear.gif';
229 $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib'] = TRUE;
230 $GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib_png'] = FALSE;
231 $GLOBALS['TYPO3_CONF_VARS']['GFX']['gif_compress'] = TRUE;
232 // Copy file to unique filename in typo3temp, set target permissions and run method
233 $testFilename = PATH_site . 'typo3temp/' . uniqid('test_') . '.gif';
234 @copy($fixtureGifFile, $testFilename);
235 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
236 Utility\GeneralUtility::gif_compress($testFilename, 'GD');
237 // Get actual permissions and clean up
238 clearstatcache();
239 $resultFilePermissions = substr(decoct(fileperms($testFilename)), 2);
240 Utility\GeneralUtility::unlink_tempfile($testFilename);
241 $this->assertEquals($resultFilePermissions, '0777');
242 }
243
244 ///////////////////////////////
245 // Tests concerning png_to_gif_by_imagemagick
246 ///////////////////////////////
247 /**
248 * @test
249 */
250 public function pngToGifByImagemagickFixesPermissionsOfConvertedFile() {
251 if (TYPO3_OS == 'WIN') {
252 $this->markTestSkipped('pngToGifByImagemagickFixesPermissionsOfConvertedFile() test not available on Windows.');
253 }
254 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['im'] || !$GLOBALS['TYPO3_CONF_VARS']['GFX']['im_path_lzw']) {
255 $this->markTestSkipped('pngToGifByImagemagickFixesPermissionsOfConvertedFile() test not available without imagemagick setup.');
256 }
257 $fixturePngFile = __DIR__ . '/Fixtures/clear.png';
258 $GLOBALS['TYPO3_CONF_VARS']['FE']['png_to_gif'] = TRUE;
259 // Copy file to unique filename in typo3temp, set target permissions and run method
260 $testFilename = PATH_site . 'typo3temp/' . uniqid('test_') . '.png';
261 @copy($fixturePngFile, $testFilename);
262 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
263 $newGifFile = Utility\GeneralUtility::png_to_gif_by_imagemagick($testFilename);
264 // Get actual permissions and clean up
265 clearstatcache();
266 $resultFilePermissions = substr(decoct(fileperms($newGifFile)), 2);
267 Utility\GeneralUtility::unlink_tempfile($newGifFile);
268 $this->assertEquals($resultFilePermissions, '0777');
269 }
270
271 ///////////////////////////////
272 // Tests concerning read_png_gif
273 ///////////////////////////////
274 /**
275 * @test
276 */
277 public function readPngGifFixesPermissionsOfConvertedFile() {
278 if (TYPO3_OS == 'WIN') {
279 $this->markTestSkipped('readPngGifFixesPermissionsOfConvertedFile() test not available on Windows.');
280 }
281 if (!$GLOBALS['TYPO3_CONF_VARS']['GFX']['im']) {
282 $this->markTestSkipped('readPngGifFixesPermissionsOfConvertedFile() test not available without imagemagick setup.');
283 }
284 $testGifFile = __DIR__ . '/Fixtures/clear.gif';
285 // Set target permissions and run method
286 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0777';
287 $newPngFile = Utility\GeneralUtility::read_png_gif($testGifFile, TRUE);
288 // Get actual permissions and clean up
289 clearstatcache();
290 $resultFilePermissions = substr(decoct(fileperms($newPngFile)), 2);
291 Utility\GeneralUtility::unlink_tempfile($newPngFile);
292 $this->assertEquals($resultFilePermissions, '0777');
293 }
294
295 ///////////////////////////
296 // Tests concerning cmpIPv4
297 ///////////////////////////
298 /**
299 * Data provider for cmpIPv4ReturnsTrueForMatchingAddress
300 *
301 * @return array Data sets
302 */
303 static public function cmpIPv4DataProviderMatching() {
304 return array(
305 'host with full IP address' => array('127.0.0.1', '127.0.0.1'),
306 'host with two wildcards at the end' => array('127.0.0.1', '127.0.*.*'),
307 'host with wildcard at third octet' => array('127.0.0.1', '127.0.*.1'),
308 'host with wildcard at second octet' => array('127.0.0.1', '127.*.0.1'),
309 '/8 subnet' => array('127.0.0.1', '127.1.1.1/8'),
310 '/32 subnet (match only name)' => array('127.0.0.1', '127.0.0.1/32'),
311 '/30 subnet' => array('10.10.3.1', '10.10.3.3/30'),
312 'host with wildcard in list with IPv4/IPv6 addresses' => array('192.168.1.1', '127.0.0.1, 1234:5678::/126, 192.168.*'),
313 'host in list with IPv4/IPv6 addresses' => array('192.168.1.1', '::1, 1234:5678::/126, 192.168.1.1'),
314 );
315 }
316
317 /**
318 * @test
319 * @dataProvider cmpIPv4DataProviderMatching
320 */
321 public function cmpIPv4ReturnsTrueForMatchingAddress($ip, $list) {
322 $this->assertTrue(Utility\GeneralUtility::cmpIPv4($ip, $list));
323 }
324
325 /**
326 * Data provider for cmpIPv4ReturnsFalseForNotMatchingAddress
327 *
328 * @return array Data sets
329 */
330 static public function cmpIPv4DataProviderNotMatching() {
331 return array(
332 'single host' => array('127.0.0.1', '127.0.0.2'),
333 'single host with wildcard' => array('127.0.0.1', '127.*.1.1'),
334 'single host with /32 subnet mask' => array('127.0.0.1', '127.0.0.2/32'),
335 '/31 subnet' => array('127.0.0.1', '127.0.0.2/31'),
336 'list with IPv4/IPv6 addresses' => array('127.0.0.1', '10.0.2.3, 192.168.1.1, ::1'),
337 'list with only IPv6 addresses' => array('10.20.30.40', '::1, 1234:5678::/127')
338 );
339 }
340
341 /**
342 * @test
343 * @dataProvider cmpIPv4DataProviderNotMatching
344 */
345 public function cmpIPv4ReturnsFalseForNotMatchingAddress($ip, $list) {
346 $this->assertFalse(Utility\GeneralUtility::cmpIPv4($ip, $list));
347 }
348
349 ///////////////////////////
350 // Tests concerning cmpIPv6
351 ///////////////////////////
352 /**
353 * Data provider for cmpIPv6ReturnsTrueForMatchingAddress
354 *
355 * @return array Data sets
356 */
357 static public function cmpIPv6DataProviderMatching() {
358 return array(
359 'empty address' => array('::', '::'),
360 'empty with netmask in list' => array('::', '::/0'),
361 'empty with netmask 0 and host-bits set in list' => array('::', '::123/0'),
362 'localhost' => array('::1', '::1'),
363 'localhost with leading zero blocks' => array('::1', '0:0::1'),
364 'host with submask /128' => array('::1', '0:0::1/128'),
365 '/16 subnet' => array('1234::1', '1234:5678::/16'),
366 '/126 subnet' => array('1234:5678::3', '1234:5678::/126'),
367 '/126 subnet with host-bits in list set' => array('1234:5678::3', '1234:5678::2/126'),
368 'list with IPv4/IPv6 addresses' => array('1234:5678::3', '::1, 127.0.0.1, 1234:5678::/126, 192.168.1.1')
369 );
370 }
371
372 /**
373 * @test
374 * @dataProvider cmpIPv6DataProviderMatching
375 */
376 public function cmpIPv6ReturnsTrueForMatchingAddress($ip, $list) {
377 $this->assertTrue(Utility\GeneralUtility::cmpIPv6($ip, $list));
378 }
379
380 /**
381 * Data provider for cmpIPv6ReturnsFalseForNotMatchingAddress
382 *
383 * @return array Data sets
384 */
385 static public function cmpIPv6DataProviderNotMatching() {
386 return array(
387 'empty against localhost' => array('::', '::1'),
388 'empty against localhost with /128 netmask' => array('::', '::1/128'),
389 'localhost against different host' => array('::1', '::2'),
390 'localhost against host with prior bits set' => array('::1', '::1:1'),
391 'host against different /17 subnet' => array('1234::1', '1234:f678::/17'),
392 'host against different /127 subnet' => array('1234:5678::3', '1234:5678::/127'),
393 'host against IPv4 address list' => array('1234:5678::3', '127.0.0.1, 192.168.1.1'),
394 'host against mixed list with IPv6 host in different subnet' => array('1234:5678::3', '::1, 1234:5678::/127')
395 );
396 }
397
398 /**
399 * @test
400 * @dataProvider cmpIPv6DataProviderNotMatching
401 */
402 public function cmpIPv6ReturnsFalseForNotMatchingAddress($ip, $list) {
403 $this->assertFalse(Utility\GeneralUtility::cmpIPv6($ip, $list));
404 }
405
406 ///////////////////////////////
407 // Tests concerning IPv6Hex2Bin
408 ///////////////////////////////
409 /**
410 * Data provider for IPv6Hex2BinCorrect
411 *
412 * @return array Data sets
413 */
414 static public function IPv6Hex2BinDataProviderCorrect() {
415 return array(
416 'empty 1' => array('::', str_pad('', 16, "\x00")),
417 'empty 2, already normalized' => array('0000:0000:0000:0000:0000:0000:0000:0000', str_pad('', 16, "\x00")),
418 'already normalized' => array('0102:0304:0000:0000:0000:0000:0506:0078', "\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78"),
419 'expansion in middle 1' => array('1::2', "\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02"),
420 'expansion in middle 2' => array('beef::fefa', "\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa"),
421 );
422 }
423
424 /**
425 * @test
426 * @dataProvider IPv6Hex2BinDataProviderCorrect
427 */
428 public function IPv6Hex2BinCorrectlyConvertsAddresses($hex, $binary) {
429 $this->assertTrue(Utility\GeneralUtility::IPv6Hex2Bin($hex) === $binary);
430 }
431
432 ///////////////////////////////
433 // Tests concerning IPv6Bin2Hex
434 ///////////////////////////////
435 /**
436 * Data provider for IPv6Bin2HexCorrect
437 *
438 * @return array Data sets
439 */
440 static public function IPv6Bin2HexDataProviderCorrect() {
441 return array(
442 'empty' => array(str_pad('', 16, "\x00"), '::'),
443 'non-empty front' => array("\x01" . str_pad('', 15, "\x00"), '100::'),
444 'non-empty back' => array(str_pad('', 15, "\x00") . "\x01", '::1'),
445 'normalized' => array("\x01\x02\x03\x04" . str_pad('', 8, "\x00") . "\x05\x06\x00\x78", '102:304::506:78'),
446 'expansion in middle 1' => array("\x00\x01" . str_pad('', 12, "\x00") . "\x00\x02", '1::2'),
447 'expansion in middle 2' => array("\xbe\xef" . str_pad('', 12, "\x00") . "\xfe\xfa", 'beef::fefa'),
448 );
449 }
450
451 /**
452 * @test
453 * @dataProvider IPv6Bin2HexDataProviderCorrect
454 */
455 public function IPv6Bin2HexCorrectlyConvertsAddresses($binary, $hex) {
456 $this->assertEquals(Utility\GeneralUtility::IPv6Bin2Hex($binary), $hex);
457 }
458
459 ////////////////////////////////////////////////
460 // Tests concerning normalizeIPv6 / compressIPv6
461 ////////////////////////////////////////////////
462 /**
463 * Data provider for normalizeIPv6ReturnsCorrectlyNormalizedFormat
464 *
465 * @return array Data sets
466 */
467 static public function normalizeCompressIPv6DataProviderCorrect() {
468 return array(
469 'empty' => array('::', '0000:0000:0000:0000:0000:0000:0000:0000'),
470 'localhost' => array('::1', '0000:0000:0000:0000:0000:0000:0000:0001'),
471 'expansion in middle 1' => array('1::2', '0001:0000:0000:0000:0000:0000:0000:0002'),
472 'expansion in middle 2' => array('1:2::3', '0001:0002:0000:0000:0000:0000:0000:0003'),
473 'expansion in middle 3' => array('1::2:3', '0001:0000:0000:0000:0000:0000:0002:0003'),
474 'expansion in middle 4' => array('1:2::3:4:5', '0001:0002:0000:0000:0000:0003:0004:0005')
475 );
476 }
477
478 /**
479 * @test
480 * @dataProvider normalizeCompressIPv6DataProviderCorrect
481 */
482 public function normalizeIPv6CorrectlyNormalizesAddresses($compressed, $normalized) {
483 $this->assertEquals($normalized, Utility\GeneralUtility::normalizeIPv6($compressed));
484 }
485
486 /**
487 * @test
488 * @dataProvider normalizeCompressIPv6DataProviderCorrect
489 */
490 public function compressIPv6CorrectlyCompressesAdresses($compressed, $normalized) {
491 $this->assertEquals($compressed, Utility\GeneralUtility::compressIPv6($normalized));
492 }
493
494 /**
495 * @test
496 */
497 public function compressIPv6CorrectlyCompressesAdressWithSomeAddressOnRightSide() {
498 if (strtolower(PHP_OS) === 'darwin') {
499 $this->markTestSkipped('This test does not work on OSX / Darwin OS.');
500 }
501 $this->assertEquals('::f0f', Utility\GeneralUtility::compressIPv6('0000:0000:0000:0000:0000:0000:0000:0f0f'));
502 }
503
504 ///////////////////////////////
505 // Tests concerning validIP
506 ///////////////////////////////
507 /**
508 * Data provider for checkValidIpReturnsTrueForValidIp
509 *
510 * @return array Data sets
511 */
512 static public function validIpDataProvider() {
513 return array(
514 '0.0.0.0' => array('0.0.0.0'),
515 'private IPv4 class C' => array('192.168.0.1'),
516 'private IPv4 class A' => array('10.0.13.1'),
517 'private IPv6' => array('fe80::daa2:5eff:fe8b:7dfb')
518 );
519 }
520
521 /**
522 * @test
523 * @dataProvider validIpDataProvider
524 */
525 public function validIpReturnsTrueForValidIp($ip) {
526 $this->assertTrue(Utility\GeneralUtility::validIP($ip));
527 }
528
529 /**
530 * Data provider for checkValidIpReturnsFalseForInvalidIp
531 *
532 * @return array Data sets
533 */
534 static public function invalidIpDataProvider() {
535 return array(
536 'null' => array(NULL),
537 'zero' => array(0),
538 'string' => array('test'),
539 'string empty' => array(''),
540 'string NULL' => array('NULL'),
541 'out of bounds IPv4' => array('300.300.300.300'),
542 'dotted decimal notation with only two dots' => array('127.0.1')
543 );
544 }
545
546 /**
547 * @test
548 * @dataProvider invalidIpDataProvider
549 */
550 public function validIpReturnsFalseForInvalidIp($ip) {
551 $this->assertFalse(Utility\GeneralUtility::validIP($ip));
552 }
553
554 ///////////////////////////////
555 // Tests concerning cmpFQDN
556 ///////////////////////////////
557 /**
558 * Data provider for cmpFqdnReturnsTrue
559 *
560 * @return array Data sets
561 */
562 static public function cmpFqdnValidDataProvider() {
563 return array(
564 'localhost should usually resolve, IPv4' => array('127.0.0.1', '*'),
565 'localhost should usually resolve, IPv6' => array('::1', '*'),
566 // other testcases with resolving not possible since it would
567 // require a working IPv4/IPv6-connectivity
568 'aaa.bbb.ccc.ddd.eee, full' => array('aaa.bbb.ccc.ddd.eee', 'aaa.bbb.ccc.ddd.eee'),
569 'aaa.bbb.ccc.ddd.eee, wildcard first' => array('aaa.bbb.ccc.ddd.eee', '*.ccc.ddd.eee'),
570 'aaa.bbb.ccc.ddd.eee, wildcard last' => array('aaa.bbb.ccc.ddd.eee', 'aaa.bbb.ccc.*'),
571 'aaa.bbb.ccc.ddd.eee, wildcard middle' => array('aaa.bbb.ccc.ddd.eee', 'aaa.*.eee'),
572 'list-matches, 1' => array('aaa.bbb.ccc.ddd.eee', 'xxx, yyy, zzz, aaa.*.eee'),
573 'list-matches, 2' => array('aaa.bbb.ccc.ddd.eee', '127:0:0:1,,aaa.*.eee,::1')
574 );
575 }
576
577 /**
578 * @test
579 * @dataProvider cmpFqdnValidDataProvider
580 */
581 public function cmpFqdnReturnsTrue($baseHost, $list) {
582 $this->assertTrue(Utility\GeneralUtility::cmpFQDN($baseHost, $list));
583 }
584
585 /**
586 * Data provider for cmpFqdnReturnsFalse
587 *
588 * @return array Data sets
589 */
590 static public function cmpFqdnInvalidDataProvider() {
591 return array(
592 'num-parts of hostname to check can only be less or equal than hostname, 1' => array('aaa.bbb.ccc.ddd.eee', 'aaa.bbb.ccc.ddd.eee.fff'),
593 'num-parts of hostname to check can only be less or equal than hostname, 2' => array('aaa.bbb.ccc.ddd.eee', 'aaa.*.bbb.ccc.ddd.eee')
594 );
595 }
596
597 /**
598 * @test
599 * @dataProvider cmpFqdnInvalidDataProvider
600 */
601 public function cmpFqdnReturnsFalse($baseHost, $list) {
602 $this->assertFalse(Utility\GeneralUtility::cmpFQDN($baseHost, $list));
603 }
604
605 ///////////////////////////////
606 // Tests concerning inList
607 ///////////////////////////////
608 /**
609 * @test
610 * @param string $haystack
611 * @dataProvider inListForItemContainedReturnsTrueDataProvider
612 */
613 public function inListForItemContainedReturnsTrue($haystack) {
614 $this->assertTrue(Utility\GeneralUtility::inList($haystack, 'findme'));
615 }
616
617 /**
618 * Data provider for inListForItemContainedReturnsTrue.
619 *
620 * @return array
621 */
622 public function inListForItemContainedReturnsTrueDataProvider() {
623 return array(
624 'Element as second element of four items' => array('one,findme,three,four'),
625 'Element at beginning of list' => array('findme,one,two'),
626 'Element at end of list' => array('one,two,findme'),
627 'One item list' => array('findme')
628 );
629 }
630
631 /**
632 * @test
633 * @param string $haystack
634 * @dataProvider inListForItemNotContainedReturnsFalseDataProvider
635 */
636 public function inListForItemNotContainedReturnsFalse($haystack) {
637 $this->assertFalse(Utility\GeneralUtility::inList($haystack, 'findme'));
638 }
639
640 /**
641 * Data provider for inListForItemNotContainedReturnsFalse.
642 *
643 * @return array
644 */
645 public function inListForItemNotContainedReturnsFalseDataProvider() {
646 return array(
647 'Four item list' => array('one,two,three,four'),
648 'One item list' => array('one'),
649 'Empty list' => array('')
650 );
651 }
652
653 ///////////////////////////////
654 // Tests concerning rmFromList
655 ///////////////////////////////
656 /**
657 * @test
658 * @param string $initialList
659 * @param string $listWithElementRemoved
660 * @dataProvider rmFromListRemovesElementsFromCommaSeparatedListDataProvider
661 */
662 public function rmFromListRemovesElementsFromCommaSeparatedList($initialList, $listWithElementRemoved) {
663 $this->assertSame($listWithElementRemoved, Utility\GeneralUtility::rmFromList('removeme', $initialList));
664 }
665
666 /**
667 * Data provider for rmFromListRemovesElementsFromCommaSeparatedList
668 *
669 * @return array
670 */
671 public function rmFromListRemovesElementsFromCommaSeparatedListDataProvider() {
672 return array(
673 'Element as second element of three' => array('one,removeme,two', 'one,two'),
674 'Element at beginning of list' => array('removeme,one,two', 'one,two'),
675 'Element at end of list' => array('one,two,removeme', 'one,two'),
676 'One item list' => array('removeme', ''),
677 'Element not contained in list' => array('one,two,three', 'one,two,three'),
678 'Empty list' => array('', '')
679 );
680 }
681
682 ///////////////////////////////
683 // Tests concerning expandList
684 ///////////////////////////////
685 /**
686 * @test
687 * @param string $list
688 * @param string $expectation
689 * @dataProvider expandListExpandsIntegerRangesDataProvider
690 */
691 public function expandListExpandsIntegerRanges($list, $expectation) {
692 $this->assertSame($expectation, Utility\GeneralUtility::expandList($list));
693 }
694
695 /**
696 * Data provider for expandListExpandsIntegerRangesDataProvider
697 *
698 * @return array
699 */
700 public function expandListExpandsIntegerRangesDataProvider() {
701 return array(
702 'Expand for the same number' => array('1,2-2,7', '1,2,7'),
703 'Small range expand with parameters reversed ignores reversed items' => array('1,5-3,7', '1,7'),
704 'Small range expand' => array('1,3-5,7', '1,3,4,5,7'),
705 'Expand at beginning' => array('3-5,1,7', '3,4,5,1,7'),
706 'Expand at end' => array('1,7,3-5', '1,7,3,4,5'),
707 'Multiple small range expands' => array('1,3-5,7-10,12', '1,3,4,5,7,8,9,10,12'),
708 'One item list' => array('1-5', '1,2,3,4,5'),
709 'Nothing to expand' => array('1,2,3,4', '1,2,3,4'),
710 'Empty list' => array('', '')
711 );
712 }
713
714 /**
715 * @test
716 */
717 public function expandListExpandsForTwoThousandElementsExpandsOnlyToThousandElementsMaximum() {
718 $list = Utility\GeneralUtility::expandList('1-2000');
719 $this->assertSame(1000, count(explode(',', $list)));
720 }
721
722 ///////////////////////////////
723 // Tests concerning uniqueList
724 ///////////////////////////////
725 /**
726 * @test
727 * @param string $initialList
728 * @param string $unifiedList
729 * @dataProvider uniqueListUnifiesCommaSeparatedListDataProvider
730 */
731 public function uniqueListUnifiesCommaSeparatedList($initialList, $unifiedList) {
732 $this->assertSame($unifiedList, Utility\GeneralUtility::uniqueList($initialList));
733 }
734
735 /**
736 * Data provider for uniqueListUnifiesCommaSeparatedList
737 *
738 * @return array
739 */
740 public function uniqueListUnifiesCommaSeparatedListDataProvider() {
741 return array(
742 'List without duplicates' => array('one,two,three', 'one,two,three'),
743 'List with two consecutive duplicates' => array('one,two,two,three,three', 'one,two,three'),
744 'List with non-consecutive duplicates' => array('one,two,three,two,three', 'one,two,three'),
745 'One item list' => array('one', 'one'),
746 'Empty list' => array('', '')
747 );
748 }
749
750 ///////////////////////////////
751 // Tests concerning isFirstPartOfStr
752 ///////////////////////////////
753 /**
754 * Data provider for isFirstPartOfStrReturnsTrueForMatchingFirstParts
755 *
756 * @return array
757 */
758 public function isFirstPartOfStrReturnsTrueForMatchingFirstPartDataProvider() {
759 return array(
760 'match first part of string' => array('hello world', 'hello'),
761 'match whole string' => array('hello', 'hello'),
762 'integer is part of string with same number' => array('24', 24),
763 'string is part of integer with same number' => array(24, '24'),
764 'integer is part of string starting with same number' => array('24 beer please', 24)
765 );
766 }
767
768 /**
769 * @test
770 * @dataProvider isFirstPartOfStrReturnsTrueForMatchingFirstPartDataProvider
771 */
772 public function isFirstPartOfStrReturnsTrueForMatchingFirstPart($string, $part) {
773 $this->assertTrue(Utility\GeneralUtility::isFirstPartOfStr($string, $part));
774 }
775
776 /**
777 * Data provider for checkIsFirstPartOfStrReturnsFalseForNotMatchingFirstParts
778 *
779 * @return array
780 */
781 public function isFirstPartOfStrReturnsFalseForNotMatchingFirstPartDataProvider() {
782 return array(
783 'no string match' => array('hello', 'bye'),
784 'no case sensitive string match' => array('hello world', 'Hello'),
785 'array is not part of string' => array('string', array()),
786 'string is not part of array' => array(array(), 'string'),
787 'NULL is not part of string' => array('string', NULL),
788 'string is not part of array' => array(NULL, 'string'),
789 'NULL is not part of array' => array(array(), NULL),
790 'array is not part of string' => array(NULL, array()),
791 'empty string is not part of empty string' => array('', ''),
792 'NULL is not part of empty string' => array('', NULL),
793 'false is not part of empty string' => array('', FALSE),
794 'empty string is not part of NULL' => array(NULL, ''),
795 'empty string is not part of false' => array(FALSE, ''),
796 'empty string is not part of zero integer' => array(0, ''),
797 'zero integer is not part of NULL' => array(NULL, 0),
798 'zero integer is not part of empty string' => array('', 0)
799 );
800 }
801
802 /**
803 * @test
804 * @dataProvider isFirstPartOfStrReturnsFalseForNotMatchingFirstPartDataProvider
805 */
806 public function isFirstPartOfStrReturnsFalseForNotMatchingFirstPart($string, $part) {
807 $this->assertFalse(Utility\GeneralUtility::isFirstPartOfStr($string, $part));
808 }
809
810 ///////////////////////////////
811 // Tests concerning formatSize
812 ///////////////////////////////
813 /**
814 * @test
815 * @dataProvider formatSizeDataProvider
816 */
817 public function formatSizeTranslatesBytesToHigherOrderRepresentation($size, $label, $expected) {
818 $this->assertEquals($expected, Utility\GeneralUtility::formatSize($size, $label));
819 }
820
821 /**
822 * Data provider for formatSizeTranslatesBytesToHigherOrderRepresentation
823 *
824 * @return array
825 */
826 public function formatSizeDataProvider() {
827 return array(
828 'Bytes keep beeing bytes (min)' => array(1, '', '1 '),
829 'Bytes keep beeing bytes (max)' => array(899, '', '899 '),
830 'Kilobytes are detected' => array(1024, '', '1.0 K'),
831 'Megabytes are detected' => array(1048576, '', '1.0 M'),
832 'Gigabytes are detected' => array(1073741824, '', '1.0 G'),
833 'Decimal is omitted for large kilobytes' => array(31080, '', '30 K'),
834 'Decimal is omitted for large megabytes' => array(31458000, '', '30 M'),
835 'Decimal is omitted for large gigabytes' => array(32212254720, '', '30 G'),
836 'Label for bytes can be exchanged' => array(1, ' Foo|||', '1 Foo'),
837 'Label for kilobytes can be exchanged' => array(1024, '| Foo||', '1.0 Foo'),
838 'Label for megabyes can be exchanged' => array(1048576, '|| Foo|', '1.0 Foo'),
839 'Label for gigabytes can be exchanged' => array(1073741824, '||| Foo', '1.0 Foo')
840 );
841 }
842
843 ///////////////////////////////
844 // Tests concerning splitCalc
845 ///////////////////////////////
846 /**
847 * Data provider for splitCalc
848 *
849 * @return array expected values, arithmetic expression
850 */
851 public function splitCalcDataProvider() {
852 return array(
853 'empty string returns empty array' => array(
854 array(),
855 ''
856 ),
857 'number without operator returns array with plus and number' => array(
858 array(array('+', 42)),
859 '42'
860 ),
861 'two numbers with asterisk return first number with plus and second number with asterisk' => array(
862 array(array('+', 42), array('*', 31)),
863 '42 * 31'
864 )
865 );
866 }
867
868 /**
869 * @test
870 * @dataProvider splitCalcDataProvider
871 */
872 public function splitCalcCorrectlySplitsExpression($expected, $expression) {
873 $this->assertEquals($expected, Utility\GeneralUtility::splitCalc($expression, '+-*/'));
874 }
875
876 ///////////////////////////////
877 // Tests concerning htmlspecialchars_decode
878 ///////////////////////////////
879 /**
880 * @test
881 */
882 public function htmlspecialcharsDecodeReturnsDecodedString() {
883 $string = '<typo3 version="6.0">&nbsp;</typo3>';
884 $encoded = htmlspecialchars($string);
885 $decoded = Utility\GeneralUtility::htmlspecialchars_decode($encoded);
886 $this->assertEquals($string, $decoded);
887 }
888
889 ///////////////////////////////
890 // Tests concerning deHSCentities
891 ///////////////////////////////
892 /**
893 * @test
894 * @dataProvider deHSCentitiesReturnsDecodedStringDataProvider
895 */
896 public function deHSCentitiesReturnsDecodedString($input, $expected) {
897 $this->assertEquals($expected, Utility\GeneralUtility::deHSCentities($input));
898 }
899
900 /**
901 * Data provider for deHSCentitiesReturnsDecodedString
902 *
903 * @return array
904 */
905 public function deHSCentitiesReturnsDecodedStringDataProvider() {
906 return array(
907 'Empty string' => array('', ''),
908 'Double encoded &' => array('&amp;amp;', '&amp;'),
909 'Double encoded numeric entity' => array('&amp;#1234;', '&#1234;'),
910 'Double encoded hexadecimal entity' => array('&amp;#x1b;', '&#x1b;'),
911 'Single encoded entities are not touched' => array('&amp; &#1234; &#x1b;', '&amp; &#1234; &#x1b;')
912 );
913 }
914
915 //////////////////////////////////
916 // Tests concerning slashJS
917 //////////////////////////////////
918 /**
919 * @test
920 * @dataProvider slashJsDataProvider
921 */
922 public function slashJsEscapesSingleQuotesAndSlashes($input, $extended, $expected) {
923 $this->assertEquals($expected, Utility\GeneralUtility::slashJS($input, $extended));
924 }
925
926 /**
927 * Data provider for slashJsEscapesSingleQuotesAndSlashes
928 *
929 * @return array
930 */
931 public function slashJsDataProvider() {
932 return array(
933 'Empty string is not changed' => array('', FALSE, ''),
934 'Normal string is not changed' => array('The cake is a lie √', FALSE, 'The cake is a lie √'),
935 'String with single quotes' => array('The \'cake\' is a lie', FALSE, 'The \\\'cake\\\' is a lie'),
936 'String with single quotes and backslashes - just escape single quotes' => array('The \\\'cake\\\' is a lie', FALSE, 'The \\\\\'cake\\\\\' is a lie'),
937 'String with single quotes and backslashes - escape both' => array('The \\\'cake\\\' is a lie', TRUE, 'The \\\\\\\'cake\\\\\\\' is a lie')
938 );
939 }
940
941 //////////////////////////////////
942 // Tests concerning rawUrlEncodeJS
943 //////////////////////////////////
944 /**
945 * @test
946 */
947 public function rawUrlEncodeJsPreservesWhitespaces() {
948 $input = 'Encode \'me\', but leave my spaces √';
949 $expected = 'Encode %27me%27%2C but leave my spaces %E2%88%9A';
950 $this->assertEquals($expected, Utility\GeneralUtility::rawUrlEncodeJS($input));
951 }
952
953 //////////////////////////////////
954 // Tests concerning rawUrlEncodeJS
955 //////////////////////////////////
956 /**
957 * @test
958 */
959 public function rawUrlEncodeFpPreservesSlashes() {
960 $input = 'Encode \'me\', but leave my / √';
961 $expected = 'Encode%20%27me%27%2C%20but%20leave%20my%20/%20%E2%88%9A';
962 $this->assertEquals($expected, Utility\GeneralUtility::rawUrlEncodeFP($input));
963 }
964
965 //////////////////////////////////
966 // Tests concerning strtoupper / strtolower
967 //////////////////////////////////
968 /**
969 * Data provider for strtoupper and strtolower
970 *
971 * @return array
972 */
973 public function strtouppperDataProvider() {
974 return array(
975 'Empty string' => array('', ''),
976 'String containing only latin characters' => array('the cake is a lie.', 'THE CAKE IS A LIE.'),
977 'String with umlauts and accent characters' => array('the càkê is ä lie.', 'THE CàKê IS ä LIE.')
978 );
979 }
980
981 /**
982 * @test
983 * @dataProvider strtouppperDataProvider
984 */
985 public function strtoupperConvertsOnlyLatinCharacters($input, $expected) {
986 $this->assertEquals($expected, Utility\GeneralUtility::strtoupper($input));
987 }
988
989 /**
990 * @test
991 * @dataProvider strtouppperDataProvider
992 */
993 public function strtolowerConvertsOnlyLatinCharacters($expected, $input) {
994 $this->assertEquals($expected, Utility\GeneralUtility::strtolower($input));
995 }
996
997 //////////////////////////////////
998 // Tests concerning validEmail
999 //////////////////////////////////
1000 /**
1001 * Data provider for valid validEmail's
1002 *
1003 * @return array Valid email addresses
1004 */
1005 public function validEmailValidDataProvider() {
1006 return array(
1007 'short mail address' => array('a@b.c'),
1008 'simple mail address' => array('test@example.com'),
1009 'uppercase characters' => array('QWERTYUIOPASDFGHJKLZXCVBNM@QWERTYUIOPASDFGHJKLZXCVBNM.NET'),
1010 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6 and 5.3.2 but fails with 5.3.0 on windows
1011 // 'equal sign in local part' => array('test=mail@example.com'),
1012 'dash in local part' => array('test-mail@example.com'),
1013 'plus in local part' => array('test+mail@example.com'),
1014 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6 and 5.3.2 but fails with 5.3.0 on windows
1015 // 'question mark in local part' => array('test?mail@example.com'),
1016 'slash in local part' => array('foo/bar@example.com'),
1017 'hash in local part' => array('foo#bar@example.com'),
1018 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6 and 5.3.2 but fails with 5.3.0 on windows
1019 // 'dot in local part' => array('firstname.lastname@employee.2something.com'),
1020 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6, but not ok with 5.3.2
1021 // 'dash as local part' => array('-@foo.com'),
1022 'umlauts in local part' => array('äöüfoo@bar.com'),
1023 'umlauts in domain part' => array('foo@äöüfoo.com')
1024 );
1025 }
1026
1027 /**
1028 * @test
1029 * @dataProvider validEmailValidDataProvider
1030 */
1031 public function validEmailReturnsTrueForValidMailAddress($address) {
1032 $this->assertTrue(Utility\GeneralUtility::validEmail($address));
1033 }
1034
1035 /**
1036 * Data provider for invalid validEmail's
1037 *
1038 * @return array Invalid email addresses
1039 */
1040 public function validEmailInvalidDataProvider() {
1041 return array(
1042 'empty string' => array(''),
1043 'empty array' => array(array()),
1044 'integer' => array(42),
1045 'float' => array(42.23),
1046 'array' => array(array('foo')),
1047 'object' => array(new \stdClass()),
1048 '@ sign only' => array('@'),
1049 'string longer than 320 characters' => array(str_repeat('0123456789', 33)),
1050 'duplicate @' => array('test@@example.com'),
1051 'duplicate @ combined with further special characters in local part' => array('test!.!@#$%^&*@example.com'),
1052 'opening parenthesis in local part' => array('foo(bar@example.com'),
1053 'closing parenthesis in local part' => array('foo)bar@example.com'),
1054 'opening square bracket in local part' => array('foo[bar@example.com'),
1055 'closing square bracket as local part' => array(']@example.com'),
1056 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6, but not ok with 5.3.2
1057 // 'top level domain only' => array('test@com'),
1058 'dash as second level domain' => array('foo@-.com'),
1059 'domain part starting with dash' => array('foo@-foo.com'),
1060 'domain part ending with dash' => array('foo@foo-.com'),
1061 'number as top level domain' => array('foo@bar.123'),
1062 // Fix / change if TYPO3 php requirement changed: Address not ok with 5.2.6, but ok with 5.3.2 (?)
1063 // 'dash as top level domain' => array('foo@bar.-'),
1064 'dot at beginning of domain part' => array('test@.com'),
1065 // Fix / change if TYPO3 php requirement changed: Address ok with 5.2.6, but not ok with 5.3.2
1066 // 'local part ends with dot' => array('e.x.a.m.p.l.e.@example.com'),
1067 'trailing whitespace' => array('test@example.com '),
1068 'trailing carriage return' => array('test@example.com' . CR),
1069 'trailing linefeed' => array('test@example.com' . LF),
1070 'trailing carriage return linefeed' => array('test@example.com' . CRLF),
1071 'trailing tab' => array('test@example.com' . TAB)
1072 );
1073 }
1074
1075 /**
1076 * @test
1077 * @dataProvider validEmailInvalidDataProvider
1078 */
1079 public function validEmailReturnsFalseForInvalidMailAddress($address) {
1080 $this->assertFalse(Utility\GeneralUtility::validEmail($address));
1081 }
1082
1083 //////////////////////////////////
1084 // Tests concerning inArray
1085 //////////////////////////////////
1086 /**
1087 * @test
1088 * @dataProvider inArrayDataProvider
1089 */
1090 public function inArrayChecksStringExistenceWithinArray($array, $item, $expected) {
1091 $this->assertEquals($expected, Utility\GeneralUtility::inArray($array, $item));
1092 }
1093
1094 /**
1095 * Data provider for inArrayChecksStringExistenceWithinArray
1096 *
1097 * @return array
1098 */
1099 public function inArrayDataProvider() {
1100 return array(
1101 'Empty array' => array(array(), 'search', FALSE),
1102 'One item array no match' => array(array('one'), 'two', FALSE),
1103 'One item array match' => array(array('one'), 'one', TRUE),
1104 'Multiple items array no match' => array(array('one', 2, 'three', 4), 'four', FALSE),
1105 'Multiple items array match' => array(array('one', 2, 'three', 4), 'three', TRUE),
1106 'Integer search items can match string values' => array(array('0', '1', '2'), 1, TRUE),
1107 'Search item is not casted to integer for a match' => array(array(4), '4a', FALSE),
1108 'Empty item won\'t match - in contrast to the php-builtin ' => array(array(0, 1, 2), '', FALSE)
1109 );
1110 }
1111
1112 //////////////////////////////////
1113 // Tests concerning intExplode
1114 //////////////////////////////////
1115 /**
1116 * @test
1117 */
1118 public function intExplodeConvertsStringsToInteger() {
1119 $testString = '1,foo,2';
1120 $expectedArray = array(1, 0, 2);
1121 $actualArray = Utility\GeneralUtility::intExplode(',', $testString);
1122 $this->assertEquals($expectedArray, $actualArray);
1123 }
1124
1125 //////////////////////////////////
1126 // Tests concerning keepItemsInArray
1127 //////////////////////////////////
1128 /**
1129 * @test
1130 * @dataProvider keepItemsInArrayWorksWithOneArgumentDataProvider
1131 */
1132 public function keepItemsInArrayWorksWithOneArgument($search, $array, $expected) {
1133 $this->assertEquals($expected, Utility\GeneralUtility::keepItemsInArray($array, $search));
1134 }
1135
1136 /**
1137 * Data provider for keepItemsInArrayWorksWithOneArgument
1138 *
1139 * @return array
1140 */
1141 public function keepItemsInArrayWorksWithOneArgumentDataProvider() {
1142 $array = array(
1143 'one' => 'one',
1144 'two' => 'two',
1145 'three' => 'three'
1146 );
1147 return array(
1148 'Empty argument will match "all" elements' => array(NULL, $array, $array),
1149 'No match' => array('four', $array, array()),
1150 'One match' => array('two', $array, array('two' => 'two')),
1151 'Multiple matches' => array('two,one', $array, array('one' => 'one', 'two' => 'two')),
1152 'Argument can be an array' => array(array('three'), $array, array('three' => 'three'))
1153 );
1154 }
1155
1156 /**
1157 * Shows the exmaple from the doc comment where
1158 * a function is used to reduce the sub arrays to one item which
1159 * is then used for the matching.
1160 *
1161 * @test
1162 */
1163 public function keepItemsInArrayCanUseCallbackOnSearchArray() {
1164 $array = array(
1165 'aa' => array('first', 'second'),
1166 'bb' => array('third', 'fourth'),
1167 'cc' => array('fifth', 'sixth')
1168 );
1169 $expected = array('bb' => array('third', 'fourth'));
1170 $keepItems = 'third';
1171 $getValueFunc = create_function('$value', 'return $value[0];');
1172 $match = Utility\GeneralUtility::keepItemsInArray($array, $keepItems, $getValueFunc);
1173 $this->assertEquals($expected, $match);
1174 }
1175
1176 //////////////////////////////////
1177 // Tests concerning implodeArrayForUrl / explodeUrl2Array
1178 //////////////////////////////////
1179 /**
1180 * Data provider for implodeArrayForUrlBuildsValidParameterString and
1181 * explodeUrl2ArrayTransformsParameterStringToArray
1182 *
1183 * @return array
1184 */
1185 public function implodeArrayForUrlDataProvider() {
1186 $valueArray = array('one' => '√', 'two' => 2);
1187 return array(
1188 'Empty input' => array('foo', array(), ''),
1189 'String parameters' => array('foo', $valueArray, '&foo[one]=%E2%88%9A&foo[two]=2'),
1190 'Nested array parameters' => array('foo', array($valueArray), '&foo[0][one]=%E2%88%9A&foo[0][two]=2'),
1191 'Keep blank parameters' => array('foo', array('one' => '√', ''), '&foo[one]=%E2%88%9A&foo[0]=')
1192 );
1193 }
1194
1195 /**
1196 * @test
1197 * @dataProvider implodeArrayForUrlDataProvider
1198 */
1199 public function implodeArrayForUrlBuildsValidParameterString($name, $input, $expected) {
1200 $this->assertSame($expected, Utility\GeneralUtility::implodeArrayForUrl($name, $input));
1201 }
1202
1203 /**
1204 * @test
1205 */
1206 public function implodeArrayForUrlCanSkipEmptyParameters() {
1207 $input = array('one' => '√', '');
1208 $expected = '&foo[one]=%E2%88%9A';
1209 $this->assertSame($expected, Utility\GeneralUtility::implodeArrayForUrl('foo', $input, '', TRUE));
1210 }
1211
1212 /**
1213 * @test
1214 */
1215 public function implodeArrayForUrlCanUrlEncodeKeyNames() {
1216 $input = array('one' => '√', '');
1217 $expected = '&foo%5Bone%5D=%E2%88%9A&foo%5B0%5D=';
1218 $this->assertSame($expected, Utility\GeneralUtility::implodeArrayForUrl('foo', $input, '', FALSE, TRUE));
1219 }
1220
1221 /**
1222 * @test
1223 * @dataProvider implodeArrayForUrlDataProvider
1224 */
1225 public function explodeUrl2ArrayTransformsParameterStringToNestedArray($name, $array, $input) {
1226 $expected = $array ? array($name => $array) : array();
1227 $this->assertEquals($expected, Utility\GeneralUtility::explodeUrl2Array($input, TRUE));
1228 }
1229
1230 /**
1231 * @test
1232 * @dataProvider explodeUrl2ArrayDataProvider
1233 */
1234 public function explodeUrl2ArrayTransformsParameterStringToFlatArray($input, $expected) {
1235 $this->assertEquals($expected, Utility\GeneralUtility::explodeUrl2Array($input, FALSE));
1236 }
1237
1238 /**
1239 * Data provider for explodeUrl2ArrayTransformsParameterStringToFlatArray
1240 *
1241 * @return array
1242 */
1243 public function explodeUrl2ArrayDataProvider() {
1244 return array(
1245 'Empty string' => array('', array()),
1246 'Simple parameter string' => array('&one=%E2%88%9A&two=2', array('one' => '√', 'two' => 2)),
1247 'Nested parameter string' => array('&foo[one]=%E2%88%9A&two=2', array('foo[one]' => '√', 'two' => 2))
1248 );
1249 }
1250
1251 //////////////////////////////////
1252 // Tests concerning compileSelectedGetVarsFromArray
1253 //////////////////////////////////
1254 /**
1255 * @test
1256 */
1257 public function compileSelectedGetVarsFromArrayFiltersIncomingData() {
1258 $filter = 'foo,bar';
1259 $getArray = array('foo' => 1, 'cake' => 'lie');
1260 $expected = array('foo' => 1);
1261 $result = Utility\GeneralUtility::compileSelectedGetVarsFromArray($filter, $getArray, FALSE);
1262 $this->assertSame($expected, $result);
1263 }
1264
1265 /**
1266 * @test
1267 */
1268 public function compileSelectedGetVarsFromArrayUsesGetPostDataFallback() {
1269 $_GET['bar'] = '2';
1270 $filter = 'foo,bar';
1271 $getArray = array('foo' => 1, 'cake' => 'lie');
1272 $expected = array('foo' => 1, 'bar' => '2');
1273 $result = Utility\GeneralUtility::compileSelectedGetVarsFromArray($filter, $getArray, TRUE);
1274 $this->assertSame($expected, $result);
1275 }
1276
1277 //////////////////////////////////
1278 // Tests concerning remapArrayKeys
1279 //////////////////////////////////
1280 /**
1281 * @test
1282 */
1283 public function remapArrayKeysExchangesKeysWithGivenMapping() {
1284 $array = array(
1285 'one' => 'one',
1286 'two' => 'two',
1287 'three' => 'three'
1288 );
1289 $keyMapping = array(
1290 'one' => '1',
1291 'two' => '2'
1292 );
1293 $expected = array(
1294 '1' => 'one',
1295 '2' => 'two',
1296 'three' => 'three'
1297 );
1298 Utility\GeneralUtility::remapArrayKeys($array, $keyMapping);
1299 $this->assertEquals($expected, $array);
1300 }
1301
1302 //////////////////////////////////
1303 // Tests concerning array_merge
1304 //////////////////////////////////
1305 /**
1306 * Test demonstrating array_merge. This is actually
1307 * a native PHP operator, therefore this test is mainly used to
1308 * show how this function can be used.
1309 *
1310 * @test
1311 */
1312 public function arrayMergeKeepsIndexesAfterMerge() {
1313 $array1 = array(10 => 'FOO', '20' => 'BAR');
1314 $array2 = array('5' => 'PLONK');
1315 $expected = array('5' => 'PLONK', 10 => 'FOO', '20' => 'BAR');
1316 $this->assertEquals($expected, Utility\GeneralUtility::array_merge($array1, $array2));
1317 }
1318
1319 //////////////////////////////////
1320 // Tests concerning revExplode
1321 //////////////////////////////////
1322 /**
1323 * @test
1324 */
1325 public function revExplodeExplodesString() {
1326 $testString = 'my:words:here';
1327 $expectedArray = array('my:words', 'here');
1328 $actualArray = Utility\GeneralUtility::revExplode(':', $testString, 2);
1329 $this->assertEquals($expectedArray, $actualArray);
1330 }
1331
1332 //////////////////////////////////
1333 // Tests concerning trimExplode
1334 //////////////////////////////////
1335 /**
1336 * @test
1337 */
1338 public function checkTrimExplodeTrimsSpacesAtElementStartAndEnd() {
1339 $testString = ' a , b , c ,d ,, e,f,';
1340 $expectedArray = array('a', 'b', 'c', 'd', '', 'e', 'f', '');
1341 $actualArray = Utility\GeneralUtility::trimExplode(',', $testString);
1342 $this->assertEquals($expectedArray, $actualArray);
1343 }
1344
1345 /**
1346 * @test
1347 */
1348 public function checkTrimExplodeRemovesNewLines() {
1349 $testString = ' a , b , ' . LF . ' ,d ,, e,f,';
1350 $expectedArray = array('a', 'b', 'd', 'e', 'f');
1351 $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE);
1352 $this->assertEquals($expectedArray, $actualArray);
1353 }
1354
1355 /**
1356 * @test
1357 */
1358 public function checkTrimExplodeRemovesEmptyElements() {
1359 $testString = 'a , b , c , ,d ,, ,e,f,';
1360 $expectedArray = array('a', 'b', 'c', 'd', 'e', 'f');
1361 $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE);
1362 $this->assertEquals($expectedArray, $actualArray);
1363 }
1364
1365 /**
1366 * @test
1367 */
1368 public function checkTrimExplodeKeepsRemainingResultsWithEmptyItemsAfterReachingLimitWithPositiveParameter() {
1369 $testString = ' a , b , c , , d,, ,e ';
1370 $expectedArray = array('a', 'b', 'c,,d,,,e');
1371 // Limiting returns the rest of the string as the last element
1372 $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, FALSE, 3);
1373 $this->assertEquals($expectedArray, $actualArray);
1374 }
1375
1376 /**
1377 * @test
1378 */
1379 public function checkTrimExplodeKeepsRemainingResultsWithoutEmptyItemsAfterReachingLimitWithPositiveParameter() {
1380 $testString = ' a , b , c , , d,, ,e ';
1381 $expectedArray = array('a', 'b', 'c,d,e');
1382 // Limiting returns the rest of the string as the last element
1383 $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE, 3);
1384 $this->assertEquals($expectedArray, $actualArray);
1385 }
1386
1387 /**
1388 * @test
1389 */
1390 public function checkTrimExplodeKeepsRamainingResultsWithEmptyItemsAfterReachingLimitWithNegativeParameter() {
1391 $testString = ' a , b , c , d, ,e, f , , ';
1392 $expectedArray = array('a', 'b', 'c', 'd', '', 'e');
1393 // limiting returns the rest of the string as the last element
1394 $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, FALSE, -3);
1395 $this->assertEquals($expectedArray, $actualArray);
1396 }
1397
1398 /**
1399 * @test
1400 */
1401 public function checkTrimExplodeKeepsRamainingResultsWithoutEmptyItemsAfterReachingLimitWithNegativeParameter() {
1402 $testString = ' a , b , c , d, ,e, f , , ';
1403 $expectedArray = array('a', 'b', 'c');
1404 // Limiting returns the rest of the string as the last element
1405 $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE, -3);
1406 $this->assertEquals($expectedArray, $actualArray);
1407 }
1408
1409 /**
1410 * @test
1411 */
1412 public function checkTrimExplodeReturnsExactResultsWithoutReachingLimitWithPositiveParameter() {
1413 $testString = ' a , b , , c , , , ';
1414 $expectedArray = array('a', 'b', 'c');
1415 // Limiting returns the rest of the string as the last element
1416 $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE, 4);
1417 $this->assertEquals($expectedArray, $actualArray);
1418 }
1419
1420 /**
1421 * @test
1422 */
1423 public function checkTrimExplodeKeepsZeroAsString() {
1424 $testString = 'a , b , c , ,d ,, ,e,f, 0 ,';
1425 $expectedArray = array('a', 'b', 'c', 'd', 'e', 'f', '0');
1426 $actualArray = Utility\GeneralUtility::trimExplode(',', $testString, TRUE);
1427 $this->assertEquals($expectedArray, $actualArray);
1428 }
1429
1430 //////////////////////////////////
1431 // Tests concerning removeArrayEntryByValue
1432 //////////////////////////////////
1433 /**
1434 * @test
1435 */
1436 public function checkRemoveArrayEntryByValueRemovesEntriesFromOneDimensionalArray() {
1437 $inputArray = array(
1438 '0' => 'test1',
1439 '1' => 'test2',
1440 '2' => 'test3',
1441 '3' => 'test2'
1442 );
1443 $compareValue = 'test2';
1444 $expectedResult = array(
1445 '0' => 'test1',
1446 '2' => 'test3'
1447 );
1448 $actualResult = Utility\GeneralUtility::removeArrayEntryByValue($inputArray, $compareValue);
1449 $this->assertEquals($expectedResult, $actualResult);
1450 }
1451
1452 /**
1453 * @test
1454 */
1455 public function checkRemoveArrayEntryByValueRemovesEntriesFromMultiDimensionalArray() {
1456 $inputArray = array(
1457 '0' => 'foo',
1458 '1' => array(
1459 '10' => 'bar'
1460 ),
1461 '2' => 'bar'
1462 );
1463 $compareValue = 'bar';
1464 $expectedResult = array(
1465 '0' => 'foo',
1466 '1' => array()
1467 );
1468 $actualResult = Utility\GeneralUtility::removeArrayEntryByValue($inputArray, $compareValue);
1469 $this->assertEquals($expectedResult, $actualResult);
1470 }
1471
1472 /**
1473 * @test
1474 */
1475 public function checkRemoveArrayEntryByValueRemovesEntryWithEmptyString() {
1476 $inputArray = array(
1477 '0' => 'foo',
1478 '1' => '',
1479 '2' => 'bar'
1480 );
1481 $compareValue = '';
1482 $expectedResult = array(
1483 '0' => 'foo',
1484 '2' => 'bar'
1485 );
1486 $actualResult = Utility\GeneralUtility::removeArrayEntryByValue($inputArray, $compareValue);
1487 $this->assertEquals($expectedResult, $actualResult);
1488 }
1489
1490 //////////////////////////////////
1491 // Tests concerning getBytesFromSizeMeasurement
1492 //////////////////////////////////
1493 /**
1494 * Data provider for getBytesFromSizeMeasurement
1495 *
1496 * @return array expected value, input string
1497 */
1498 public function getBytesFromSizeMeasurementDataProvider() {
1499 return array(
1500 '100 kilo Bytes' => array('102400', '100k'),
1501 '100 mega Bytes' => array('104857600', '100m'),
1502 '100 giga Bytes' => array('107374182400', '100g')
1503 );
1504 }
1505
1506 /**
1507 * @test
1508 * @dataProvider getBytesFromSizeMeasurementDataProvider
1509 */
1510 public function getBytesFromSizeMeasurementCalculatesCorrectByteValue($expected, $byteString) {
1511 $this->assertEquals($expected, Utility\GeneralUtility::getBytesFromSizeMeasurement($byteString));
1512 }
1513
1514 //////////////////////////////////
1515 // Tests concerning getIndpEnv
1516 //////////////////////////////////
1517 /**
1518 * @test
1519 */
1520 public function getIndpEnvTypo3SitePathReturnNonEmptyString() {
1521 $this->assertTrue(strlen(Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH')) >= 1);
1522 }
1523
1524 /**
1525 * @test
1526 */
1527 public function getIndpEnvTypo3SitePathReturnsStringStartingWithSlash() {
1528 $result = Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
1529 $this->assertEquals('/', $result[0]);
1530 }
1531
1532 /**
1533 * @test
1534 */
1535 public function getIndpEnvTypo3SitePathReturnsStringEndingWithSlash() {
1536 $result = Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
1537 $this->assertEquals('/', $result[strlen($result) - 1]);
1538 }
1539
1540 /**
1541 * @return array
1542 */
1543 static public function hostnameAndPortDataProvider() {
1544 return array(
1545 'localhost ipv4 without port' => array('127.0.0.1', '127.0.0.1', ''),
1546 'localhost ipv4 with port' => array('127.0.0.1:81', '127.0.0.1', '81'),
1547 'localhost ipv6 without port' => array('[::1]', '[::1]', ''),
1548 'localhost ipv6 with port' => array('[::1]:81', '[::1]', '81'),
1549 'ipv6 without port' => array('[2001:DB8::1]', '[2001:DB8::1]', ''),
1550 'ipv6 with port' => array('[2001:DB8::1]:81', '[2001:DB8::1]', '81'),
1551 'hostname without port' => array('lolli.did.this', 'lolli.did.this', ''),
1552 'hostname with port' => array('lolli.did.this:42', 'lolli.did.this', '42')
1553 );
1554 }
1555
1556 /**
1557 * @test
1558 * @dataProvider hostnameAndPortDataProvider
1559 */
1560 public function getIndpEnvTypo3HostOnlyParsesHostnamesAndIpAdresses($httpHost, $expectedIp) {
1561 $_SERVER['HTTP_HOST'] = $httpHost;
1562 $this->assertEquals($expectedIp, Utility\GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY'));
1563 }
1564
1565 /**
1566 * @test
1567 * @dataProvider hostnameAndPortDataProvider
1568 */
1569 public function getIndpEnvTypo3PortParsesHostnamesAndIpAdresses($httpHost, $dummy, $expectedPort) {
1570 $_SERVER['HTTP_HOST'] = $httpHost;
1571 $this->assertEquals($expectedPort, Utility\GeneralUtility::getIndpEnv('TYPO3_PORT'));
1572 }
1573
1574 //////////////////////////////////
1575 // Tests concerning underscoredToUpperCamelCase
1576 //////////////////////////////////
1577 /**
1578 * Data provider for underscoredToUpperCamelCase
1579 *
1580 * @return array expected, input string
1581 */
1582 public function underscoredToUpperCamelCaseDataProvider() {
1583 return array(
1584 'single word' => array('Blogexample', 'blogexample'),
1585 'multiple words' => array('BlogExample', 'blog_example')
1586 );
1587 }
1588
1589 /**
1590 * @test
1591 * @dataProvider underscoredToUpperCamelCaseDataProvider
1592 */
1593 public function underscoredToUpperCamelCase($expected, $inputString) {
1594 $this->assertEquals($expected, Utility\GeneralUtility::underscoredToUpperCamelCase($inputString));
1595 }
1596
1597 //////////////////////////////////
1598 // Tests concerning underscoredToLowerCamelCase
1599 //////////////////////////////////
1600 /**
1601 * Data provider for underscoredToLowerCamelCase
1602 *
1603 * @return array expected, input string
1604 */
1605 public function underscoredToLowerCamelCaseDataProvider() {
1606 return array(
1607 'single word' => array('minimalvalue', 'minimalvalue'),
1608 'multiple words' => array('minimalValue', 'minimal_value')
1609 );
1610 }
1611
1612 /**
1613 * @test
1614 * @dataProvider underscoredToLowerCamelCaseDataProvider
1615 */
1616 public function underscoredToLowerCamelCase($expected, $inputString) {
1617 $this->assertEquals($expected, Utility\GeneralUtility::underscoredToLowerCamelCase($inputString));
1618 }
1619
1620 //////////////////////////////////
1621 // Tests concerning camelCaseToLowerCaseUnderscored
1622 //////////////////////////////////
1623 /**
1624 * Data provider for camelCaseToLowerCaseUnderscored
1625 *
1626 * @return array expected, input string
1627 */
1628 public function camelCaseToLowerCaseUnderscoredDataProvider() {
1629 return array(
1630 'single word' => array('blogexample', 'blogexample'),
1631 'single word starting upper case' => array('blogexample', 'Blogexample'),
1632 'two words starting lower case' => array('minimal_value', 'minimalValue'),
1633 'two words starting upper case' => array('blog_example', 'BlogExample')
1634 );
1635 }
1636
1637 /**
1638 * @test
1639 * @dataProvider camelCaseToLowerCaseUnderscoredDataProvider
1640 */
1641 public function camelCaseToLowerCaseUnderscored($expected, $inputString) {
1642 $this->assertEquals($expected, Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($inputString));
1643 }
1644
1645 //////////////////////////////////
1646 // Tests concerning lcFirst
1647 //////////////////////////////////
1648 /**
1649 * Data provider for lcFirst
1650 *
1651 * @return array expected, input string
1652 */
1653 public function lcfirstDataProvider() {
1654 return array(
1655 'single word' => array('blogexample', 'blogexample'),
1656 'single Word starting upper case' => array('blogexample', 'Blogexample'),
1657 'two words' => array('blogExample', 'BlogExample')
1658 );
1659 }
1660
1661 /**
1662 * @test
1663 * @dataProvider lcfirstDataProvider
1664 */
1665 public function lcFirst($expected, $inputString) {
1666 $this->assertEquals($expected, Utility\GeneralUtility::lcfirst($inputString));
1667 }
1668
1669 //////////////////////////////////
1670 // Tests concerning encodeHeader
1671 //////////////////////////////////
1672 /**
1673 * @test
1674 */
1675 public function encodeHeaderEncodesWhitespacesInQuotedPrintableMailHeader() {
1676 $this->assertEquals('=?utf-8?Q?We_test_whether_the_copyright_character_=C2=A9_is_encoded_correctly?=', Utility\GeneralUtility::encodeHeader('We test whether the copyright character © is encoded correctly', 'quoted-printable', 'utf-8'));
1677 }
1678
1679 /**
1680 * @test
1681 */
1682 public function encodeHeaderEncodesQuestionmarksInQuotedPrintableMailHeader() {
1683 $this->assertEquals('=?utf-8?Q?Is_the_copyright_character_=C2=A9_really_encoded_correctly=3F_Really=3F?=', Utility\GeneralUtility::encodeHeader('Is the copyright character © really encoded correctly? Really?', 'quoted-printable', 'utf-8'));
1684 }
1685
1686 //////////////////////////////////
1687 // Tests concerning isValidUrl
1688 //////////////////////////////////
1689 /**
1690 * Data provider for valid isValidUrl's
1691 *
1692 * @return array Valid ressource
1693 */
1694 public function validUrlValidRessourceDataProvider() {
1695 return array(
1696 'http' => array('http://www.example.org/'),
1697 'http without trailing slash' => array('http://qwe'),
1698 'http directory with trailing slash' => array('http://www.example/img/dir/'),
1699 'http directory without trailing slash' => array('http://www.example/img/dir'),
1700 'http index.html' => array('http://example.com/index.html'),
1701 'http index.php' => array('http://www.example.com/index.php'),
1702 'http test.png' => array('http://www.example/img/test.png'),
1703 'http username password querystring and ancher' => array('https://user:pw@www.example.org:80/path?arg=value#fragment'),
1704 'file' => array('file:///tmp/test.c'),
1705 'file directory' => array('file://foo/bar'),
1706 'ftp directory' => array('ftp://ftp.example.com/tmp/'),
1707 'mailto' => array('mailto:foo@bar.com'),
1708 'news' => array('news:news.php.net'),
1709 'telnet' => array('telnet://192.0.2.16:80/'),
1710 'ldap' => array('ldap://[2001:db8::7]/c=GB?objectClass?one'),
1711 'http punycode domain name' => array('http://www.xn--bb-eka.at'),
1712 'http punicode subdomain' => array('http://xn--h-zfa.oebb.at'),
1713 'http domain-name umlauts' => array('http://www.öbb.at'),
1714 'http subdomain umlauts' => array('http://äh.oebb.at'),
1715 'http directory umlauts' => array('http://www.oebb.at/äöü/')
1716 );
1717 }
1718
1719 /**
1720 * @test
1721 * @dataProvider validUrlValidRessourceDataProvider
1722 */
1723 public function validURLReturnsTrueForValidRessource($url) {
1724 $this->assertTrue(Utility\GeneralUtility::isValidUrl($url));
1725 }
1726
1727 /**
1728 * Data provider for invalid isValidUrl's
1729 *
1730 * @return array Invalid ressource
1731 */
1732 public function isValidUrlInvalidRessourceDataProvider() {
1733 return array(
1734 'http missing colon' => array('http//www.example/wrong/url/'),
1735 'http missing slash' => array('http:/www.example'),
1736 'hostname only' => array('www.example.org/'),
1737 'file missing protocol specification' => array('/tmp/test.c'),
1738 'slash only' => array('/'),
1739 'string http://' => array('http://'),
1740 'string http:/' => array('http:/'),
1741 'string http:' => array('http:'),
1742 'string http' => array('http'),
1743 'empty string' => array(''),
1744 'string -1' => array('-1'),
1745 'string array()' => array('array()'),
1746 'random string' => array('qwe')
1747 );
1748 }
1749
1750 /**
1751 * @test
1752 * @dataProvider isValidUrlInvalidRessourceDataProvider
1753 */
1754 public function validURLReturnsFalseForInvalidRessoure($url) {
1755 $this->assertFalse(Utility\GeneralUtility::isValidUrl($url));
1756 }
1757
1758 //////////////////////////////////
1759 // Tests concerning isOnCurrentHost
1760 //////////////////////////////////
1761 /**
1762 * @test
1763 */
1764 public function isOnCurrentHostReturnsTrueWithCurrentHost() {
1765 $testUrl = Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_URL');
1766 $this->assertTrue(Utility\GeneralUtility::isOnCurrentHost($testUrl));
1767 }
1768
1769 /**
1770 * Data provider for invalid isOnCurrentHost's
1771 *
1772 * @return array Invalid Hosts
1773 */
1774 public function checkisOnCurrentHostInvalidHosts() {
1775 return array(
1776 'empty string' => array(''),
1777 'arbitrary string' => array('arbitrary string'),
1778 'localhost IP' => array('127.0.0.1'),
1779 'relative path' => array('./relpath/file.txt'),
1780 'absolute path' => array('/abspath/file.txt?arg=value'),
1781 'differnt host' => array(Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_HOST') . '.example.org')
1782 );
1783 }
1784
1785 ////////////////////////////////////////
1786 // Tests concerning sanitizeLocalUrl
1787 ////////////////////////////////////////
1788 /**
1789 * Data provider for valid sanitizeLocalUrl's
1790 *
1791 * @return array Valid url
1792 */
1793 public function sanitizeLocalUrlValidUrlDataProvider() {
1794 $subDirectory = Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_PATH');
1795 $typo3SiteUrl = Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
1796 $typo3RequestHost = Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_HOST');
1797 return array(
1798 'alt_intro.php' => array('alt_intro.php'),
1799 'alt_intro.php?foo=1&bar=2' => array('alt_intro.php?foo=1&bar=2'),
1800 $subDirectory . 'typo3/alt_intro.php' => array($subDirectory . 'typo3/alt_intro.php'),
1801 $subDirectory . 'index.php' => array($subDirectory . 'index.php'),
1802 '../index.php' => array('../index.php'),
1803 '../typo3/alt_intro.php' => array('../typo3/alt_intro.php'),
1804 '../~userDirectory/index.php' => array('../~userDirectory/index.php'),
1805 '../typo3/mod.php?var1=test-case&var2=~user' => array('../typo3/mod.php?var1=test-case&var2=~user'),
1806 PATH_site . 'typo3/alt_intro.php' => array(PATH_site . 'typo3/alt_intro.php'),
1807 $typo3SiteUrl . 'typo3/alt_intro.php' => array($typo3SiteUrl . 'typo3/alt_intro.php'),
1808 $typo3RequestHost . $subDirectory . '/index.php' => array($typo3RequestHost . $subDirectory . '/index.php')
1809 );
1810 }
1811
1812 /**
1813 * @test
1814 * @dataProvider sanitizeLocalUrlValidUrlDataProvider
1815 */
1816 public function sanitizeLocalUrlAcceptsNotEncodedValidUrls($url) {
1817 $this->assertEquals($url, Utility\GeneralUtility::sanitizeLocalUrl($url));
1818 }
1819
1820 /**
1821 * @test
1822 * @dataProvider sanitizeLocalUrlValidUrlDataProvider
1823 */
1824 public function sanitizeLocalUrlAcceptsEncodedValidUrls($url) {
1825 $this->assertEquals(rawurlencode($url), Utility\GeneralUtility::sanitizeLocalUrl(rawurlencode($url)));
1826 }
1827
1828 /**
1829 * Data provider for invalid sanitizeLocalUrl's
1830 *
1831 * @return array Valid url
1832 */
1833 public function sanitizeLocalUrlInvalidDataProvider() {
1834 return array(
1835 'empty string' => array(''),
1836 'http domain' => array('http://www.google.de/'),
1837 'https domain' => array('https://www.google.de/'),
1838 'relative path with XSS' => array('../typo3/whatever.php?argument=javascript:alert(0)')
1839 );
1840 }
1841
1842 /**
1843 * @test
1844 * @dataProvider sanitizeLocalUrlInvalidDataProvider
1845 */
1846 public function sanitizeLocalUrlDeniesPlainInvalidUrls($url) {
1847 $this->assertEquals('', Utility\GeneralUtility::sanitizeLocalUrl($url));
1848 }
1849
1850 /**
1851 * @test
1852 * @dataProvider sanitizeLocalUrlInvalidDataProvider
1853 */
1854 public function sanitizeLocalUrlDeniesEncodedInvalidUrls($url) {
1855 $this->assertEquals('', Utility\GeneralUtility::sanitizeLocalUrl(rawurlencode($url)));
1856 }
1857
1858 ////////////////////////////////////////
1859 // Tests concerning unlink_tempfile
1860 ////////////////////////////////////////
1861
1862 /**
1863 * @test
1864 */
1865 public function unlink_tempfileRemovesValidFileInTypo3temp() {
1866 $fixtureFile = __DIR__ . '/Fixtures/clear.gif';
1867 $testFilename = PATH_site . 'typo3temp/' . uniqid('test_') . '.gif';
1868 @copy($fixtureFile, $testFilename);
1869 Utility\GeneralUtility::unlink_tempfile($testFilename);
1870 $fileExists = file_exists($testFilename);
1871 @unlink($testFilename);
1872 $this->assertFalse($fileExists);
1873 }
1874
1875 /**
1876 * @test
1877 */
1878 public function unlink_tempfileRemovesHiddenFile() {
1879 $fixtureFile = __DIR__ . '/Fixtures/clear.gif';
1880 $testFilename = PATH_site . 'typo3temp/' . uniqid('.test_') . '.gif';
1881 @copy($fixtureFile, $testFilename);
1882 Utility\GeneralUtility::unlink_tempfile($testFilename);
1883 $fileExists = file_exists($testFilename);
1884 @unlink($testFilename);
1885 $this->assertFalse($fileExists);
1886 }
1887
1888 /**
1889 * @test
1890 */
1891 public function unlink_tempfileReturnsTrueIfFileWasRemoved() {
1892 $fixtureFile = __DIR__ . '/Fixtures/clear.gif';
1893 $testFilename = PATH_site . 'typo3temp/' . uniqid('test_') . '.gif';
1894 @copy($fixtureFile, $testFilename);
1895 $returnValue = Utility\GeneralUtility::unlink_tempfile($testFilename);
1896 @unlink($testFilename);
1897 $this->assertTrue($returnValue);
1898 }
1899
1900 /**
1901 * @test
1902 */
1903 public function unlink_tempfileReturnsNullIfFileDoesNotExist() {
1904 $returnValue = Utility\GeneralUtility::unlink_tempfile(PATH_site . 'typo3temp/' . uniqid('i_do_not_exist'));
1905 $this->assertNull($returnValue);
1906 }
1907
1908 /**
1909 * @test
1910 */
1911 public function unlink_tempfileReturnsNullIfFileIsNowWithinTypo3temp() {
1912 $returnValue = Utility\GeneralUtility::unlink_tempfile('/tmp/typo3-unit-test-unlink_tempfile');
1913 $this->assertNull($returnValue);
1914 }
1915
1916 //////////////////////////////////////
1917 // Tests concerning addSlashesOnArray
1918 //////////////////////////////////////
1919 /**
1920 * @test
1921 */
1922 public function addSlashesOnArrayAddsSlashesRecursive() {
1923 $inputArray = array(
1924 'key1' => array(
1925 'key11' => 'val\'ue1',
1926 'key12' => 'val"ue2'
1927 ),
1928 'key2' => 'val\\ue3'
1929 );
1930 $expectedResult = array(
1931 'key1' => array(
1932 'key11' => 'val\\\'ue1',
1933 'key12' => 'val\\"ue2'
1934 ),
1935 'key2' => 'val\\\\ue3'
1936 );
1937 Utility\GeneralUtility::addSlashesOnArray($inputArray);
1938 $this->assertEquals($expectedResult, $inputArray);
1939 }
1940
1941 //////////////////////////////////////
1942 // Tests concerning addSlashesOnArray
1943 //////////////////////////////////////
1944 /**
1945 * @test
1946 */
1947 public function stripSlashesOnArrayStripsSlashesRecursive() {
1948 $inputArray = array(
1949 'key1' => array(
1950 'key11' => 'val\\\'ue1',
1951 'key12' => 'val\\"ue2'
1952 ),
1953 'key2' => 'val\\\\ue3'
1954 );
1955 $expectedResult = array(
1956 'key1' => array(
1957 'key11' => 'val\'ue1',
1958 'key12' => 'val"ue2'
1959 ),
1960 'key2' => 'val\\ue3'
1961 );
1962 Utility\GeneralUtility::stripSlashesOnArray($inputArray);
1963 $this->assertEquals($expectedResult, $inputArray);
1964 }
1965
1966 //////////////////////////////////////
1967 // Tests concerning arrayDiffAssocRecursive
1968 //////////////////////////////////////
1969 /**
1970 * @test
1971 */
1972 public function arrayDiffAssocRecursiveHandlesOneDimensionalArrays() {
1973 $array1 = array(
1974 'key1' => 'value1',
1975 'key2' => 'value2',
1976 'key3' => 'value3'
1977 );
1978 $array2 = array(
1979 'key1' => 'value1',
1980 'key3' => 'value3'
1981 );
1982 $expectedResult = array(
1983 'key2' => 'value2'
1984 );
1985 $actualResult = Utility\GeneralUtility::arrayDiffAssocRecursive($array1, $array2);
1986 $this->assertEquals($expectedResult, $actualResult);
1987 }
1988
1989 /**
1990 * @test
1991 */
1992 public function arrayDiffAssocRecursiveHandlesMultiDimensionalArrays() {
1993 $array1 = array(
1994 'key1' => 'value1',
1995 'key2' => array(
1996 'key21' => 'value21',
1997 'key22' => 'value22',
1998 'key23' => array(
1999 'key231' => 'value231',
2000 'key232' => 'value232'
2001 )
2002 )
2003 );
2004 $array2 = array(
2005 'key1' => 'value1',
2006 'key2' => array(
2007 'key21' => 'value21',
2008 'key23' => array(
2009 'key231' => 'value231'
2010 )
2011 )
2012 );
2013 $expectedResult = array(
2014 'key2' => array(
2015 'key22' => 'value22',
2016 'key23' => array(
2017 'key232' => 'value232'
2018 )
2019 )
2020 );
2021 $actualResult = Utility\GeneralUtility::arrayDiffAssocRecursive($array1, $array2);
2022 $this->assertEquals($expectedResult, $actualResult);
2023 }
2024
2025 /**
2026 * @test
2027 */
2028 public function arrayDiffAssocRecursiveHandlesMixedArrays() {
2029 $array1 = array(
2030 'key1' => array(
2031 'key11' => 'value11',
2032 'key12' => 'value12'
2033 ),
2034 'key2' => 'value2',
2035 'key3' => 'value3'
2036 );
2037 $array2 = array(
2038 'key1' => 'value1',
2039 'key2' => array(
2040 'key21' => 'value21'
2041 )
2042 );
2043 $expectedResult = array(
2044 'key3' => 'value3'
2045 );
2046 $actualResult = Utility\GeneralUtility::arrayDiffAssocRecursive($array1, $array2);
2047 $this->assertEquals($expectedResult, $actualResult);
2048 }
2049
2050 //////////////////////////////////////
2051 // Tests concerning removeDotsFromTS
2052 //////////////////////////////////////
2053 /**
2054 * @test
2055 */
2056 public function removeDotsFromTypoScriptSucceedsWithDottedArray() {
2057 $typoScript = array(
2058 'propertyA.' => array(
2059 'keyA.' => array(
2060 'valueA' => 1
2061 ),
2062 'keyB' => 2
2063 ),
2064 'propertyB' => 3
2065 );
2066 $expectedResult = array(
2067 'propertyA' => array(
2068 'keyA' => array(
2069 'valueA' => 1
2070 ),
2071 'keyB' => 2
2072 ),
2073 'propertyB' => 3
2074 );
2075 $this->assertEquals($expectedResult, Utility\GeneralUtility::removeDotsFromTS($typoScript));
2076 }
2077
2078 /**
2079 * @test
2080 */
2081 public function removeDotsFromTypoScriptOverridesSubArray() {
2082 $typoScript = array(
2083 'propertyA.' => array(
2084 'keyA' => 'getsOverridden',
2085 'keyA.' => array(
2086 'valueA' => 1
2087 ),
2088 'keyB' => 2
2089 ),
2090 'propertyB' => 3
2091 );
2092 $expectedResult = array(
2093 'propertyA' => array(
2094 'keyA' => array(
2095 'valueA' => 1
2096 ),
2097 'keyB' => 2
2098 ),
2099 'propertyB' => 3
2100 );
2101 $this->assertEquals($expectedResult, Utility\GeneralUtility::removeDotsFromTS($typoScript));
2102 }
2103
2104 /**
2105 * @test
2106 */
2107 public function removeDotsFromTypoScriptOverridesWithScalar() {
2108 $typoScript = array(
2109 'propertyA.' => array(
2110 'keyA.' => array(
2111 'valueA' => 1
2112 ),
2113 'keyA' => 'willOverride',
2114 'keyB' => 2
2115 ),
2116 'propertyB' => 3
2117 );
2118 $expectedResult = array(
2119 'propertyA' => array(
2120 'keyA' => 'willOverride',
2121 'keyB' => 2
2122 ),
2123 'propertyB' => 3
2124 );
2125 $this->assertEquals($expectedResult, Utility\GeneralUtility::removeDotsFromTS($typoScript));
2126 }
2127
2128 //////////////////////////////////////
2129 // Tests concerning naturalKeySortRecursive
2130 //////////////////////////////////////
2131 /**
2132 * @test
2133 */
2134 public function naturalKeySortRecursiveReturnsFalseIfInputIsNotAnArray() {
2135 $testValues = array(
2136 1,
2137 'string',
2138 FALSE
2139 );
2140 foreach ($testValues as $testValue) {
2141 $this->assertFalse(Utility\GeneralUtility::naturalKeySortRecursive($testValue));
2142 }
2143 }
2144
2145 /**
2146 * @test
2147 */
2148 public function naturalKeySortRecursiveSortsOneDimensionalArrayByNaturalOrder() {
2149 $testArray = array(
2150 'bb' => 'bb',
2151 'ab' => 'ab',
2152 '123' => '123',
2153 'aaa' => 'aaa',
2154 'abc' => 'abc',
2155 '23' => '23',
2156 'ba' => 'ba',
2157 'bad' => 'bad',
2158 '2' => '2',
2159 'zap' => 'zap',
2160 '210' => '210'
2161 );
2162 $expectedResult = array(
2163 '2',
2164 '23',
2165 '123',
2166 '210',
2167 'aaa',
2168 'ab',
2169 'abc',
2170 'ba',
2171 'bad',
2172 'bb',
2173 'zap'
2174 );
2175 Utility\GeneralUtility::naturalKeySortRecursive($testArray);
2176 $this->assertEquals($expectedResult, array_values($testArray));
2177 }
2178
2179 /**
2180 * @test
2181 */
2182 public function naturalKeySortRecursiveSortsMultiDimensionalArrayByNaturalOrder() {
2183 $testArray = array(
2184 '2' => '2',
2185 'bb' => 'bb',
2186 'ab' => 'ab',
2187 '23' => '23',
2188 'aaa' => array(
2189 'bb' => 'bb',
2190 'ab' => 'ab',
2191 '123' => '123',
2192 'aaa' => 'aaa',
2193 '2' => '2',
2194 'abc' => 'abc',
2195 'ba' => 'ba',
2196 '23' => '23',
2197 'bad' => array(
2198 'bb' => 'bb',
2199 'ab' => 'ab',
2200 '123' => '123',
2201 'aaa' => 'aaa',
2202 'abc' => 'abc',
2203 '23' => '23',
2204 'ba' => 'ba',
2205 'bad' => 'bad',
2206 '2' => '2',
2207 'zap' => 'zap',
2208 '210' => '210'
2209 ),
2210 '210' => '210',
2211 'zap' => 'zap'
2212 ),
2213 'abc' => 'abc',
2214 'ba' => 'ba',
2215 '210' => '210',
2216 'bad' => 'bad',
2217 '123' => '123',
2218 'zap' => 'zap'
2219 );
2220 $expectedResult = array(
2221 '2',
2222 '23',
2223 '123',
2224 '210',
2225 'aaa',
2226 'ab',
2227 'abc',
2228 'ba',
2229 'bad',
2230 'bb',
2231 'zap'
2232 );
2233 Utility\GeneralUtility::naturalKeySortRecursive($testArray);
2234 $this->assertEquals($expectedResult, array_values(array_keys($testArray['aaa']['bad'])));
2235 $this->assertEquals($expectedResult, array_values(array_keys($testArray['aaa'])));
2236 $this->assertEquals($expectedResult, array_values(array_keys($testArray)));
2237 }
2238
2239 //////////////////////////////////////
2240 // Tests concerning get_dirs
2241 //////////////////////////////////////
2242 /**
2243 * @test
2244 */
2245 public function getDirsReturnsArrayOfDirectoriesFromGivenDirectory() {
2246 $path = PATH_t3lib;
2247 $directories = Utility\GeneralUtility::get_dirs($path);
2248 $this->assertInternalType(\PHPUnit_Framework_Constraint_IsType::TYPE_ARRAY, $directories);
2249 }
2250
2251 /**
2252 * @test
2253 */
2254 public function getDirsReturnsStringErrorOnPathFailure() {
2255 $path = 'foo';
2256 $result = Utility\GeneralUtility::get_dirs($path);
2257 $expectedResult = 'error';
2258 $this->assertEquals($expectedResult, $result);
2259 }
2260
2261 //////////////////////////////////
2262 // Tests concerning hmac
2263 //////////////////////////////////
2264 /**
2265 * @test
2266 */
2267 public function hmacReturnsHashOfProperLength() {
2268 $hmac = Utility\GeneralUtility::hmac('message');
2269 $this->assertTrue(!empty($hmac) && is_string($hmac));
2270 $this->assertTrue(strlen($hmac) == 40);
2271 }
2272
2273 /**
2274 * @test
2275 */
2276 public function hmacReturnsEqualHashesForEqualInput() {
2277 $msg0 = 'message';
2278 $msg1 = 'message';
2279 $this->assertEquals(Utility\GeneralUtility::hmac($msg0), Utility\GeneralUtility::hmac($msg1));
2280 }
2281
2282 /**
2283 * @test
2284 */
2285 public function hmacReturnsNoEqualHashesForNonEqualInput() {
2286 $msg0 = 'message0';
2287 $msg1 = 'message1';
2288 $this->assertNotEquals(Utility\GeneralUtility::hmac($msg0), Utility\GeneralUtility::hmac($msg1));
2289 }
2290
2291 //////////////////////////////////
2292 // Tests concerning quoteJSvalue
2293 //////////////////////////////////
2294 /**
2295 * Data provider for quoteJSvalueTest.
2296 *
2297 * @return array
2298 */
2299 public function quoteJsValueDataProvider() {
2300 return array(
2301 'Immune characters are returned as is' => array(
2302 '._,',
2303 '._,'
2304 ),
2305 'Alphanumerical characters are returned as is' => array(
2306 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
2307 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
2308 ),
2309 'Angel brackets and ampersand are encoded' => array(
2310 '<>&',
2311 '\\x3C\\x3E\\x26'
2312 ),
2313 'Quotes and slashes are encoded' => array(
2314 '"\'\\/',
2315 '\\x22\\x27\\x5C\\x2F'
2316 ),
2317 'Empty string stays empty' => array(
2318 '',
2319 ''
2320 ),
2321 'Exclamation mark and space are properly encoded' => array(
2322 'Hello World!',
2323 'Hello\\x20World\\x21'
2324 ),
2325 'Whitespaces are properly encoded' => array(
2326 TAB . LF . CR . ' ',
2327 '\\x09\\x0A\\x0D\\x20'
2328 ),
2329 'Null byte is properly encoded' => array(
2330 chr(0),
2331 '\\x00'
2332 ),
2333 'Umlauts are properly encoded' => array(
2334 'ÜüÖöÄä',
2335 '\\xDC\\xFC\\xD6\\xF6\\xC4\\xE4'
2336 )
2337 );
2338 }
2339
2340 /**
2341 * @test
2342 * @param string $input
2343 * @param string $expected
2344 * @dataProvider quoteJsValueDataProvider
2345 */
2346 public function quoteJsValueTest($input, $expected) {
2347 $this->assertSame('\'' . $expected . '\'', Utility\GeneralUtility::quoteJSvalue($input));
2348 }
2349
2350 //////////////////////////////////
2351 // Tests concerning readLLfile
2352 //////////////////////////////////
2353 /**
2354 * @test
2355 */
2356 public function readLLfileHandlesLocallangXMLOverride() {
2357 $unique = uniqid('locallangXMLOverrideTest');
2358 $xml = '<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
2359 <T3locallang>
2360 <data type="array">
2361 <languageKey index="default" type="array">
2362 <label index="buttons.logout">EXIT</label>
2363 </languageKey>
2364 </data>
2365 </T3locallang>';
2366 $file = PATH_site . 'typo3temp/' . $unique . '.xml';
2367 Utility\GeneralUtility::writeFileToTypo3tempDir($file, $xml);
2368 // Make sure there is no cached version of the label
2369 $GLOBALS['typo3CacheManager']->getCache('t3lib_l10n')->flush();
2370 // Get default value
2371 $defaultLL = Utility\GeneralUtility::readLLfile('EXT:lang/locallang_core.xml', 'default');
2372 // Clear language cache again
2373 $GLOBALS['typo3CacheManager']->getCache('t3lib_l10n')->flush();
2374 // Set override file
2375 $GLOBALS['TYPO3_CONF_VARS']['SYS']['locallangXMLOverride']['EXT:lang/locallang_core.xml'][$unique] = $file;
2376 /** @var $store \TYPO3\CMS\Core\Localization\LanguageStore */
2377 $store = Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\LanguageStore');
2378 $store->flushData('EXT:lang/locallang_core.xml');
2379 // Get override value
2380 $overrideLL = Utility\GeneralUtility::readLLfile('EXT:lang/locallang_core.xml', 'default');
2381 // Clean up again
2382 unlink($file);
2383 $this->assertNotEquals($overrideLL['default']['buttons.logout'][0]['target'], '');
2384 $this->assertNotEquals($defaultLL['default']['buttons.logout'][0]['target'], $overrideLL['default']['buttons.logout'][0]['target']);
2385 $this->assertEquals($overrideLL['default']['buttons.logout'][0]['target'], 'EXIT');
2386 }
2387
2388 ///////////////////////////////
2389 // Tests concerning _GETset()
2390 ///////////////////////////////
2391 /**
2392 * @test
2393 */
2394 public function getSetWritesArrayToGetSystemVariable() {
2395 $_GET = array();
2396 $GLOBALS['HTTP_GET_VARS'] = array();
2397 $getParameters = array('foo' => 'bar');
2398 Utility\GeneralUtility::_GETset($getParameters);
2399 $this->assertSame($getParameters, $_GET);
2400 }
2401
2402 /**
2403 * @test
2404 */
2405 public function getSetWritesArrayToGlobalsHttpGetVars() {
2406 $_GET = array();
2407 $GLOBALS['HTTP_GET_VARS'] = array();
2408 $getParameters = array('foo' => 'bar');
2409 Utility\GeneralUtility::_GETset($getParameters);
2410 $this->assertSame($getParameters, $GLOBALS['HTTP_GET_VARS']);
2411 }
2412
2413 /**
2414 * @test
2415 */
2416 public function getSetForArrayDropsExistingValues() {
2417 $_GET = array();
2418 $GLOBALS['HTTP_GET_VARS'] = array();
2419 Utility\GeneralUtility::_GETset(array('foo' => 'bar'));
2420 Utility\GeneralUtility::_GETset(array('oneKey' => 'oneValue'));
2421 $this->assertEquals(array('oneKey' => 'oneValue'), $GLOBALS['HTTP_GET_VARS']);
2422 }
2423
2424 /**
2425 * @test
2426 */
2427 public function getSetAssignsOneValueToOneKey() {
2428 $_GET = array();
2429 $GLOBALS['HTTP_GET_VARS'] = array();
2430 Utility\GeneralUtility::_GETset('oneValue', 'oneKey');
2431 $this->assertEquals('oneValue', $GLOBALS['HTTP_GET_VARS']['oneKey']);
2432 }
2433
2434 /**
2435 * @test
2436 */
2437 public function getSetForOneValueDoesNotDropUnrelatedValues() {
2438 $_GET = array();
2439 $GLOBALS['HTTP_GET_VARS'] = array();
2440 Utility\GeneralUtility::_GETset(array('foo' => 'bar'));
2441 Utility\GeneralUtility::_GETset('oneValue', 'oneKey');
2442 $this->assertEquals(array('foo' => 'bar', 'oneKey' => 'oneValue'), $GLOBALS['HTTP_GET_VARS']);
2443 }
2444
2445 /**
2446 * @test
2447 */
2448 public function getSetCanAssignsAnArrayToASpecificArrayElement() {
2449 $_GET = array();
2450 $GLOBALS['HTTP_GET_VARS'] = array();
2451 Utility\GeneralUtility::_GETset(array('childKey' => 'oneValue'), 'parentKey');
2452 $this->assertEquals(array('parentKey' => array('childKey' => 'oneValue')), $GLOBALS['HTTP_GET_VARS']);
2453 }
2454
2455 /**
2456 * @test
2457 */
2458 public function getSetCanAssignAStringValueToASpecificArrayChildElement() {
2459 $_GET = array();
2460 $GLOBALS['HTTP_GET_VARS'] = array();
2461 Utility\GeneralUtility::_GETset('oneValue', 'parentKey|childKey');
2462 $this->assertEquals(array('parentKey' => array('childKey' => 'oneValue')), $GLOBALS['HTTP_GET_VARS']);
2463 }
2464
2465 /**
2466 * @test
2467 */
2468 public function getSetCanAssignAnArrayToASpecificArrayChildElement() {
2469 $_GET = array();
2470 $GLOBALS['HTTP_GET_VARS'] = array();
2471 Utility\GeneralUtility::_GETset(array('key1' => 'value1', 'key2' => 'value2'), 'parentKey|childKey');
2472 $this->assertEquals(array(
2473 'parentKey' => array(
2474 'childKey' => array('key1' => 'value1', 'key2' => 'value2')
2475 )
2476 ), $GLOBALS['HTTP_GET_VARS']);
2477 }
2478
2479 ///////////////////////////
2480 // Tests concerning minifyJavaScript
2481 ///////////////////////////
2482 /**
2483 * @test
2484 */
2485 public function minifyJavaScriptReturnsInputStringIfNoHookIsRegistered() {
2486 unset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript']);
2487 $testString = uniqid('string');
2488 $this->assertSame($testString, Utility\GeneralUtility::minifyJavaScript($testString));
2489 }
2490
2491 /**
2492 * Create an own hook callback class, register as hook, and check
2493 * if given string to compress is given to hook method
2494 *
2495 * @test
2496 */
2497 public function minifyJavaScriptCallsRegisteredHookWithInputString() {
2498 $hookClassName = uniqid('tx_coretest');
2499 $minifyHookMock = $this->getMock('stdClass', array('minify'), array(), $hookClassName);
2500 $functionName = '&' . $hookClassName . '->minify';
2501 $GLOBALS['T3_VAR']['callUserFunction'][$functionName] = array();
2502 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['obj'] = $minifyHookMock;
2503 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['method'] = 'minify';
2504 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'][] = $functionName;
2505 $minifyHookMock->expects($this->once())->method('minify')->will($this->returnCallback(array($this, 'isMinifyJavaScriptHookCalledCallback')));
2506 Utility\GeneralUtility::minifyJavaScript('foo');
2507 }
2508
2509 /**
2510 * Callback function used in minifyJavaScriptCallsRegisteredHookWithInputString test
2511 *
2512 * @param array $params
2513 */
2514 public function isMinifyJavaScriptHookCalledCallback(array $params) {
2515 // We can not throw an exception here, because that would be caught by the
2516 // minifyJavaScript method under test itself. Thus, we just die if the
2517 // input string is not ok.
2518 if ($params['script'] !== 'foo') {
2519 die('broken');
2520 }
2521 }
2522
2523 /**
2524 * Create a hook callback, use callback to throw an exception and check
2525 * if the exception is given as error parameter to the calling method.
2526 *
2527 * @test
2528 */
2529 public function minifyJavaScriptReturnsErrorStringOfHookException() {
2530 $hookClassName = uniqid('tx_coretest');
2531 $minifyHookMock = $this->getMock('stdClass', array('minify'), array(), $hookClassName);
2532 $functionName = '&' . $hookClassName . '->minify';
2533 $GLOBALS['T3_VAR']['callUserFunction'][$functionName] = array();
2534 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['obj'] = $minifyHookMock;
2535 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['method'] = 'minify';
2536 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'][] = $functionName;
2537 $minifyHookMock->expects($this->any())->method('minify')->will($this->returnCallback(array($this, 'minifyJavaScriptErroneousCallback')));
2538 $error = '';
2539 Utility\GeneralUtility::minifyJavaScript('string to compress', $error);
2540 $this->assertSame('Error minifying java script: foo', $error);
2541 }
2542
2543 /**
2544 * Check if the error message that is returned by the hook callback
2545 * is logged to \TYPO3\CMS\Core\Utility\GeneralUtility::devLog.
2546 *
2547 * @test
2548 */
2549 public function minifyJavaScriptWritesExceptionMessageToDevLog() {
2550 $namespace = 'TYPO3\\CMS\\Core\\Utility';
2551 $t3libDivMock = uniqid('GeneralUtility');
2552 eval('namespace ' . $namespace . '; class ' . $t3libDivMock . ' extends \\TYPO3\\CMS\\Core\\Utility\\GeneralUtility {' . ' public static function devLog($errorMessage) {' . ' if (!($errorMessage === \'Error minifying java script: foo\')) {' . ' throw new \\UnexpectedValue(\'broken\');' . ' }' . ' throw new \\RuntimeException();' . ' }' . '}');
2553 $t3libDivMock = $namespace . '\\' . $t3libDivMock;
2554 $hookClassName = uniqid('tx_coretest');
2555 $minifyHookMock = $this->getMock('stdClass', array('minify'), array(), $hookClassName);
2556 $functionName = '&' . $hookClassName . '->minify';
2557 $GLOBALS['T3_VAR']['callUserFunction'][$functionName] = array();
2558 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['obj'] = $minifyHookMock;
2559 $GLOBALS['T3_VAR']['callUserFunction'][$functionName]['method'] = 'minify';
2560 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_div.php']['minifyJavaScript'][] = $functionName;
2561 $minifyHookMock->expects($this->any())->method('minify')->will($this->returnCallback(array($this, 'minifyJavaScriptErroneousCallback')));
2562 $this->setExpectedException('\\RuntimeException');
2563 $t3libDivMock::minifyJavaScript('string to compress');
2564 }
2565
2566 /**
2567 * Callback function used in
2568 * minifyJavaScriptReturnsErrorStringOfHookException and
2569 * minifyJavaScriptWritesExceptionMessageToDevLog
2570 *
2571 * @throws \RuntimeException
2572 */
2573 public function minifyJavaScriptErroneousCallback() {
2574 throw new \RuntimeException('foo', 1344888548);
2575 }
2576
2577 ///////////////////////////
2578 // Tests concerning getUrl
2579 ///////////////////////////
2580 /**
2581 * @test
2582 */
2583 public function getUrlWithAdditionalRequestHeadersProvidesHttpHeaderOnError() {
2584 $url = 'http://typo3.org/i-do-not-exist-' . time();
2585 $report = array();
2586 Utility\GeneralUtility::getUrl($url, 0, array(), $report);
2587 $this->assertContains('404', $report['message']);
2588 }
2589
2590 /**
2591 * @test
2592 */
2593 public function getUrlProvidesWithoutAdditionalRequestHeadersHttpHeaderOnError() {
2594 $url = 'http://typo3.org/i-do-not-exist-' . time();
2595 $report = array();
2596 Utility\GeneralUtility::getUrl($url, 0, FALSE, $report);
2597 $this->assertContains('404', $report['message'], 'Did not provide the HTTP response header when requesting a failing URL.');
2598 }
2599
2600 ///////////////////////////////
2601 // Tests concerning fixPermissions
2602 ///////////////////////////////
2603 /**
2604 * @test
2605 */
2606 public function fixPermissionsSetsGroup() {
2607 if (TYPO3_OS == 'WIN') {
2608 $this->markTestSkipped('fixPermissionsSetsGroup() tests not available on Windows');
2609 }
2610 if (!function_exists('posix_getegid')) {
2611 $this->markTestSkipped('Function posix_getegid() not available, fixPermissionsSetsGroup() tests skipped');
2612 }
2613 if (posix_getegid() === -1) {
2614 $this->markTestSkipped('The fixPermissionsSetsGroup() is not available on Mac OS because posix_getegid() always returns -1 on Mac OS.');
2615 }
2616 // Create and prepare test file
2617 $filename = PATH_site . 'typo3temp/' . uniqid('test_');
2618 Utility\GeneralUtility::writeFileToTypo3tempDir($filename, '42');
2619 $this->testFilesToDelete[] = $filename;
2620 $currentGroupId = posix_getegid();
2621 // Set target group and run method
2622 $GLOBALS['TYPO3_CONF_VARS']['BE']['createGroup'] = $currentGroupId;
2623 Utility\GeneralUtility::fixPermissions($filename);
2624 clearstatcache();
2625 $this->assertEquals($currentGroupId, filegroup($filename));
2626 }
2627
2628 /**
2629 * @test
2630 */
2631 public function fixPermissionsSetsPermissionsToFile() {
2632 if (TYPO3_OS == 'WIN') {
2633 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2634 }
2635 // Create and prepare test file
2636 $filename = PATH_site . 'typo3temp/' . uniqid('test_');
2637 Utility\GeneralUtility::writeFileToTypo3tempDir($filename, '42');
2638 $this->testFilesToDelete[] = $filename;
2639 chmod($filename, 482);
2640 // Set target permissions and run method
2641 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2642 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
2643 clearstatcache();
2644 $this->assertTrue($fixPermissionsResult);
2645 $this->assertEquals('0660', substr(decoct(fileperms($filename)), 2));
2646 }
2647
2648 /**
2649 * @test
2650 */
2651 public function fixPermissionsSetsPermissionsToHiddenFile() {
2652 if (TYPO3_OS == 'WIN') {
2653 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2654 }
2655 // Create and prepare test file
2656 $filename = PATH_site . 'typo3temp/' . uniqid('.test_');
2657 Utility\GeneralUtility::writeFileToTypo3tempDir($filename, '42');
2658 $this->testFilesToDelete[] = $filename;
2659 chmod($filename, 482);
2660 // Set target permissions and run method
2661 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2662 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
2663 clearstatcache();
2664 $this->assertTrue($fixPermissionsResult);
2665 $this->assertEquals('0660', substr(decoct(fileperms($filename)), 2));
2666 }
2667
2668 /**
2669 * @test
2670 */
2671 public function fixPermissionsSetsPermissionsToDirectory() {
2672 if (TYPO3_OS == 'WIN') {
2673 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2674 }
2675 // Create and prepare test directory
2676 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2677 Utility\GeneralUtility::mkdir($directory);
2678 chmod($directory, 1551);
2679 // Set target permissions and run method
2680 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2681 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($directory);
2682 // Get actual permissions and clean up
2683 clearstatcache();
2684 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2685 Utility\GeneralUtility::rmdir($directory);
2686 // Test if everything was ok
2687 $this->assertTrue($fixPermissionsResult);
2688 $this->assertEquals('0770', $resultDirectoryPermissions);
2689 }
2690
2691 /**
2692 * @test
2693 */
2694 public function fixPermissionsSetsPermissionsToDirectoryWithTrailingSlash() {
2695 if (TYPO3_OS == 'WIN') {
2696 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2697 }
2698 // Create and prepare test directory
2699 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2700 Utility\GeneralUtility::mkdir($directory);
2701 chmod($directory, 1551);
2702 // Set target permissions and run method
2703 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2704 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($directory . '/');
2705 // Get actual permissions and clean up
2706 clearstatcache();
2707 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2708 Utility\GeneralUtility::rmdir($directory);
2709 // Test if everything was ok
2710 $this->assertTrue($fixPermissionsResult);
2711 $this->assertEquals('0770', $resultDirectoryPermissions);
2712 }
2713
2714 /**
2715 * @test
2716 */
2717 public function fixPermissionsSetsPermissionsToHiddenDirectory() {
2718 if (TYPO3_OS == 'WIN') {
2719 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2720 }
2721 // Create and prepare test directory
2722 $directory = PATH_site . 'typo3temp/' . uniqid('.test_');
2723 Utility\GeneralUtility::mkdir($directory);
2724 chmod($directory, 1551);
2725 // Set target permissions and run method
2726 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2727 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($directory);
2728 // Get actual permissions and clean up
2729 clearstatcache();
2730 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2731 Utility\GeneralUtility::rmdir($directory);
2732 // Test if everything was ok
2733 $this->assertTrue($fixPermissionsResult);
2734 $this->assertEquals('0770', $resultDirectoryPermissions);
2735 }
2736
2737 /**
2738 * @test
2739 */
2740 public function fixPermissionsCorrectlySetsPermissionsRecursive() {
2741 if (TYPO3_OS == 'WIN') {
2742 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2743 }
2744 // Create and prepare test directory and file structure
2745 $baseDirectory = PATH_site . 'typo3temp/' . uniqid('test_');
2746 Utility\GeneralUtility::mkdir($baseDirectory);
2747 chmod($baseDirectory, 1751);
2748 Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/file', '42');
2749 chmod($baseDirectory . '/file', 482);
2750 Utility\GeneralUtility::mkdir($baseDirectory . '/foo');
2751 chmod($baseDirectory . '/foo', 1751);
2752 Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/foo/file', '42');
2753 chmod($baseDirectory . '/foo/file', 482);
2754 Utility\GeneralUtility::mkdir($baseDirectory . '/.bar');
2755 chmod($baseDirectory . '/.bar', 1751);
2756 // Use this if writeFileToTypo3tempDir is fixed to create hidden files in subdirectories
2757 // \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/.bar/.file', '42');
2758 // \TYPO3\CMS\Core\Utility\GeneralUtility::writeFileToTypo3tempDir($baseDirectory . '/.bar/..file2', '42');
2759 touch($baseDirectory . '/.bar/.file', '42');
2760 chmod($baseDirectory . '/.bar/.file', 482);
2761 touch($baseDirectory . '/.bar/..file2', '42');
2762 chmod($baseDirectory . '/.bar/..file2', 482);
2763 // Set target permissions and run method
2764 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2765 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0770';
2766 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($baseDirectory, TRUE);
2767 // Get actual permissions
2768 clearstatcache();
2769 $resultBaseDirectoryPermissions = substr(decoct(fileperms($baseDirectory)), 1);
2770 $resultBaseFilePermissions = substr(decoct(fileperms($baseDirectory . '/file')), 2);
2771 $resultFooDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/foo')), 1);
2772 $resultFooFilePermissions = substr(decoct(fileperms($baseDirectory . '/foo/file')), 2);
2773 $resultBarDirectoryPermissions = substr(decoct(fileperms($baseDirectory . '/.bar')), 1);
2774 $resultBarFilePermissions = substr(decoct(fileperms($baseDirectory . '/.bar/.file')), 2);
2775 $resultBarFile2Permissions = substr(decoct(fileperms($baseDirectory . '/.bar/..file2')), 2);
2776 // Clean up
2777 unlink($baseDirectory . '/file');
2778 unlink($baseDirectory . '/foo/file');
2779 unlink($baseDirectory . '/.bar/.file');
2780 unlink($baseDirectory . '/.bar/..file2');
2781 Utility\GeneralUtility::rmdir($baseDirectory . '/foo');
2782 Utility\GeneralUtility::rmdir($baseDirectory . '/.bar');
2783 Utility\GeneralUtility::rmdir($baseDirectory);
2784 // Test if everything was ok
2785 $this->assertTrue($fixPermissionsResult);
2786 $this->assertEquals('0770', $resultBaseDirectoryPermissions);
2787 $this->assertEquals('0660', $resultBaseFilePermissions);
2788 $this->assertEquals('0770', $resultFooDirectoryPermissions);
2789 $this->assertEquals('0660', $resultFooFilePermissions);
2790 $this->assertEquals('0770', $resultBarDirectoryPermissions);
2791 $this->assertEquals('0660', $resultBarFilePermissions);
2792 $this->assertEquals('0660', $resultBarFile2Permissions);
2793 }
2794
2795 /**
2796 * @test
2797 */
2798 public function fixPermissionsDoesNotSetPermissionsToNotAllowedPath() {
2799 if (TYPO3_OS == 'WIN') {
2800 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2801 }
2802 // Create and prepare test file
2803 $filename = PATH_site . 'typo3temp/../typo3temp/' . uniqid('test_');
2804 touch($filename);
2805 chmod($filename, 482);
2806 // Set target permissions and run method
2807 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2808 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
2809 // Get actual permissions and clean up
2810 clearstatcache();
2811 $resultFilePermissions = substr(decoct(fileperms($filename)), 2);
2812 unlink($filename);
2813 // Test if everything was ok
2814 $this->assertFalse($fixPermissionsResult);
2815 }
2816
2817 /**
2818 * @test
2819 */
2820 public function fixPermissionsSetsPermissionsWithRelativeFileReference() {
2821 if (TYPO3_OS == 'WIN') {
2822 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2823 }
2824 $filename = 'typo3temp/' . uniqid('test_');
2825 Utility\GeneralUtility::writeFileToTypo3tempDir(PATH_site . $filename, '42');
2826 chmod(PATH_site . $filename, 482);
2827 // Set target permissions and run method
2828 $GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask'] = '0660';
2829 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
2830 // Get actual permissions and clean up
2831 clearstatcache();
2832 $resultFilePermissions = substr(decoct(fileperms(PATH_site . $filename)), 2);
2833 unlink(PATH_site . $filename);
2834 // Test if everything was ok
2835 $this->assertTrue($fixPermissionsResult);
2836 $this->assertEquals('0660', $resultFilePermissions);
2837 }
2838
2839 /**
2840 * @test
2841 */
2842 public function fixPermissionsSetsDefaultPermissionsToFile() {
2843 if (TYPO3_OS == 'WIN') {
2844 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2845 }
2846 $filename = PATH_site . 'typo3temp/' . uniqid('test_');
2847 Utility\GeneralUtility::writeFileToTypo3tempDir($filename, '42');
2848 $this->testFilesToDelete[] = $filename;
2849 chmod($filename, 482);
2850 unset($GLOBALS['TYPO3_CONF_VARS']['BE']['fileCreateMask']);
2851 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($filename);
2852 clearstatcache();
2853 $this->assertTrue($fixPermissionsResult);
2854 $this->assertEquals('0644', substr(decoct(fileperms($filename)), 2));
2855 }
2856
2857 /**
2858 * @test
2859 */
2860 public function fixPermissionsSetsDefaultPermissionsToDirectory() {
2861 if (TYPO3_OS == 'WIN') {
2862 $this->markTestSkipped('fixPermissions() tests not available on Windows');
2863 }
2864 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2865 Utility\GeneralUtility::mkdir($directory);
2866 chmod($directory, 1551);
2867 unset($GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask']);
2868 $fixPermissionsResult = Utility\GeneralUtility::fixPermissions($directory);
2869 clearstatcache();
2870 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2871 Utility\GeneralUtility::rmdir($directory);
2872 $this->assertTrue($fixPermissionsResult);
2873 $this->assertEquals('0755', $resultDirectoryPermissions);
2874 }
2875
2876 ///////////////////////////////
2877 // Tests concerning mkdir
2878 ///////////////////////////////
2879 /**
2880 * @test
2881 */
2882 public function mkdirCreatesDirectory() {
2883 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2884 $mkdirResult = Utility\GeneralUtility::mkdir($directory);
2885 clearstatcache();
2886 $directoryCreated = is_dir($directory);
2887 @rmdir($directory);
2888 $this->assertTrue($mkdirResult);
2889 $this->assertTrue($directoryCreated);
2890 }
2891
2892 /**
2893 * @test
2894 */
2895 public function mkdirCreatesHiddenDirectory() {
2896 $directory = PATH_site . 'typo3temp/' . uniqid('.test_');
2897 $mkdirResult = Utility\GeneralUtility::mkdir($directory);
2898 clearstatcache();
2899 $directoryCreated = is_dir($directory);
2900 @rmdir($directory);
2901 $this->assertTrue($mkdirResult);
2902 $this->assertTrue($directoryCreated);
2903 }
2904
2905 /**
2906 * @test
2907 */
2908 public function mkdirCreatesDirectoryWithTrailingSlash() {
2909 $directory = PATH_site . 'typo3temp/' . uniqid('test_') . '/';
2910 $mkdirResult = Utility\GeneralUtility::mkdir($directory);
2911 clearstatcache();
2912 $directoryCreated = is_dir($directory);
2913 @rmdir($directory);
2914 $this->assertTrue($mkdirResult);
2915 $this->assertTrue($directoryCreated);
2916 }
2917
2918 /**
2919 * @test
2920 */
2921 public function mkdirSetsPermissionsOfCreatedDirectory() {
2922 if (TYPO3_OS == 'WIN') {
2923 $this->markTestSkipped('mkdirSetsPermissionsOfCreatedDirectory() test not available on Windows');
2924 }
2925 $directory = PATH_site . 'typo3temp/' . uniqid('test_');
2926 $oldUmask = umask(19);
2927 $GLOBALS['TYPO3_CONF_VARS']['BE']['folderCreateMask'] = '0772';
2928 Utility\GeneralUtility::mkdir($directory);
2929 clearstatcache();
2930 $resultDirectoryPermissions = substr(decoct(fileperms($directory)), 1);
2931 umask($oldUmask);
2932 rmdir($directory);
2933 $this->assertEquals($resultDirectoryPermissions, '0772');
2934 }
2935
2936 /**
2937 * @test
2938 */
2939 public function mkdirSetsGroupOwnershipOfCreatedDirectory() {
2940 if (!function_exists('posix_getegid')) {
2941 $this->markTestSkipped('Function posix_getegid() not available, mkdirSetsGroupOwnershipOfCreatedDirectory() tests skipped');
2942 }
2943 if (posix_getegid() === -1) {
2944 $this->markTestSkipped('The mkdirSetsGroupOwnershipOfCreatedDirectory() is not available on Mac OS because posix_getegid() always returns -1 on Mac OS.'