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