use PHPUnit\Framework\TestCase;
use Psr\Log\LogLevel;
-use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\BufferingLogger;
-use Symfony\Component\Debug\Exception\ContextErrorException;
+use Symfony\Component\Debug\ErrorHandler;
+use Symfony\Component\Debug\Exception\SilencedErrorContext;
/**
* ErrorHandlerTest.
$newHandler = new ErrorHandler();
- $this->assertSame($newHandler, ErrorHandler::register($newHandler, false));
+ $this->assertSame($handler, ErrorHandler::register($newHandler, false));
$h = set_error_handler('var_dump');
restore_error_handler();
$this->assertSame(array($handler, 'handleError'), $h);
try {
self::triggerNotice($this);
- $this->fail('ContextErrorException expected');
- } catch (ContextErrorException $exception) {
+ $this->fail('ErrorException expected');
+ } catch (\ErrorException $exception) {
// if an exception is thrown, the test passed
- restore_error_handler();
- 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']);
- $this->assertEquals('handleError', $trace[0]['function']);
- $this->assertEquals('->', $trace[0]['type']);
+ $this->assertEquals(__CLASS__, $trace[0]['class']);
+ $this->assertEquals('triggerNotice', $trace[0]['function']);
+ $this->assertEquals('::', $trace[0]['type']);
- $this->assertEquals(__FILE__, $trace[1]['file']);
+ $this->assertEquals(__FILE__, $trace[0]['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) {
+ $this->assertEquals(__FUNCTION__, $trace[1]['function']);
+ $this->assertEquals('->', $trace[1]['type']);
+ } finally {
restore_error_handler();
restore_exception_handler();
-
- throw $e;
}
}
// dummy function to test trace in error handler.
private static function triggerNotice($that)
{
- // dummy variable to check for in error handler.
- $foobar = 123;
$that->assertSame('', $foo.$foo.$bar);
}
$handler = ErrorHandler::register();
$handler->throwAt(3, true);
$this->assertEquals(3 | E_RECOVERABLE_ERROR | E_USER_ERROR, $handler->throwAt(0));
-
+ } finally {
restore_error_handler();
restore_exception_handler();
- } catch (\Exception $e) {
- restore_error_handler();
- restore_exception_handler();
-
- throw $e;
}
}
E_CORE_ERROR => array(null, LogLevel::CRITICAL),
);
$this->assertSame($loggers, $handler->setLoggers(array()));
-
- restore_error_handler();
- restore_exception_handler();
- } catch (\Exception $e) {
+ } finally {
restore_error_handler();
restore_exception_handler();
-
- throw $e;
}
}
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
- $that = $this;
- $warnArgCheck = function ($logLevel, $message, $context) use ($that) {
- $that->assertEquals('info', $logLevel);
- $that->assertEquals('foo', $message);
- $that->assertArrayHasKey('type', $context);
- $that->assertEquals($context['type'], E_USER_DEPRECATED);
- $that->assertArrayHasKey('stack', $context);
- $that->assertInternalType('array', $context['stack']);
+ $warnArgCheck = function ($logLevel, $message, $context) {
+ $this->assertEquals('info', $logLevel);
+ $this->assertEquals('User Deprecated: foo', $message);
+ $this->assertArrayHasKey('exception', $context);
+ $exception = $context['exception'];
+ $this->assertInstanceOf(\ErrorException::class, $exception);
+ $this->assertSame('User Deprecated: foo', $exception->getMessage());
+ $this->assertSame(E_USER_DEPRECATED, $exception->getSeverity());
};
$logger
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
- $that = $this;
- $logArgCheck = function ($level, $message, $context) use ($that) {
- $that->assertEquals('Undefined variable: undefVar', $message);
- $that->assertArrayHasKey('type', $context);
- $that->assertEquals($context['type'], E_NOTICE);
+ $line = null;
+ $logArgCheck = function ($level, $message, $context) use (&$line) {
+ $this->assertEquals('Notice: Undefined variable: undefVar', $message);
+ $this->assertArrayHasKey('exception', $context);
+ $exception = $context['exception'];
+ $this->assertInstanceOf(SilencedErrorContext::class, $exception);
+ $this->assertSame(E_NOTICE, $exception->getSeverity());
+ $this->assertSame(__FILE__, $exception->getFile());
+ $this->assertSame($line, $exception->getLine());
+ $this->assertNotEmpty($exception->getTrace());
+ $this->assertSame(1, $exception->count);
};
$logger
$handler->setDefaultLogger($logger, E_NOTICE);
$handler->screamAt(E_NOTICE);
unset($undefVar);
+ $line = __LINE__ + 1;
@$undefVar++;
restore_error_handler();
}
$this->assertSame($x, $e);
-
- restore_error_handler();
- restore_exception_handler();
- } catch (\Exception $e) {
+ } finally {
restore_error_handler();
restore_exception_handler();
-
- throw $e;
}
}
public function testHandleDeprecation()
{
- $that = $this;
- $logArgCheck = function ($level, $message, $context) use ($that) {
- $that->assertEquals(LogLevel::INFO, $level);
- $that->assertArrayHasKey('level', $context);
- $that->assertEquals(E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED, $context['level']);
- $that->assertArrayHasKey('stack', $context);
+ $logArgCheck = function ($level, $message, $context) {
+ $this->assertEquals(LogLevel::INFO, $level);
+ $this->assertArrayHasKey('exception', $context);
+ $exception = $context['exception'];
+ $this->assertInstanceOf(\ErrorException::class, $exception);
+ $this->assertSame('User Deprecated: Foo deprecation', $exception->getMessage());
};
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
@$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, array());
}
+ /**
+ * @group no-hhvm
+ */
public function testHandleException()
{
try {
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
- $that = $this;
- $logArgCheck = function ($level, $message, $context) use ($that) {
- $that->assertEquals('Uncaught Exception: foo', $message);
- $that->assertArrayHasKey('type', $context);
- $that->assertEquals($context['type'], E_ERROR);
+ $logArgCheck = function ($level, $message, $context) {
+ $this->assertSame('Uncaught Exception: foo', $message);
+ $this->assertArrayHasKey('exception', $context);
+ $this->assertInstanceOf(\Exception::class, $context['exception']);
};
$logger
$this->assertSame($exception, $e);
}
- $that = $this;
- $handler->setExceptionHandler(function ($e) use ($exception, $that) {
- $that->assertSame($exception, $e);
+ $handler->setExceptionHandler(function ($e) use ($exception) {
+ $this->assertSame($exception, $e);
});
$handler->handleException($exception);
-
+ } finally {
restore_error_handler();
restore_exception_handler();
- } catch (\Exception $e) {
- restore_error_handler();
- restore_exception_handler();
-
- throw $e;
}
}
+ /**
+ * @group legacy
+ */
public function testErrorStacking()
{
try {
->method('log')
->withConsecutive(
array($this->equalTo(LogLevel::WARNING), $this->equalTo('Dummy log')),
- array($this->equalTo(LogLevel::DEBUG), $this->equalTo('Silenced warning'))
+ array($this->equalTo(LogLevel::DEBUG), $this->equalTo('User Warning: Silenced warning'))
)
;
@trigger_error('Silenced warning', E_USER_WARNING);
$logger->log(LogLevel::WARNING, 'Dummy log');
ErrorHandler::unstackErrors();
-
+ } finally {
restore_error_handler();
restore_exception_handler();
- } catch (\Exception $e) {
- restore_error_handler();
- restore_exception_handler();
-
- throw $e;
}
}
$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);
+ $this->assertCount(1, $logs);
+ $log = $logs[0];
+ $this->assertSame('info', $log[0]);
+ $this->assertSame('Deprecated: Foo message', $log[1]);
+ $this->assertArrayHasKey('exception', $log[2]);
+ $exception = $log[2]['exception'];
+ $this->assertInstanceOf(\ErrorException::class, $exception);
+ $this->assertSame('Deprecated: Foo message', $exception->getMessage());
+ $this->assertSame(__FILE__, $exception->getFile());
+ $this->assertSame(123, $exception->getLine());
+ $this->assertSame(E_DEPRECATED, $exception->getSeverity());
- $bootLogger->log($expectedLog[0], $expectedLog[1], $expectedLog[2]);
+ $bootLogger->log(LogLevel::WARNING, 'Foo message', array('exception' => $exception));
$mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$mockLogger->expects($this->once())
->method('log')
- ->with(LogLevel::WARNING, 'Foo message', $expectedLog[2]);
+ ->with(LogLevel::WARNING, 'Foo message', array('exception' => $exception));
$handler->setLoggers(array(E_DEPRECATED => array($mockLogger, LogLevel::WARNING)));
}
+ /**
+ * @group no-hhvm
+ */
+ public function testSettingLoggerWhenExceptionIsBuffered()
+ {
+ $bootLogger = new BufferingLogger();
+ $handler = new ErrorHandler($bootLogger);
+
+ $exception = new \Exception('Foo message');
+
+ $mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+ $mockLogger->expects($this->once())
+ ->method('log')
+ ->with(LogLevel::CRITICAL, 'Uncaught Exception: Foo message', array('exception' => $exception));
+
+ $handler->setExceptionHandler(function () use ($handler, $mockLogger) {
+ $handler->setDefaultLogger($mockLogger);
+ });
+
+ $handler->handleException($exception);
+ }
+
+ /**
+ * @group no-hhvm
+ */
public function testHandleFatalError()
{
try {
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
- $that = $this;
- $logArgCheck = function ($level, $message, $context) use ($that) {
- $that->assertEquals('Fatal Parse Error: foo', $message);
- $that->assertArrayHasKey('type', $context);
- $that->assertEquals($context['type'], E_PARSE);
+ $logArgCheck = function ($level, $message, $context) {
+ $this->assertEquals('Fatal Parse Error: foo', $message);
+ $this->assertArrayHasKey('exception', $context);
+ $this->assertInstanceOf(\Exception::class, $context['exception']);
};
$logger
$this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage());
}
+ /**
+ * @group no-hhvm
+ */
public function testHandleFatalErrorOnHHVM()
{
try {
->method('log')
->with(
$this->equalTo(LogLevel::CRITICAL),
- $this->equalTo('Fatal Error: foo'),
- $this->equalTo(array(
- 'type' => 1,
- 'file' => 'bar',
- 'line' => 123,
- 'level' => -1,
- 'stack' => array(456),
- ))
+ $this->equalTo('Fatal Error: foo')
)
;
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;
- }
- }
-
- /**
- * @group legacy
- */
- public function testLegacyInterface()
- {
- try {
- $handler = ErrorHandler::register(0);
- $this->assertFalse($handler->handle(0, 'foo', 'foo.php', 12, array()));
-
- restore_error_handler();
- restore_exception_handler();
-
- $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
-
- $that = $this;
- $logArgCheck = function ($level, $message, $context) use ($that) {
- $that->assertEquals('Undefined variable: undefVar', $message);
- $that->assertArrayHasKey('type', $context);
- $that->assertEquals($context['type'], E_NOTICE);
- };
-
- $logger
- ->expects($this->once())
- ->method('log')
- ->will($this->returnCallback($logArgCheck))
- ;
-
- $handler = ErrorHandler::register(E_NOTICE);
- @$handler->setLogger($logger, 'scream');
- unset($undefVar);
- @$undefVar++;
-
- restore_error_handler();
- restore_exception_handler();
- } catch (\Exception $e) {
+ } finally {
restore_error_handler();
restore_exception_handler();
-
- throw $e;
}
}
}