[BUGFIX] Reallow '0' as valid userFunc argument in TypoScript
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Tests / Unit / Configuration / TypoScript / ConditionMatching / AbstractConditionMatcherTest.php
1 <?php
2 namespace TYPO3\CMS\Core\Tests\Unit\Configuration\TypoScript\ConditionMatching;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Configuration\TypoScript\ConditionMatching\AbstractConditionMatcher;
18 use TYPO3\CMS\Core\Core\ApplicationContext;
19 use TYPO3\CMS\Core\Tests\UnitTestCase;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22 /**
23 * Test cases
24 */
25 class AbstractConditionMatcherTest extends UnitTestCase
26 {
27 /**
28 * @var \TYPO3\CMS\Core\Core\ApplicationContext
29 */
30 protected $backupApplicationContext = null;
31
32 /**
33 * @var AbstractConditionMatcher|\PHPUnit_Framework_MockObject_MockObject
34 */
35 protected $conditionMatcher;
36
37 /**
38 * @var \ReflectionMethod
39 */
40 protected $evaluateConditionCommonMethod;
41
42 /**
43 * Set up
44 */
45 protected function setUp()
46 {
47 require_once('Fixtures/ConditionMatcherUserFuncs.php');
48
49 GeneralUtility::flushInternalRuntimeCaches();
50
51 $this->backupApplicationContext = GeneralUtility::getApplicationContext();
52 $this->conditionMatcher = $this->getMockForAbstractClass(AbstractConditionMatcher::class);
53 $this->evaluateConditionCommonMethod = new \ReflectionMethod(AbstractConditionMatcher::class, 'evaluateConditionCommon');
54 $this->evaluateConditionCommonMethod->setAccessible(true);
55 }
56
57 /**
58 * Tear down
59 */
60 protected function tearDown()
61 {
62 Fixtures\GeneralUtilityFixture::setApplicationContext($this->backupApplicationContext);
63 parent::tearDown();
64 }
65
66 /**
67 * Data provider with matching applicationContext conditions.
68 *
69 * @return array[]
70 */
71 public function matchingApplicationContextConditionsDataProvider()
72 {
73 return array(
74 array('Production*'),
75 array('Production/Staging/*'),
76 array('Production/Staging/Server2'),
77 array('/^Production.*$/'),
78 array('/^Production\\/.+\\/Server\\d+$/'),
79 );
80 }
81
82 /**
83 * @test
84 * @dataProvider matchingApplicationContextConditionsDataProvider
85 */
86 public function evaluateConditionCommonReturnsTrueForMatchingContexts($matchingContextCondition)
87 {
88 /** @var \TYPO3\CMS\Core\Core\ApplicationContext $applicationContext */
89 $applicationContext = new ApplicationContext('Production/Staging/Server2');
90 Fixtures\GeneralUtilityFixture::setApplicationContext($applicationContext);
91
92 $this->assertTrue(
93 $this->evaluateConditionCommonMethod->invokeArgs($this->conditionMatcher, array('applicationContext', $matchingContextCondition))
94 );
95 }
96
97 /**
98 * Data provider with not matching applicationContext conditions.
99 *
100 * @return array[]
101 */
102 public function notMatchingApplicationContextConditionsDataProvider()
103 {
104 return array(
105 array('Production'),
106 array('Testing*'),
107 array('Development/Profiling, Testing/Unit'),
108 array('Testing/Staging/Server2'),
109 array('/^Testing.*$/'),
110 array('/^Production\\/.+\\/Host\\d+$/'),
111 );
112 }
113
114 /**
115 * @test
116 * @dataProvider notMatchingApplicationContextConditionsDataProvider
117 */
118 public function evaluateConditionCommonReturnsNullForNotMatchingApplicationContexts($notMatchingApplicationContextCondition)
119 {
120 /** @var \TYPO3\CMS\Core\Core\ApplicationContext $applicationContext */
121 $applicationContext = new ApplicationContext('Production/Staging/Server2');
122 Fixtures\GeneralUtilityFixture::setApplicationContext($applicationContext);
123
124 $this->assertFalse(
125 $this->evaluateConditionCommonMethod->invokeArgs($this->conditionMatcher, array('applicationContext', $notMatchingApplicationContextCondition))
126 );
127 }
128
129 /**
130 * Data provider for evaluateConditionCommonEvaluatesIpAddressesCorrectly
131 *
132 * @return array[]
133 */
134 public function evaluateConditionCommonDevIpMaskDataProvider()
135 {
136 return array(
137 // [0] $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask']
138 // [1] Actual IP
139 // [2] Expected condition result
140 'IP matches' => array(
141 '127.0.0.1',
142 '127.0.0.1',
143 true,
144 ),
145 'ipv4 wildcard subnet' => array(
146 '127.0.0.1/24',
147 '127.0.0.2',
148 true,
149 ),
150 'ipv6 wildcard subnet' => array(
151 '0:0::1/128',
152 '::1',
153 true,
154 ),
155 'List of addresses matches' => array(
156 '1.2.3.4, 5.6.7.8',
157 '5.6.7.8',
158 true,
159 ),
160 'IP does not match' => array(
161 '127.0.0.1',
162 '127.0.0.2',
163 false,
164 ),
165 'ipv4 subnet does not match' => array(
166 '127.0.0.1/8',
167 '126.0.0.1',
168 false,
169 ),
170 'ipv6 subnet does not match' => array(
171 '::1/127',
172 '::2',
173 false
174 ),
175 'List of addresses does not match' => array(
176 '127.0.0.1, ::1',
177 '::2',
178 false,
179 ),
180 );
181 }
182
183 /**
184 * @test
185 * @dataProvider evaluateConditionCommonDevIpMaskDataProvider
186 */
187 public function evaluateConditionCommonEvaluatesIpAddressesCorrectly($devIpMask, $actualIp, $expectedResult)
188 {
189 // Do not trigger proxy stuff of GeneralUtility::getIndPEnv
190 unset($GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP']);
191
192 $_SERVER['REMOTE_ADDR'] = $actualIp;
193 $GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'] = $devIpMask;
194
195 $actualResult = $this->evaluateConditionCommonMethod->invokeArgs($this->conditionMatcher, array('IP', 'devIP'));
196 $this->assertSame($expectedResult, $actualResult);
197 }
198
199 /**
200 * @test
201 */
202 public function testUserFuncIsCalled()
203 {
204 $this->assertTrue(
205 $this->evaluateConditionCommonMethod->invokeArgs(
206 $this->conditionMatcher,
207 array('userFunc', 'user_testFunction')
208 )
209 );
210 }
211
212 /**
213 * @test
214 */
215 public function testUserFuncWithSingleArgument()
216 {
217 $this->assertTrue(
218 $this->evaluateConditionCommonMethod->invokeArgs(
219 $this->conditionMatcher,
220 array('userFunc', 'user_testFunctionWithSingleArgument(x)')
221 )
222 );
223 }
224
225 /**
226 * @test
227 */
228 public function testUserFuncWithIntegerZeroArgument()
229 {
230 $this->assertTrue(
231 $this->evaluateConditionCommonMethod->invokeArgs(
232 $this->conditionMatcher,
233 array('userFunc', 'user_testFunctionWithSingleArgument(0)')
234 )
235 );
236 }
237
238 /**
239 * @test
240 */
241 public function testUserFuncWithWhitespaceArgument()
242 {
243 $this->assertTrue(
244 $this->evaluateConditionCommonMethod->invokeArgs(
245 $this->conditionMatcher,
246 array('userFunc', 'user_testFunctionWithNoArgument( )')
247 )
248 );
249 }
250
251 /**
252 * @test
253 */
254 public function testUserFuncWithMultipleArguments()
255 {
256 $this->assertTrue(
257 $this->evaluateConditionCommonMethod->invokeArgs(
258 $this->conditionMatcher,
259 array('userFunc', 'user_testFunctionWithThreeArguments(1,2,3)')
260 )
261 );
262 }
263
264 /**
265 * @test
266 */
267 public function testUserFuncWithMultipleDifferentArgumentsNullBoolString()
268 {
269 $this->assertTrue(
270 $this->evaluateConditionCommonMethod->invokeArgs(
271 $this->conditionMatcher,
272 array('userFunc', 'user_testFunctionWithThreeArguments(0,true,"foo")')
273 )
274 );
275 }
276
277 /**
278 * @test
279 */
280 public function testUserFuncWithMultipleDifferentArgumentsNullStringBool()
281 {
282 $this->assertTrue(
283 $this->evaluateConditionCommonMethod->invokeArgs(
284 $this->conditionMatcher,
285 array('userFunc', 'user_testFunctionWithThreeArguments(0,"foo",true)')
286 )
287 );
288 }
289
290 /**
291 * @test
292 */
293 public function testUserFuncWithMultipleDifferentArgumentsStringBoolNull()
294 {
295 $this->assertTrue(
296 $this->evaluateConditionCommonMethod->invokeArgs(
297 $this->conditionMatcher,
298 array('userFunc', 'user_testFunctionWithThreeArguments("foo",true,0)')
299 )
300 );
301 }
302
303 /**
304 * @test
305 */
306 public function testUserFuncWithMultipleDifferentArgumentsStringNullBool()
307 {
308 $this->assertTrue(
309 $this->evaluateConditionCommonMethod->invokeArgs(
310 $this->conditionMatcher,
311 array('userFunc', 'user_testFunctionWithThreeArguments("foo",0,true)')
312 )
313 );
314 }
315
316 /**
317 * @test
318 */
319 public function testUserFuncWithMultipleDifferentArgumentsBoolNullString()
320 {
321 $this->assertTrue(
322 $this->evaluateConditionCommonMethod->invokeArgs(
323 $this->conditionMatcher,
324 array('userFunc', 'user_testFunctionWithThreeArguments(true,0,"foo")')
325 )
326 );
327 }
328
329 /**
330 * @test
331 */
332 public function testUserFuncWithMultipleDifferentArgumentsBoolStringNull()
333 {
334 $this->assertTrue(
335 $this->evaluateConditionCommonMethod->invokeArgs(
336 $this->conditionMatcher,
337 array('userFunc', 'user_testFunctionWithThreeArguments(true,"foo",0)')
338 )
339 );
340 }
341
342 /**
343 * @test
344 */
345 public function testUserFuncWithMultipleDifferentArgumentsNullBoolStringSingleQuotes()
346 {
347 $this->assertTrue(
348 $this->evaluateConditionCommonMethod->invokeArgs(
349 $this->conditionMatcher,
350 array('userFunc', "user_testFunctionWithThreeArguments(0,true,'foo')")
351 )
352 );
353 }
354
355 /**
356 * @test
357 */
358 public function testUserFuncWithMultipleDifferentArgumentsNullStringBoolSingleQuotes()
359 {
360 $this->assertTrue(
361 $this->evaluateConditionCommonMethod->invokeArgs(
362 $this->conditionMatcher,
363 array('userFunc', "user_testFunctionWithThreeArguments(0,'foo',true)")
364 )
365 );
366 }
367
368 /**
369 * @test
370 */
371 public function testUserFuncWithMultipleDifferentArgumentsStringBoolNullSingleQuotes()
372 {
373 $this->assertTrue(
374 $this->evaluateConditionCommonMethod->invokeArgs(
375 $this->conditionMatcher,
376 array('userFunc', "user_testFunctionWithThreeArguments('foo',true,0)")
377 )
378 );
379 }
380
381 /**
382 * @test
383 */
384 public function testUserFuncWithMultipleDifferentArgumentsStringNullBoolSingleQuotes()
385 {
386 $this->assertTrue(
387 $this->evaluateConditionCommonMethod->invokeArgs(
388 $this->conditionMatcher,
389 array('userFunc', "user_testFunctionWithThreeArguments('foo',0,true)")
390 )
391 );
392 }
393
394 /**
395 * @test
396 */
397 public function testUserFuncWithMultipleDifferentArgumentsBoolNullStringSingleQuotes()
398 {
399 $this->assertTrue(
400 $this->evaluateConditionCommonMethod->invokeArgs(
401 $this->conditionMatcher,
402 array('userFunc', "user_testFunctionWithThreeArguments(true,0,'foo')")
403 )
404 );
405 }
406
407 /**
408 * @test
409 */
410 public function testUserFuncWithMultipleDifferentArgumentsBoolStringNullSingleQuotes()
411 {
412 $this->assertTrue(
413 $this->evaluateConditionCommonMethod->invokeArgs(
414 $this->conditionMatcher,
415 array('userFunc', "user_testFunctionWithThreeArguments(true,'foo',0)")
416 )
417 );
418 }
419
420 /**
421 * @test
422 */
423 public function testUserFuncWithMultipleSingleQuotedArguments()
424 {
425 $this->assertTrue(
426 $this->evaluateConditionCommonMethod->invokeArgs(
427 $this->conditionMatcher,
428 array('userFunc', "user_testFunctionWithThreeArguments('foo','bar', 'baz')")
429 )
430 );
431 }
432
433 /**
434 * @test
435 */
436 public function testUserFuncWithMultipleSoubleQuotedArguments()
437 {
438 $this->assertTrue(
439 $this->evaluateConditionCommonMethod->invokeArgs(
440 $this->conditionMatcher,
441 array('userFunc', 'user_testFunctionWithThreeArguments("foo","bar","baz")')
442 )
443 );
444 }
445
446 /**
447 * @test
448 */
449 public function testUserFuncReturnsFalse()
450 {
451 $this->assertFalse(
452 $this->evaluateConditionCommonMethod->invokeArgs(
453 $this->conditionMatcher,
454 array('userFunc', 'user_testFunctionFalse')
455 )
456 );
457 }
458
459 /**
460 * @test
461 */
462 public function testUserFuncWithMultipleArgumentsAndQuotes()
463 {
464 $this->assertTrue(
465 $this->evaluateConditionCommonMethod->invokeArgs(
466 $this->conditionMatcher,
467 array('userFunc', 'user_testFunctionWithThreeArguments(1,2,"3,4,5,6")')
468 )
469 );
470 }
471
472 /**
473 * @test
474 */
475 public function testUserFuncWithMultipleArgumentsAndQuotesAndSpaces()
476 {
477 $this->assertTrue(
478 $this->evaluateConditionCommonMethod->invokeArgs(
479 $this->conditionMatcher,
480 array('userFunc', 'user_testFunctionWithThreeArguments ( 1 , 2, "3, 4, 5, 6" )')
481 )
482 );
483 }
484
485 /**
486 * @test
487 */
488 public function testUserFuncWithMultipleArgumentsAndQuotesAndSpacesStripped()
489 {
490 $this->assertTrue(
491 $this->evaluateConditionCommonMethod->invokeArgs(
492 $this->conditionMatcher,
493 array('userFunc', 'user_testFunctionWithThreeArgumentsSpaces ( 1 , 2, "3, 4, 5, 6" )')
494 )
495 );
496 }
497
498 /**
499 * @test
500 */
501 public function testUserFuncWithSpacesInQuotes()
502 {
503 $this->assertTrue(
504 $this->evaluateConditionCommonMethod->invokeArgs(
505 $this->conditionMatcher,
506 array('userFunc', 'user_testFunctionWithSpaces(" 3, 4, 5, 6 ")')
507 )
508 );
509 }
510
511 /**
512 * @test
513 */
514 public function testUserFuncWithMultipleArgumentsAndQuotesAndSpacesStrippedAndEscapes()
515 {
516 $this->assertTrue(
517 $this->evaluateConditionCommonMethod->invokeArgs(
518 $this->conditionMatcher,
519 array('userFunc', 'user_testFunctionWithThreeArgumentsSpaces ( 1 , 2, "3, \"4, 5\", 6" )')
520 )
521 );
522 }
523
524 /**
525 * @test
526 */
527 public function testUserFuncWithQuoteMissing()
528 {
529 $this->assertTrue(
530 $this->evaluateConditionCommonMethod->invokeArgs(
531 $this->conditionMatcher,
532 array('userFunc', 'user_testFunctionWithQuoteMissing ("value \")')
533 )
534 );
535 }
536
537 /**
538 * @test
539 */
540 public function testUserFuncWithQuotesInside()
541 {
542 $this->assertTrue(
543 $this->evaluateConditionCommonMethod->invokeArgs(
544 $this->conditionMatcher,
545 array('userFunc', 'user_testQuotes("1 \" 2")')
546 )
547 );
548 }
549
550 /**
551 * @test
552 */
553 public function testUserFuncWithClassMethodCall()
554 {
555 $this->assertTrue(
556 $this->evaluateConditionCommonMethod->invokeArgs(
557 $this->conditionMatcher,
558 array('userFunc', 'ConditionMatcherUserFunctions::isTrue(1)')
559 )
560 );
561 }
562 }