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