Security update for Core, with self-updated composer
[yaffs-website] / vendor / symfony / http-kernel / Tests / HttpKernelTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Component\HttpKernel\Tests;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
16 use Symfony\Component\HttpFoundation\RequestStack;
17 use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
18 use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
19 use Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent;
20 use Symfony\Component\HttpKernel\HttpKernel;
21 use Symfony\Component\HttpKernel\HttpKernelInterface;
22 use Symfony\Component\HttpKernel\KernelEvents;
23 use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
24 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
25 use Symfony\Component\HttpFoundation\Request;
26 use Symfony\Component\HttpFoundation\Response;
27 use Symfony\Component\HttpFoundation\RedirectResponse;
28 use Symfony\Component\EventDispatcher\EventDispatcher;
29
30 class HttpKernelTest extends TestCase
31 {
32     /**
33      * @expectedException \RuntimeException
34      */
35     public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrue()
36     {
37         $kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); });
38
39         $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
40     }
41
42     /**
43      * @expectedException \RuntimeException
44      */
45     public function testHandleWhenControllerThrowsAnExceptionAndCatchIsFalseAndNoListenerIsRegistered()
46     {
47         $kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); });
48
49         $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false);
50     }
51
52     public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrueWithAHandlingListener()
53     {
54         $dispatcher = new EventDispatcher();
55         $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
56             $event->setResponse(new Response($event->getException()->getMessage()));
57         });
58
59         $kernel = $this->getHttpKernel($dispatcher, function () { throw new \RuntimeException('foo'); });
60         $response = $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
61
62         $this->assertEquals('500', $response->getStatusCode());
63         $this->assertEquals('foo', $response->getContent());
64     }
65
66     public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrueWithANonHandlingListener()
67     {
68         $exception = new \RuntimeException();
69
70         $dispatcher = new EventDispatcher();
71         $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
72             // should set a response, but does not
73         });
74
75         $kernel = $this->getHttpKernel($dispatcher, function () use ($exception) { throw $exception; });
76
77         try {
78             $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
79             $this->fail('LogicException expected');
80         } catch (\RuntimeException $e) {
81             $this->assertSame($exception, $e);
82         }
83     }
84
85     public function testHandleExceptionWithARedirectionResponse()
86     {
87         $dispatcher = new EventDispatcher();
88         $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
89             $event->setResponse(new RedirectResponse('/login', 301));
90         });
91
92         $kernel = $this->getHttpKernel($dispatcher, function () { throw new AccessDeniedHttpException(); });
93         $response = $kernel->handle(new Request());
94
95         $this->assertEquals('301', $response->getStatusCode());
96         $this->assertEquals('/login', $response->headers->get('Location'));
97     }
98
99     public function testHandleHttpException()
100     {
101         $dispatcher = new EventDispatcher();
102         $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
103             $event->setResponse(new Response($event->getException()->getMessage()));
104         });
105
106         $kernel = $this->getHttpKernel($dispatcher, function () { throw new MethodNotAllowedHttpException(array('POST')); });
107         $response = $kernel->handle(new Request());
108
109         $this->assertEquals('405', $response->getStatusCode());
110         $this->assertEquals('POST', $response->headers->get('Allow'));
111     }
112
113     /**
114      * @dataProvider getStatusCodes
115      */
116     public function testHandleWhenAnExceptionIsHandledWithASpecificStatusCode($responseStatusCode, $expectedStatusCode)
117     {
118         $dispatcher = new EventDispatcher();
119         $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) use ($responseStatusCode, $expectedStatusCode) {
120             $event->setResponse(new Response('', $responseStatusCode, array('X-Status-Code' => $expectedStatusCode)));
121         });
122
123         $kernel = $this->getHttpKernel($dispatcher, function () { throw new \RuntimeException(); });
124         $response = $kernel->handle(new Request());
125
126         $this->assertEquals($expectedStatusCode, $response->getStatusCode());
127         $this->assertFalse($response->headers->has('X-Status-Code'));
128     }
129
130     public function getStatusCodes()
131     {
132         return array(
133             array(200, 404),
134             array(404, 200),
135             array(301, 200),
136             array(500, 200),
137         );
138     }
139
140     public function testHandleWhenAListenerReturnsAResponse()
141     {
142         $dispatcher = new EventDispatcher();
143         $dispatcher->addListener(KernelEvents::REQUEST, function ($event) {
144             $event->setResponse(new Response('hello'));
145         });
146
147         $kernel = $this->getHttpKernel($dispatcher);
148
149         $this->assertEquals('hello', $kernel->handle(new Request())->getContent());
150     }
151
152     /**
153      * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
154      */
155     public function testHandleWhenNoControllerIsFound()
156     {
157         $dispatcher = new EventDispatcher();
158         $kernel = $this->getHttpKernel($dispatcher, false);
159
160         $kernel->handle(new Request());
161     }
162
163     public function testHandleWhenTheControllerIsAClosure()
164     {
165         $response = new Response('foo');
166         $dispatcher = new EventDispatcher();
167         $kernel = $this->getHttpKernel($dispatcher, function () use ($response) { return $response; });
168
169         $this->assertSame($response, $kernel->handle(new Request()));
170     }
171
172     public function testHandleWhenTheControllerIsAnObjectWithInvoke()
173     {
174         $dispatcher = new EventDispatcher();
175         $kernel = $this->getHttpKernel($dispatcher, new Controller());
176
177         $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
178     }
179
180     public function testHandleWhenTheControllerIsAFunction()
181     {
182         $dispatcher = new EventDispatcher();
183         $kernel = $this->getHttpKernel($dispatcher, 'Symfony\Component\HttpKernel\Tests\controller_func');
184
185         $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
186     }
187
188     public function testHandleWhenTheControllerIsAnArray()
189     {
190         $dispatcher = new EventDispatcher();
191         $kernel = $this->getHttpKernel($dispatcher, array(new Controller(), 'controller'));
192
193         $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
194     }
195
196     public function testHandleWhenTheControllerIsAStaticArray()
197     {
198         $dispatcher = new EventDispatcher();
199         $kernel = $this->getHttpKernel($dispatcher, array('Symfony\Component\HttpKernel\Tests\Controller', 'staticcontroller'));
200
201         $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
202     }
203
204     /**
205      * @expectedException \LogicException
206      */
207     public function testHandleWhenTheControllerDoesNotReturnAResponse()
208     {
209         $dispatcher = new EventDispatcher();
210         $kernel = $this->getHttpKernel($dispatcher, function () { return 'foo'; });
211
212         $kernel->handle(new Request());
213     }
214
215     public function testHandleWhenTheControllerDoesNotReturnAResponseButAViewIsRegistered()
216     {
217         $dispatcher = new EventDispatcher();
218         $dispatcher->addListener(KernelEvents::VIEW, function ($event) {
219             $event->setResponse(new Response($event->getControllerResult()));
220         });
221
222         $kernel = $this->getHttpKernel($dispatcher, function () { return 'foo'; });
223
224         $this->assertEquals('foo', $kernel->handle(new Request())->getContent());
225     }
226
227     public function testHandleWithAResponseListener()
228     {
229         $dispatcher = new EventDispatcher();
230         $dispatcher->addListener(KernelEvents::RESPONSE, function ($event) {
231             $event->setResponse(new Response('foo'));
232         });
233         $kernel = $this->getHttpKernel($dispatcher);
234
235         $this->assertEquals('foo', $kernel->handle(new Request())->getContent());
236     }
237
238     public function testHandleAllowChangingControllerArguments()
239     {
240         $dispatcher = new EventDispatcher();
241         $dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function (FilterControllerArgumentsEvent $event) {
242             $event->setArguments(array('foo'));
243         });
244
245         $kernel = $this->getHttpKernel($dispatcher, function ($content) { return new Response($content); });
246
247         $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
248     }
249
250     public function testHandleAllowChangingControllerAndArguments()
251     {
252         $dispatcher = new EventDispatcher();
253         $dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function (FilterControllerArgumentsEvent $event) {
254             $oldController = $event->getController();
255             $oldArguments = $event->getArguments();
256
257             $newController = function ($id) use ($oldController, $oldArguments) {
258                 $response = call_user_func_array($oldController, $oldArguments);
259
260                 $response->headers->set('X-Id', $id);
261
262                 return $response;
263             };
264
265             $event->setController($newController);
266             $event->setArguments(array('bar'));
267         });
268
269         $kernel = $this->getHttpKernel($dispatcher, function ($content) { return new Response($content); }, null, array('foo'));
270
271         $this->assertResponseEquals(new Response('foo', 200, array('X-Id' => 'bar')), $kernel->handle(new Request()));
272     }
273
274     public function testTerminate()
275     {
276         $dispatcher = new EventDispatcher();
277         $kernel = $this->getHttpKernel($dispatcher);
278         $dispatcher->addListener(KernelEvents::TERMINATE, function ($event) use (&$called, &$capturedKernel, &$capturedRequest, &$capturedResponse) {
279             $called = true;
280             $capturedKernel = $event->getKernel();
281             $capturedRequest = $event->getRequest();
282             $capturedResponse = $event->getResponse();
283         });
284
285         $kernel->terminate($request = Request::create('/'), $response = new Response());
286         $this->assertTrue($called);
287         $this->assertEquals($kernel, $capturedKernel);
288         $this->assertEquals($request, $capturedRequest);
289         $this->assertEquals($response, $capturedResponse);
290     }
291
292     public function testVerifyRequestStackPushPopDuringHandle()
293     {
294         $request = new Request();
295
296         $stack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->setMethods(array('push', 'pop'))->getMock();
297         $stack->expects($this->at(0))->method('push')->with($this->equalTo($request));
298         $stack->expects($this->at(1))->method('pop');
299
300         $dispatcher = new EventDispatcher();
301         $kernel = $this->getHttpKernel($dispatcher, null, $stack);
302
303         $kernel->handle($request, HttpKernelInterface::MASTER_REQUEST);
304     }
305
306     /**
307      * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
308      */
309     public function testInconsistentClientIpsOnMasterRequests()
310     {
311         $request = new Request();
312         $request->setTrustedProxies(array('1.1.1.1'), -1);
313         $request->server->set('REMOTE_ADDR', '1.1.1.1');
314         $request->headers->set('FORWARDED', 'for=2.2.2.2');
315         $request->headers->set('X_FORWARDED_FOR', '3.3.3.3');
316
317         $dispatcher = new EventDispatcher();
318         $dispatcher->addListener(KernelEvents::REQUEST, function ($event) {
319             $event->getRequest()->getClientIp();
320         });
321
322         $kernel = $this->getHttpKernel($dispatcher);
323         $kernel->handle($request, $kernel::MASTER_REQUEST, false);
324     }
325
326     private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, RequestStack $requestStack = null, array $arguments = array())
327     {
328         if (null === $controller) {
329             $controller = function () { return new Response('Hello'); };
330         }
331
332         $controllerResolver = $this->getMockBuilder(ControllerResolverInterface::class)->getMock();
333         $controllerResolver
334             ->expects($this->any())
335             ->method('getController')
336             ->will($this->returnValue($controller));
337
338         $argumentResolver = $this->getMockBuilder(ArgumentResolverInterface::class)->getMock();
339         $argumentResolver
340             ->expects($this->any())
341             ->method('getArguments')
342             ->will($this->returnValue($arguments));
343
344         return new HttpKernel($eventDispatcher, $controllerResolver, $requestStack, $argumentResolver);
345     }
346
347     private function assertResponseEquals(Response $expected, Response $actual)
348     {
349         $expected->setDate($actual->getDate());
350         $this->assertEquals($expected, $actual);
351     }
352 }
353
354 class Controller
355 {
356     public function __invoke()
357     {
358         return new Response('foo');
359     }
360
361     public function controller()
362     {
363         return new Response('foo');
364     }
365
366     public static function staticController()
367     {
368         return new Response('foo');
369     }
370 }
371
372 function controller_func()
373 {
374     return new Response('foo');
375 }