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