4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\HttpKernel\Tests\EventListener;
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\EventDispatcher\EventDispatcher;
16 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
17 use Symfony\Component\HttpKernel\HttpKernelInterface;
18 use Symfony\Component\HttpKernel\EventListener\ExceptionListener;
19 use Symfony\Component\HttpKernel\KernelEvents;
20 use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
21 use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
22 use Symfony\Component\HttpFoundation\Request;
23 use Symfony\Component\HttpFoundation\Response;
24 use Symfony\Component\HttpKernel\Tests\Logger;
27 * ExceptionListenerTest.
29 * @author Robert Schönthal <seroscho@googlemail.com>
31 * @group time-sensitive
33 class ExceptionListenerTest extends TestCase
35 public function testConstruct()
37 $logger = new TestLogger();
38 $l = new ExceptionListener('foo', $logger);
40 $_logger = new \ReflectionProperty(get_class($l), 'logger');
41 $_logger->setAccessible(true);
42 $_controller = new \ReflectionProperty(get_class($l), 'controller');
43 $_controller->setAccessible(true);
45 $this->assertSame($logger, $_logger->getValue($l));
46 $this->assertSame('foo', $_controller->getValue($l));
50 * @dataProvider provider
52 public function testHandleWithoutLogger($event, $event2)
54 $this->iniSet('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul');
56 $l = new ExceptionListener('foo');
57 $l->onKernelException($event);
59 $this->assertEquals(new Response('foo'), $event->getResponse());
62 $l->onKernelException($event2);
63 $this->fail('RuntimeException expected');
64 } catch (\RuntimeException $e) {
65 $this->assertSame('bar', $e->getMessage());
66 $this->assertSame('foo', $e->getPrevious()->getMessage());
71 * @dataProvider provider
73 public function testHandleWithLogger($event, $event2)
75 $logger = new TestLogger();
77 $l = new ExceptionListener('foo', $logger);
78 $l->onKernelException($event);
80 $this->assertEquals(new Response('foo'), $event->getResponse());
83 $l->onKernelException($event2);
84 $this->fail('RuntimeException expected');
85 } catch (\RuntimeException $e) {
86 $this->assertSame('bar', $e->getMessage());
87 $this->assertSame('foo', $e->getPrevious()->getMessage());
90 $this->assertEquals(3, $logger->countErrors());
91 $this->assertCount(3, $logger->getLogs('critical'));
94 public function provider()
96 if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
97 return array(array(null, null));
100 $request = new Request();
101 $exception = new \Exception('foo');
102 $event = new GetResponseForExceptionEvent(new TestKernel(), $request, HttpKernelInterface::MASTER_REQUEST, $exception);
103 $event2 = new GetResponseForExceptionEvent(new TestKernelThatThrowsException(), $request, HttpKernelInterface::MASTER_REQUEST, $exception);
106 array($event, $event2),
110 public function testSubRequestFormat()
112 $listener = new ExceptionListener('foo', $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock());
114 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
115 $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
116 return new Response($request->getRequestFormat());
119 $request = Request::create('/');
120 $request->setRequestFormat('xml');
122 $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo'));
123 $listener->onKernelException($event);
125 $response = $event->getResponse();
126 $this->assertEquals('xml', $response->getContent());
129 public function testCSPHeaderIsRemoved()
131 $dispatcher = new EventDispatcher();
132 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
133 $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
134 return new Response($request->getRequestFormat());
137 $listener = new ExceptionListener('foo', $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(), true);
139 $dispatcher->addSubscriber($listener);
141 $request = Request::create('/');
142 $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo'));
143 $dispatcher->dispatch(KernelEvents::EXCEPTION, $event);
145 $response = new Response('', 200, array('content-security-policy' => "style-src 'self'"));
146 $this->assertTrue($response->headers->has('content-security-policy'));
148 $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response);
149 $dispatcher->dispatch(KernelEvents::RESPONSE, $event);
151 $this->assertFalse($response->headers->has('content-security-policy'), 'CSP header has been removed');
152 $this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed');
155 public function testNullController()
157 $listener = new ExceptionListener(null);
158 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
159 $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
160 $controller = $request->attributes->get('_controller');
162 return $controller();
164 $request = Request::create('/');
165 $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo'));
167 $listener->onKernelException($event);
169 $this->assertContains('Whoops, looks like something went wrong.', $event->getResponse()->getContent());
173 class TestLogger extends Logger implements DebugLoggerInterface
175 public function countErrors()
177 return count($this->logs['critical']);
181 class TestKernel implements HttpKernelInterface
183 public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
185 return new Response('foo');
189 class TestKernelThatThrowsException implements HttpKernelInterface
191 public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
193 throw new \RuntimeException('bar');