* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\EventListener\ExceptionListener; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Tests\Logger; /** * ExceptionListenerTest. * * @author Robert Schönthal * * @group time-sensitive */ class ExceptionListenerTest extends TestCase { public function testConstruct() { $logger = new TestLogger(); $l = new ExceptionListener('foo', $logger); $_logger = new \ReflectionProperty(get_class($l), 'logger'); $_logger->setAccessible(true); $_controller = new \ReflectionProperty(get_class($l), 'controller'); $_controller->setAccessible(true); $this->assertSame($logger, $_logger->getValue($l)); $this->assertSame('foo', $_controller->getValue($l)); } /** * @dataProvider provider */ public function testHandleWithoutLogger($event, $event2) { $this->iniSet('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul'); $l = new ExceptionListener('foo'); $l->onKernelException($event); $this->assertEquals(new Response('foo'), $event->getResponse()); try { $l->onKernelException($event2); $this->fail('RuntimeException expected'); } catch (\RuntimeException $e) { $this->assertSame('bar', $e->getMessage()); $this->assertSame('foo', $e->getPrevious()->getMessage()); } } /** * @dataProvider provider */ public function testHandleWithLogger($event, $event2) { $logger = new TestLogger(); $l = new ExceptionListener('foo', $logger); $l->onKernelException($event); $this->assertEquals(new Response('foo'), $event->getResponse()); try { $l->onKernelException($event2); $this->fail('RuntimeException expected'); } catch (\RuntimeException $e) { $this->assertSame('bar', $e->getMessage()); $this->assertSame('foo', $e->getPrevious()->getMessage()); } $this->assertEquals(3, $logger->countErrors()); $this->assertCount(3, $logger->getLogs('critical')); } public function provider() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { return array(array(null, null)); } $request = new Request(); $exception = new \Exception('foo'); $event = new GetResponseForExceptionEvent(new TestKernel(), $request, HttpKernelInterface::MASTER_REQUEST, $exception); $event2 = new GetResponseForExceptionEvent(new TestKernelThatThrowsException(), $request, HttpKernelInterface::MASTER_REQUEST, $exception); return array( array($event, $event2), ); } public function testSubRequestFormat() { $listener = new ExceptionListener('foo', $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock()); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { return new Response($request->getRequestFormat()); })); $request = Request::create('/'); $request->setRequestFormat('xml'); $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo')); $listener->onKernelException($event); $response = $event->getResponse(); $this->assertEquals('xml', $response->getContent()); } public function testCSPHeaderIsRemoved() { $dispatcher = new EventDispatcher(); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { return new Response($request->getRequestFormat()); })); $listener = new ExceptionListener('foo', $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(), true); $dispatcher->addSubscriber($listener); $request = Request::create('/'); $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo')); $dispatcher->dispatch(KernelEvents::EXCEPTION, $event); $response = new Response('', 200, array('content-security-policy' => "style-src 'self'")); $this->assertTrue($response->headers->has('content-security-policy')); $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); $dispatcher->dispatch(KernelEvents::RESPONSE, $event); $this->assertFalse($response->headers->has('content-security-policy'), 'CSP header has been removed'); $this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed'); } public function testNullController() { $listener = new ExceptionListener(null); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { $controller = $request->attributes->get('_controller'); return $controller(); })); $request = Request::create('/'); $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo')); $listener->onKernelException($event); $this->assertContains('Whoops, looks like something went wrong.', $event->getResponse()->getContent()); } } class TestLogger extends Logger implements DebugLoggerInterface { public function countErrors() { return count($this->logs['critical']); } } class TestKernel implements HttpKernelInterface { public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) { return new Response('foo'); } } class TestKernelThatThrowsException implements HttpKernelInterface { public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) { throw new \RuntimeException('bar'); } } __halt_compiler();----SIGNATURE:----FX92j65dSTm5jk2WWDFBK+S1H+OQ/wAH8cVziGDQHRTmmRNeutI9aAO8yMBwiK9KBAWPCUFVqhnfp7IBf3OZ7GbKYfovi65+aGFDjaUstjrpa1/zQmBUQ32ZhQSkhU4/6C405I2pnjBHHEAXjJ8nSn9kHx9QzTLeS5p65ePc28Lymqs5TH7QjzDSpBXTOdysTXALmSZZQA0LmQq95KKT59rIDI826w26ZtLZq5t+jhs2ktsRheR+BKhyfqW9OOATa29JiwX2rHS306lNHNUJbo6phI9sh6r4R+9TqC1rZddcefjidNjYtYVUBvjmcz0c4ptAN30fXTBBx4DzX+jFuVQmFAwK46YtyvdTHa+fIo3mtwSXwciSVmDjTE8Hl1VlgvdllNBmadcC44mH1nm7OunqBU2I8B7WdFn2moGpVz5GzNbLgpx+ZlWF01Utzu7t8Dh/XyRPEQ51OnUOa+LUpkTaaWcObNkn9VQ/ADF3oBKliV2q0TzTc1ZM6qnp0cFv0YFhDnfxPDfytDshUpox3RZM0USCE71R+P8Jyjs5/hMDYZ/CASFntNqJr45re1KOL8Wm2gaZEzX+aB8lGi4a4+PowXVEuIMsJrLJEug3HayUWnsBaJRylDrOCzdWruhNPhsDr0WZU3X6ObavNtzEnXx27W34j2dEgTeZlnOl7cA=----ATTACHMENT:----Njg4NDI0NTUzNDMyMDM4NSA1MDc0NTE1MzIyMDcxODM4IDk2MTM1Njc4Nzk3Nzk4OTY=