This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php

527 lines
18 KiB
PHP
Raw Normal View History

<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Debug\Tests;
2014-05-26 11:29:25 +01:00
use Psr\Log\LogLevel;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\BufferingLogger;
use Symfony\Component\Debug\Exception\ContextErrorException;
/**
2014-12-21 17:00:50 +00:00
* ErrorHandlerTest.
*
* @author Robert Schönthal <seroscho@googlemail.com>
2014-05-26 11:29:25 +01:00
* @author Nicolas Grekas <p@tchwork.com>
*/
class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
{
public function testRegister()
{
$handler = ErrorHandler::register();
try {
$this->assertInstanceOf('Symfony\Component\Debug\ErrorHandler', $handler);
$this->assertSame($handler, ErrorHandler::register());
$newHandler = new ErrorHandler();
$this->assertSame($newHandler, ErrorHandler::register($newHandler, false));
$h = set_error_handler('var_dump');
restore_error_handler();
$this->assertSame(array($handler, 'handleError'), $h);
try {
$this->assertSame($newHandler, ErrorHandler::register($newHandler, true));
$h = set_error_handler('var_dump');
restore_error_handler();
$this->assertSame(array($newHandler, 'handleError'), $h);
} catch (\Exception $e) {
}
restore_error_handler();
restore_exception_handler();
if (isset($e)) {
throw $e;
}
} catch (\Exception $e) {
}
restore_error_handler();
restore_exception_handler();
if (isset($e)) {
throw $e;
}
}
public function testNotice()
{
ErrorHandler::register();
try {
self::triggerNotice($this);
$this->fail('ContextErrorException expected');
} catch (ContextErrorException $exception) {
// if an exception is thrown, the test passed
restore_error_handler();
2014-05-26 11:29:25 +01:00
restore_exception_handler();
$this->assertEquals(E_NOTICE, $exception->getSeverity());
$this->assertEquals(__FILE__, $exception->getFile());
$this->assertRegExp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage());
$this->assertArrayHasKey('foobar', $exception->getContext());
$trace = $exception->getTrace();
$this->assertEquals(__FILE__, $trace[0]['file']);
$this->assertEquals('Symfony\Component\Debug\ErrorHandler', $trace[0]['class']);
2014-05-26 11:29:25 +01:00
$this->assertEquals('handleError', $trace[0]['function']);
$this->assertEquals('->', $trace[0]['type']);
$this->assertEquals(__FILE__, $trace[1]['file']);
$this->assertEquals(__CLASS__, $trace[1]['class']);
$this->assertEquals('triggerNotice', $trace[1]['function']);
$this->assertEquals('::', $trace[1]['type']);
$this->assertEquals(__FILE__, $trace[1]['file']);
$this->assertEquals(__CLASS__, $trace[2]['class']);
$this->assertEquals(__FUNCTION__, $trace[2]['function']);
$this->assertEquals('->', $trace[2]['type']);
} catch (\Exception $e) {
restore_error_handler();
2014-05-26 11:29:25 +01:00
restore_exception_handler();
throw $e;
}
}
2011-04-15 20:12:02 +01:00
// dummy function to test trace in error handler.
2013-11-28 10:16:43 +00:00
private static function triggerNotice($that)
{
// dummy variable to check for in error handler.
$foobar = 123;
2013-11-28 10:16:43 +00:00
$that->assertSame('', $foo.$foo.$bar);
}
2011-04-15 20:12:02 +01:00
public function testConstruct()
{
try {
$handler = ErrorHandler::register();
$handler->throwAt(3, true);
$this->assertEquals(3 | E_RECOVERABLE_ERROR | E_USER_ERROR, $handler->throwAt(0));
2014-05-26 11:29:25 +01:00
restore_error_handler();
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
restore_exception_handler();
throw $e;
}
}
public function testDefaultLogger()
{
try {
$handler = ErrorHandler::register();
2011-04-15 20:12:02 +01:00
2014-05-26 11:29:25 +01:00
$logger = $this->getMock('Psr\Log\LoggerInterface');
2011-04-15 20:12:02 +01:00
2014-05-26 11:29:25 +01:00
$handler->setDefaultLogger($logger, E_NOTICE);
$handler->setDefaultLogger($logger, array(E_USER_NOTICE => LogLevel::CRITICAL));
$loggers = array(
2014-11-04 14:29:39 +00:00
E_DEPRECATED => array(null, LogLevel::INFO),
E_USER_DEPRECATED => array(null, LogLevel::INFO),
E_NOTICE => array($logger, LogLevel::WARNING),
2014-11-04 14:29:39 +00:00
E_USER_NOTICE => array($logger, LogLevel::CRITICAL),
E_STRICT => array(null, LogLevel::WARNING),
2014-11-04 14:29:39 +00:00
E_WARNING => array(null, LogLevel::WARNING),
E_USER_WARNING => array(null, LogLevel::WARNING),
E_COMPILE_WARNING => array(null, LogLevel::WARNING),
E_CORE_WARNING => array(null, LogLevel::WARNING),
E_USER_ERROR => array(null, LogLevel::CRITICAL),
E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
E_PARSE => array(null, LogLevel::CRITICAL),
E_ERROR => array(null, LogLevel::CRITICAL),
E_CORE_ERROR => array(null, LogLevel::CRITICAL),
2014-05-26 11:29:25 +01:00
);
$this->assertSame($loggers, $handler->setLoggers(array()));
2011-04-15 20:12:02 +01:00
restore_error_handler();
2014-05-26 11:29:25 +01:00
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
2014-05-26 11:29:25 +01:00
restore_exception_handler();
throw $e;
}
}
2014-05-26 11:29:25 +01:00
public function testHandleError()
{
try {
$handler = ErrorHandler::register();
$handler->throwAt(0, true);
2014-05-26 11:29:25 +01:00
$this->assertFalse($handler->handleError(0, 'foo', 'foo.php', 12, array()));
restore_error_handler();
2014-05-26 11:29:25 +01:00
restore_exception_handler();
$handler = ErrorHandler::register();
$handler->throwAt(3, true);
2014-05-26 11:29:25 +01:00
$this->assertFalse($handler->handleError(4, 'foo', 'foo.php', 12, array()));
2011-04-15 20:12:02 +01:00
restore_error_handler();
2014-05-26 11:29:25 +01:00
restore_exception_handler();
2011-04-15 20:12:02 +01:00
$handler = ErrorHandler::register();
$handler->throwAt(3, true);
try {
2014-05-26 11:29:25 +01:00
$handler->handleError(4, 'foo', 'foo.php', 12, array());
} catch (\ErrorException $e) {
2014-05-26 11:29:25 +01:00
$this->assertSame('Parse Error: foo', $e->getMessage());
$this->assertSame(4, $e->getSeverity());
$this->assertSame('foo.php', $e->getFile());
$this->assertSame(12, $e->getLine());
}
restore_error_handler();
2014-05-26 11:29:25 +01:00
restore_exception_handler();
$handler = ErrorHandler::register();
$handler->throwAt(E_USER_DEPRECATED, true);
2014-05-26 11:29:25 +01:00
$this->assertFalse($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
restore_error_handler();
2014-05-26 11:29:25 +01:00
restore_exception_handler();
$handler = ErrorHandler::register();
$handler->throwAt(E_DEPRECATED, true);
2014-05-26 11:29:25 +01:00
$this->assertFalse($handler->handleError(E_DEPRECATED, 'foo', 'foo.php', 12, array()));
restore_error_handler();
2014-05-26 11:29:25 +01:00
restore_exception_handler();
$logger = $this->getMock('Psr\Log\LoggerInterface');
2014-12-03 22:04:33 +00:00
$warnArgCheck = function ($logLevel, $message, $context) {
$this->assertEquals('info', $logLevel);
$this->assertEquals('foo', $message);
$this->assertArrayHasKey('type', $context);
$this->assertEquals($context['type'], E_USER_DEPRECATED);
$this->assertArrayHasKey('stack', $context);
$this->assertInternalType('array', $context['stack']);
};
$logger
->expects($this->once())
2014-05-26 11:29:25 +01:00
->method('log')
->will($this->returnCallback($warnArgCheck))
;
$handler = ErrorHandler::register();
2014-05-26 11:29:25 +01:00
$handler->setDefaultLogger($logger, E_USER_DEPRECATED);
$this->assertTrue($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array()));
restore_error_handler();
restore_exception_handler();
$logger = $this->getMock('Psr\Log\LoggerInterface');
2014-12-03 22:04:33 +00:00
$logArgCheck = function ($level, $message, $context) {
$this->assertEquals('Undefined variable: undefVar', $message);
$this->assertArrayHasKey('type', $context);
$this->assertEquals($context['type'], E_NOTICE);
2014-05-26 11:29:25 +01:00
};
$logger
->expects($this->once())
->method('log')
->will($this->returnCallback($logArgCheck))
;
$handler = ErrorHandler::register();
2014-05-26 11:29:25 +01:00
$handler->setDefaultLogger($logger, E_NOTICE);
$handler->screamAt(E_NOTICE);
unset($undefVar);
@$undefVar++;
restore_error_handler();
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
restore_exception_handler();
throw $e;
}
}
public function testHandleUserError()
{
try {
$handler = ErrorHandler::register();
$handler->throwAt(0, true);
$e = null;
$x = new \Exception('Foo');
try {
$f = new Fixtures\ToStringThrower($x);
$f .= ''; // Trigger $f->__toString()
} catch (\Exception $e) {
}
$this->assertSame($x, $e);
restore_error_handler();
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
restore_exception_handler();
2014-05-26 11:29:25 +01:00
throw $e;
}
}
public function testHandleDeprecation()
{
2015-09-01 11:10:08 +01:00
$logArgCheck = function ($level, $message, $context) {
$this->assertEquals(LogLevel::INFO, $level);
$this->assertArrayHasKey('level', $context);
$this->assertEquals(E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED, $context['level']);
$this->assertArrayHasKey('stack', $context);
};
$logger = $this->getMock('Psr\Log\LoggerInterface');
$logger
->expects($this->once())
->method('log')
->will($this->returnCallback($logArgCheck))
;
$handler = new ErrorHandler();
$handler->setDefaultLogger($logger);
@$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, array());
}
2014-05-26 11:29:25 +01:00
public function testHandleException()
{
try {
$handler = ErrorHandler::register();
$exception = new \Exception('foo');
$logger = $this->getMock('Psr\Log\LoggerInterface');
2015-04-02 08:55:37 +01:00
$logArgCheck = function ($level, $message, $context) {
2014-12-03 22:04:33 +00:00
$this->assertEquals('Uncaught Exception: foo', $message);
$this->assertArrayHasKey('type', $context);
$this->assertEquals($context['type'], E_ERROR);
2014-05-26 11:29:25 +01:00
};
$logger
->expects($this->exactly(2))
->method('log')
->will($this->returnCallback($logArgCheck))
;
$handler->setDefaultLogger($logger, E_ERROR);
try {
$handler->handleException($exception);
$this->fail('Exception expected');
} catch (\Exception $e) {
$this->assertSame($exception, $e);
}
2014-12-03 22:04:33 +00:00
$handler->setExceptionHandler(function ($e) use ($exception) {
$this->assertSame($exception, $e);
2014-05-26 11:29:25 +01:00
});
$handler->handleException($exception);
restore_error_handler();
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
restore_exception_handler();
throw $e;
}
}
public function testErrorStacking()
{
try {
$handler = ErrorHandler::register();
$handler->screamAt(E_USER_WARNING);
$logger = $this->getMock('Psr\Log\LoggerInterface');
$logger
->expects($this->exactly(2))
->method('log')
->withConsecutive(
array($this->equalTo(LogLevel::WARNING), $this->equalTo('Dummy log')),
array($this->equalTo(LogLevel::DEBUG), $this->equalTo('Silenced warning'))
)
;
$handler->setDefaultLogger($logger, array(E_USER_WARNING => LogLevel::WARNING));
ErrorHandler::stackErrors();
@trigger_error('Silenced warning', E_USER_WARNING);
$logger->log(LogLevel::WARNING, 'Dummy log');
ErrorHandler::unstackErrors();
restore_error_handler();
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
restore_exception_handler();
throw $e;
}
}
public function testBootstrappingLogger()
{
$bootLogger = new BufferingLogger();
$handler = new ErrorHandler($bootLogger);
$loggers = array(
E_DEPRECATED => array($bootLogger, LogLevel::INFO),
E_USER_DEPRECATED => array($bootLogger, LogLevel::INFO),
E_NOTICE => array($bootLogger, LogLevel::WARNING),
E_USER_NOTICE => array($bootLogger, LogLevel::WARNING),
E_STRICT => array($bootLogger, LogLevel::WARNING),
E_WARNING => array($bootLogger, LogLevel::WARNING),
E_USER_WARNING => array($bootLogger, LogLevel::WARNING),
E_COMPILE_WARNING => array($bootLogger, LogLevel::WARNING),
E_CORE_WARNING => array($bootLogger, LogLevel::WARNING),
E_USER_ERROR => array($bootLogger, LogLevel::CRITICAL),
E_RECOVERABLE_ERROR => array($bootLogger, LogLevel::CRITICAL),
E_COMPILE_ERROR => array($bootLogger, LogLevel::CRITICAL),
E_PARSE => array($bootLogger, LogLevel::CRITICAL),
E_ERROR => array($bootLogger, LogLevel::CRITICAL),
E_CORE_ERROR => array($bootLogger, LogLevel::CRITICAL),
);
$this->assertSame($loggers, $handler->setLoggers(array()));
$handler->handleError(E_DEPRECATED, 'Foo message', __FILE__, 123, array());
$expectedLog = array(LogLevel::INFO, 'Foo message', array('type' => E_DEPRECATED, 'file' => __FILE__, 'line' => 123, 'level' => error_reporting()));
$logs = $bootLogger->cleanLogs();
unset($logs[0][2]['stack']);
$this->assertSame(array($expectedLog), $logs);
$bootLogger->log($expectedLog[0], $expectedLog[1], $expectedLog[2]);
$mockLogger = $this->getMock('Psr\Log\LoggerInterface');
$mockLogger->expects($this->once())
->method('log')
->with(LogLevel::WARNING, 'Foo message', $expectedLog[2]);
$handler->setLoggers(array(E_DEPRECATED => array($mockLogger, LogLevel::WARNING)));
}
2014-05-26 11:29:25 +01:00
public function testHandleFatalError()
{
try {
$handler = ErrorHandler::register();
$error = array(
'type' => E_PARSE,
'message' => 'foo',
'file' => 'bar',
'line' => 123,
);
$logger = $this->getMock('Psr\Log\LoggerInterface');
2014-12-03 22:04:33 +00:00
$logArgCheck = function ($level, $message, $context) {
$this->assertEquals('Fatal Parse Error: foo', $message);
$this->assertArrayHasKey('type', $context);
Merge branch '2.8' * 2.8: (77 commits) [travis] Use container-based infrastructure [HttpKernel] use ConfigCache::getPath() method when it exists [PropertyAccess] Fix setting public property on a class having a magic getter [Routing] Display file which contain deprecated option ContainerInterface: unused exception dropped bumped Symfony version to 2.6.8 updated VERSION for 2.6.7 updated CHANGELOG for 2.6.7 bumped Symfony version to 2.3.29 updated VERSION for 2.3.28 update CONTRIBUTORS for 2.3.28 updated CHANGELOG for 2.3.28 [Debug] Fixed ClassNotFoundFatalErrorHandlerTest [SecurityBundle] use access decision constants in config [SecurityBundle] use session auth constants in config PhpDoc fix in AbstractRememberMeServices [FrameworkBundle][DX] Add option to specify additional translation loading paths [Filesystem] Simplified an if statement fixed CS [SecurityBundle] Use Enum Nodes Instead Of Scalar ... Conflicts: CHANGELOG-2.3.md CHANGELOG-2.6.md src/Symfony/Bridge/Swiftmailer/composer.json src/Symfony/Bundle/DebugBundle/composer.json src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.txt src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.txt src/Symfony/Component/Debug/DebugClassLoader.php src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php src/Symfony/Component/Form/README.md src/Symfony/Component/Intl/README.md src/Symfony/Component/Locale/composer.json src/Symfony/Component/Routing/Loader/XmlFileLoader.php src/Symfony/Component/Routing/Loader/YamlFileLoader.php src/Symfony/Component/Security/README.md src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php src/Symfony/Component/Translation/README.md src/Symfony/Component/Validator/README.md src/Symfony/Component/Yaml/Yaml.php
2015-05-12 16:48:43 +01:00
$this->assertEquals($context['type'], E_PARSE);
2014-05-26 11:29:25 +01:00
};
$logger
->expects($this->once())
->method('log')
->will($this->returnCallback($logArgCheck))
;
$handler->setDefaultLogger($logger, E_PARSE);
2014-05-26 11:29:25 +01:00
$handler->handleFatalError($error);
restore_error_handler();
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
restore_exception_handler();
throw $e;
}
}
2015-06-12 22:50:21 +01:00
public function testHandleFatalErrorOnHHVM()
{
try {
$handler = ErrorHandler::register();
$logger = $this->getMock('Psr\Log\LoggerInterface');
$logger
->expects($this->once())
->method('log')
->with(
$this->equalTo(LogLevel::CRITICAL),
2015-06-12 22:50:21 +01:00
$this->equalTo('Fatal Error: foo'),
$this->equalTo(array(
'type' => 1,
'file' => 'bar',
'line' => 123,
'level' => -1,
'stack' => array(456),
))
)
;
$handler->setDefaultLogger($logger, E_ERROR);
$error = array(
'type' => E_ERROR + 0x1000000, // This error level is used by HHVM for fatal errors
'message' => 'foo',
'file' => 'bar',
'line' => 123,
'context' => array(123),
'backtrace' => array(456),
);
call_user_func_array(array($handler, 'handleError'), $error);
$handler->handleFatalError($error);
restore_error_handler();
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
restore_exception_handler();
throw $e;
}
}
2013-12-12 16:06:35 +00:00
}