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