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