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