ErrorTrapTest.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  5. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  6. *
  7. * Licensed under The MIT License
  8. * For full copyright and license information, please see the LICENSE.txt
  9. * Redistributions of files must retain the above copyright notice.
  10. *
  11. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  12. * @link https://cakephp.org CakePHP Project
  13. * @since 4.4.0
  14. * @license https://opensource.org/licenses/mit-license.php MIT License
  15. */
  16. namespace Cake\Test\TestCase\Error;
  17. use Cake\Core\Configure;
  18. use Cake\Error\ErrorLogger;
  19. use Cake\Error\ErrorTrap;
  20. use Cake\Error\FatalErrorException;
  21. use Cake\Error\PhpError;
  22. use Cake\Error\Renderer\ConsoleErrorRenderer;
  23. use Cake\Error\Renderer\HtmlErrorRenderer;
  24. use Cake\Error\Renderer\TextErrorRenderer;
  25. use Cake\Log\Log;
  26. use Cake\TestSuite\TestCase;
  27. use InvalidArgumentException;
  28. use stdClass;
  29. class ErrorTrapTest extends TestCase
  30. {
  31. public function setUp(): void
  32. {
  33. parent::setUp();
  34. Log::drop('test_error');
  35. }
  36. public function testConfigRendererInvalid()
  37. {
  38. $trap = new ErrorTrap(['errorRenderer' => stdClass::class]);
  39. $this->expectException(InvalidArgumentException::class);
  40. $trap->renderer();
  41. }
  42. public function testConfigErrorRendererFallback()
  43. {
  44. $trap = new ErrorTrap(['errorRenderer' => null]);
  45. $this->assertInstanceOf(ConsoleErrorRenderer::class, $trap->renderer());
  46. }
  47. public function testConfigErrorRenderer()
  48. {
  49. $trap = new ErrorTrap(['errorRenderer' => HtmlErrorRenderer::class]);
  50. $this->assertInstanceOf(HtmlErrorRenderer::class, $trap->renderer());
  51. }
  52. public function testConfigRendererHandleUnsafeOverwrite()
  53. {
  54. $trap = new ErrorTrap();
  55. $trap->setConfig('errorRenderer', null);
  56. $this->assertInstanceOf(ConsoleErrorRenderer::class, $trap->renderer());
  57. }
  58. public function testLoggerConfigInvalid()
  59. {
  60. $trap = new ErrorTrap(['logger' => stdClass::class]);
  61. $this->expectException(InvalidArgumentException::class);
  62. $trap->logger();
  63. }
  64. public function testLoggerConfig()
  65. {
  66. $trap = new ErrorTrap(['logger' => ErrorLogger::class]);
  67. $this->assertInstanceOf(ErrorLogger::class, $trap->logger());
  68. }
  69. public function testLoggerHandleUnsafeOverwrite()
  70. {
  71. $trap = new ErrorTrap();
  72. $trap->setConfig('logger', null);
  73. $this->assertInstanceOf(ErrorLogger::class, $trap->logger());
  74. }
  75. public function testRegisterAndRendering()
  76. {
  77. $trap = new ErrorTrap(['errorRenderer' => TextErrorRenderer::class]);
  78. $trap->register();
  79. ob_start();
  80. trigger_error('Oh no it was bad', E_USER_NOTICE);
  81. $output = ob_get_clean();
  82. restore_error_handler();
  83. $this->assertStringContainsString('Oh no it was bad', $output);
  84. }
  85. public function testRegisterAndHandleFatalUserError()
  86. {
  87. $trap = new ErrorTrap(['errorRenderer' => TextErrorRenderer::class]);
  88. $trap->register();
  89. try {
  90. trigger_error('Oh no it was bad', E_USER_ERROR);
  91. $this->fail('Should raise a fatal error');
  92. } catch (FatalErrorException $e) {
  93. $this->assertEquals('Oh no it was bad', $e->getMessage());
  94. $this->assertEquals(E_USER_ERROR, $e->getCode());
  95. } finally {
  96. restore_error_handler();
  97. }
  98. }
  99. public function testRegisterAndLogging()
  100. {
  101. Log::setConfig('test_error', [
  102. 'className' => 'Array',
  103. ]);
  104. $trap = new ErrorTrap([
  105. 'errorRenderer' => TextErrorRenderer::class,
  106. ]);
  107. $trap->register();
  108. ob_start();
  109. trigger_error('Oh no it was bad', E_USER_NOTICE);
  110. ob_get_clean();
  111. restore_error_handler();
  112. $logs = Log::engine('test_error')->read();
  113. $this->assertStringContainsString('Oh no it was bad', $logs[0]);
  114. }
  115. public function testRegisterNoOutputDebug()
  116. {
  117. Log::setConfig('test_error', [
  118. 'className' => 'Array',
  119. ]);
  120. Configure::write('debug', false);
  121. $trap = new ErrorTrap(['errorRenderer' => TextErrorRenderer::class]);
  122. $trap->register();
  123. ob_start();
  124. trigger_error('Oh no it was bad', E_USER_NOTICE);
  125. $output = ob_get_clean();
  126. restore_error_handler();
  127. $this->assertSame('', $output);
  128. }
  129. public function testEventTriggered()
  130. {
  131. $trap = new ErrorTrap(['errorRenderer' => TextErrorRenderer::class]);
  132. $trap->register();
  133. $trap->getEventManager()->on('Error.handled', function ($event, PhpError $error) {
  134. $this->assertEquals(E_USER_NOTICE, $error->getCode());
  135. $this->assertStringContainsString('Oh no it was bad', $error->getMessage());
  136. });
  137. ob_start();
  138. trigger_error('Oh no it was bad', E_USER_NOTICE);
  139. $out = ob_get_clean();
  140. restore_error_handler();
  141. $this->assertNotEmpty($out);
  142. }
  143. }