|
20 | 20 | */ |
21 | 21 | class ErrorHandlerTest extends \PHPUnit_Framework_TestCase |
22 | 22 | { |
| 23 | + /** |
| 24 | + * @var int Error reporting level before running tests. |
| 25 | + */ |
| 26 | + protected $errorReporting; |
| 27 | + |
| 28 | + /** |
| 29 | + * @var string Display errors setting before running tests. |
| 30 | + */ |
| 31 | + protected $displayErrors; |
| 32 | + |
| 33 | + public function setUp() { |
| 34 | + $this->errorReporting = error_reporting(E_ALL | E_STRICT); |
| 35 | + $this->displayErrors = ini_get('display_errors'); |
| 36 | + ini_set('display_errors', '1'); |
| 37 | + } |
| 38 | + |
| 39 | + public function tearDown() { |
| 40 | + ini_set('display_errors', $this->displayErrors); |
| 41 | + error_reporting($this->errorReporting); |
| 42 | + } |
| 43 | + |
23 | 44 | public function testCompileTimeError() |
24 | 45 | { |
25 | | - // the ContextErrorException must not be loaded for this test to work |
| 46 | + // the ContextErrorException must not be loaded to test the workaround |
| 47 | + // for https://bugs.php.net/bug.php?id=65322. |
26 | 48 | if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) { |
27 | 49 | $this->markTestSkipped('The ContextErrorException class is already loaded.'); |
28 | 50 | } |
29 | 51 |
|
30 | | - $handler = ErrorHandler::register(E_ALL | E_STRICT); |
31 | | - $displayErrors = ini_get('display_errors'); |
32 | | - ini_set('display_errors', '1'); |
| 52 | + $exceptionHandler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('handle')); |
33 | 53 |
|
34 | | - try { |
35 | | - // trigger compile time error |
36 | | - eval(<<<'PHP' |
| 54 | + // the following code forces some PHPUnit classes to be loaded |
| 55 | + // so that they will be available in the exception handler |
| 56 | + // as they won't be autoloaded by PHP |
| 57 | + class_exists('PHPUnit_Framework_MockObject_Invocation_Object'); |
| 58 | + $this->assertInstanceOf('stdClass', new \stdClass()); |
| 59 | + $this->assertEquals(1, 1); |
| 60 | + $this->assertStringStartsWith('foo', 'foobar'); |
| 61 | + $this->assertArrayHasKey('bar', array('bar' => 'foo')); |
| 62 | + |
| 63 | + $that = $this; |
| 64 | + $exceptionCheck = function ($exception) use ($that) { |
| 65 | + $that->assertInstanceOf('Symfony\Component\Debug\Exception\ContextErrorException', $exception); |
| 66 | + $that->assertEquals(E_STRICT, $exception->getSeverity()); |
| 67 | + $that->assertEquals(2, $exception->getLine()); |
| 68 | + $that->assertStringStartsWith('Runtime Notice: Declaration of _CompileTimeError::foo() should be compatible with', $exception->getMessage()); |
| 69 | + $that->assertArrayHasKey('bar', $exception->getContext()); |
| 70 | + }; |
| 71 | + |
| 72 | + $exceptionHandler->expects($this->once()) |
| 73 | + ->method('handle') |
| 74 | + ->will($this->returnCallback($exceptionCheck)) |
| 75 | + ; |
| 76 | + |
| 77 | + ErrorHandler::register(); |
| 78 | + set_exception_handler(array($exceptionHandler, 'handle')); |
| 79 | + |
| 80 | + // dummy variable to check for in error handler. |
| 81 | + $bar = 123; |
| 82 | + |
| 83 | + // trigger compile time error |
| 84 | + eval(<<<'PHP' |
37 | 85 | class _BaseCompileTimeError { function foo() {} } |
38 | 86 | class _CompileTimeError extends _BaseCompileTimeError { function foo($invalid) {} } |
39 | 87 | PHP |
40 | | - ); |
41 | | - } catch (\Exception $e) { |
42 | | - // if an exception is thrown, the test passed |
43 | | - } |
| 88 | + ); |
44 | 89 |
|
45 | | - ini_set('display_errors', $displayErrors); |
46 | 90 | restore_error_handler(); |
| 91 | + restore_exception_handler(); |
| 92 | + } |
| 93 | + |
| 94 | + public function testNotice() |
| 95 | + { |
| 96 | + $exceptionHandler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('handle')); |
| 97 | + set_exception_handler(array($exceptionHandler, 'handle')); |
| 98 | + |
| 99 | + $that = $this; |
| 100 | + $exceptionCheck = function($exception) use ($that) { |
| 101 | + $that->assertInstanceOf('Symfony\Component\Debug\Exception\ContextErrorException', $exception); |
| 102 | + $that->assertEquals(E_NOTICE, $exception->getSeverity()); |
| 103 | + $that->assertEquals(__LINE__ + 36, $exception->getLine()); |
| 104 | + $that->assertEquals(__FILE__, $exception->getFile()); |
| 105 | + $that->assertRegexp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage()); |
| 106 | + $that->assertArrayHasKey('foobar', $exception->getContext()); |
| 107 | + |
| 108 | + $trace = $exception->getTrace(); |
| 109 | + $that->assertEquals(__FILE__, $trace[0]['file']); |
| 110 | + $that->assertEquals('Symfony\Component\Debug\ErrorHandler', $trace[0]['class']); |
| 111 | + $that->assertEquals('handle', $trace[0]['function']); |
| 112 | + $that->assertEquals('->', $trace[0]['type']); |
| 113 | + |
| 114 | + $that->assertEquals(__FILE__, $trace[1]['file']); |
| 115 | + $that->assertEquals(__CLASS__, $trace[1]['class']); |
| 116 | + $that->assertEquals('triggerNotice', $trace[1]['function']); |
| 117 | + $that->assertEquals('::', $trace[1]['type']); |
| 118 | + |
| 119 | + $that->assertEquals(__CLASS__, $trace[2]['class']); |
| 120 | + $that->assertEquals('testNotice', $trace[2]['function']); |
| 121 | + $that->assertEquals('->', $trace[2]['type']); |
| 122 | + }; |
| 123 | + |
| 124 | + $exceptionHandler->expects($this->exactly(3)) |
| 125 | + ->method('handle') |
| 126 | + ->will($this->returnCallback($exceptionCheck)); |
| 127 | + ErrorHandler::register(); |
| 128 | + |
| 129 | + self::triggerNotice($this); |
| 130 | + |
| 131 | + restore_error_handler(); |
| 132 | + } |
| 133 | + |
| 134 | + // dummy function to test trace in error handler. |
| 135 | + private static function triggerNotice($that) |
| 136 | + { |
| 137 | + // dummy variable to check for in error handler. |
| 138 | + $foobar = 123; |
| 139 | + $that->assertSame('', $foo.$foo.$bar); |
47 | 140 | } |
48 | 141 |
|
49 | 142 | public function testConstruct() |
|
0 commit comments