‪TYPO3CMS  11.5
ErrorHandlerTest.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Log\LoggerInterface;
21 use Psr\Log\LoggerTrait;
22 use Psr\Log\LogLevel;
28 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
29 
33 class ‪ErrorHandlerTest extends UnitTestCase
34 {
36 
37  protected LoggerInterface ‪$unusedLogger;
38  protected LoggerInterface ‪$trackingLogger;
39 
40  // These are borrowed from DefaultConfiguration.php.
41  protected const ‪DEFAULT_ERROR_HANDLER_LEVELS = E_ALL & ~(E_STRICT | E_NOTICE | E_COMPILE_WARNING | E_COMPILE_ERROR | E_CORE_WARNING | E_CORE_ERROR | E_PARSE | E_ERROR);
42  protected const ‪DEFAULT_EXCEPTIONAL_ERROR_LEVELS = E_ALL & ~(E_STRICT | E_NOTICE | E_COMPILE_WARNING | E_COMPILE_ERROR | E_CORE_WARNING | E_CORE_ERROR | E_PARSE | E_ERROR | E_DEPRECATED | E_USER_DEPRECATED | E_WARNING | E_USER_ERROR | E_USER_NOTICE | E_USER_WARNING);
43 
44  protected ‪$resetSingletonInstances = true;
45 
49  protected function ‪setUp(): void
50  {
51  parent::setUp();
52 
53  $this->trackingLogger = new class () implements LoggerInterface {
54  use LoggerTrait;
55  public array $records = [];
56  public function log($level, $message, array $context = []): void
57  {
58  $this->records[] = [
59  'level' => $level,
60  'message' => $message,
61  'context' => $context,
62  ];
63  }
64  };
65  }
66 
72  int $levelsToHandle,
73  int $levelsToThrow,
74  int $levelToTrigger,
75  string $message,
76  string $file,
77  int $line,
78  ?bool $expectedReturn,
79  ?string $deprecationsLogMessage,
80  ?string $deprecationsLogLevel,
81  ?string $errorsLogMessage,
82  ?string $errorsLogLevel,
83  ?string $exceptionMessage
84  ): void {
85  $logManager = new class () extends ‪LogManager implements ‪LogManagerInterface {
86  protected array $loggers = [];
87  public function getLogger(string $name = ''): LoggerInterface
88  {
89  return $this->loggers[$name];
90  }
91  public function setLogger(string $name, LoggerInterface $logger): self
92  {
93  $this->loggers[$name] = $logger;
94  return $this;
95  }
96  };
97 
98  ‪$subject = new ‪ErrorHandler($levelsToHandle);
99  ‪$subject->‪setExceptionalErrors($levelsToThrow);
100  $logManager->setLogger('TYPO3.CMS.deprecations', clone $this->trackingLogger);
101  // disabled until the new logger is in place
102  // $logManager->setLogger('TYPO3.CMS.php_errors', clone $this->trackingLogger);
103  GeneralUtility::setSingletonInstance(LogManager::class, $logManager);
104 
105  try {
106  $return = ‪$subject->‪handleError($levelToTrigger, $message, $file, $line);
107  } catch (\‪Exception $e) {
108  if ($exceptionMessage) {
109  self::assertEquals($exceptionMessage, $e->getMessage());
110  return;
111  }
112  // An exception happened when it shouldn't; let PHPUnit deal with it.
113  throw $e;
114  }
115  self::assertEquals($expectedReturn, $return);
116  if ($deprecationsLogMessage) {
117  self::assertEquals($deprecationsLogMessage, $logManager->getLogger('TYPO3.CMS.deprecations')->records[0]['message']);
118  self::assertEquals($deprecationsLogLevel, $logManager->getLogger('TYPO3.CMS.deprecations')->records[0]['level']);
119  }
127  }
128 
129  public function ‪errorTests(): iterable
130  {
131  // @todo Clean up the code base so the defaults can change to report notices.
132  yield 'defaults ignore a notice' => [
133  'levelsToHandle' => ‪self::DEFAULT_ERROR_HANDLER_LEVELS,
135  'levelToTrigger' => E_NOTICE,
136  'message' => 'A slightly bad thing happened',
137  'file' => 'foo.php',
138  'line' => 42,
139  'expectedReturn' => ‪ErrorHandlerInterface::ERROR_HANDLED,
140  'deprecationsLogMessage' => null,
141  'deprecationsLogLevel' => null,
142  'errorsLogMessage' => null,
143  'errorsLogLevel' => null,
144  'exceptionMessage' => null,
145  ];
146  yield 'defaults log a warning' => [
147  'levelsToHandle' => ‪self::DEFAULT_ERROR_HANDLER_LEVELS,
149  'levelToTrigger' => E_WARNING,
150  'message' => 'A bad thing happened',
151  'file' => 'foo.php',
152  'line' => 42,
153  'expectedReturn' => ‪ErrorHandlerInterface::ERROR_HANDLED,
154  'deprecationsLogMessage' => null,
155  'deprecationsLogLevel' => LogLevel::NOTICE,
156  'errorsLogMessage' => 'Core: Error handler (BE): PHP Warning: A bad thing happened in foo.php line 42',
157  'errorsLogLevel' => LogLevel::WARNING,
158  'exceptionMessage' => null,
159  ];
160  // @todo Currently Errors are supressed by default. This seems unwise, but changing it is a separate task.
161  /*
162  yield 'defaults log an error' => [
163  'levelsToHandle' => self::DEFAULT_ERROR_HANDLER_LEVELS,
164  'levelsToThrow' => self::DEFAULT_EXCEPTIONAL_ERROR_LEVELS,
165  'levelToTrigger' => E_ERROR,
166  'message' => 'A very bad thing happened',
167  'file' => 'foo.php',
168  'line' => 42,
169  'expectedReturn' => ErrorHandlerInterface::ERROR_HANDLED,
170  'deprecationsLogMessage' => null,
171  'deprecationsLogLevel' => null,
172  'errorsLogMessage' => 'Core: Error handler (BE): PHP Error: A very bad thing happened in foo.php line 42',
173  'errorsLogLevel' => LogLevel::ERROR,
174  'exceptionMessage' => null,
175  ];
176  */
177  yield 'user deprecations are logged' => [
178  'levelsToHandle' => ‪self::DEFAULT_ERROR_HANDLER_LEVELS,
180  'levelToTrigger' => E_USER_DEPRECATED,
181  'message' => 'Stop doing that',
182  'file' => 'foo.php',
183  'line' => 42,
184  'expectedReturn' => ‪ErrorHandlerInterface::ERROR_HANDLED,
185  'deprecationsLogMessage' => 'Core: Error handler (BE): TYPO3 Deprecation Notice: Stop doing that in foo.php line 42',
186  'deprecationsLogLevel' => LogLevel::NOTICE,
187  'errorsLogMessage' => null,
188  'errorsLogLevel' => null,
189  'exceptionMessage' => null,
190  ];
191  // @todo These ought to get logged to the deprecations channel.
192  yield 'system deprecations are logged' => [
193  'levelsToHandle' => ‪self::DEFAULT_ERROR_HANDLER_LEVELS,
195  'levelToTrigger' => E_DEPRECATED,
196  'message' => 'Stop doing that',
197  'file' => 'foo.php',
198  'line' => 42,
199  'expectedReturn' => ‪ErrorHandlerInterface::ERROR_HANDLED,
200  'deprecationsLogMessage' => 'Core: Error handler (BE): PHP Runtime Deprecation Notice: Stop doing that in foo.php line 42',
201  'deprecationsLogLevel' => LogLevel::NOTICE,
202  'errorsLogMessage' => '',
203  'errorsLogLevel' => null,
204  'exceptionMessage' => null,
205  ];
206  yield 'user errors are logged but continue to PHP' => [
207  'levelsToHandle' => ‪self::DEFAULT_ERROR_HANDLER_LEVELS,
209  'levelToTrigger' => E_USER_ERROR,
210  'message' => 'A horrible thing happened',
211  'file' => 'foo.php',
212  'line' => 42,
213  'expectedReturn' => ‪ErrorHandlerInterface::PROPAGATE_ERROR,
214  'deprecationsLogMessage' => null,
215  'deprecationsLogLevel' => null,
216  'errorsLogMessage' => 'Core: Error handler (BE): PHP User Error: A horrible thing happened in foo.php line 42',
217  'errorsLogLevel' => LogLevel::ERROR,
218  'exceptionMessage' => null,
219  ];
220  yield 'can force errors to exceptions' => [
221  'levelsToHandle' => self::DEFAULT_ERROR_HANDLER_LEVELS | E_WARNING,
222  'levelsToThrow' => self::DEFAULT_EXCEPTIONAL_ERROR_LEVELS | E_WARNING,
223  'levelToTrigger' => E_WARNING,
224  'message' => 'A throwable thing happened',
225  'file' => 'foo.php',
226  'line' => 42,
227  'expectedReturn' => null,
228  'deprecationsLogMessage' => null,
229  'deprecationsLogLevel' => null,
230  'errorsLogMessage' => null,
231  'errorsLogLevel' => LogLevel::ERROR,
232  'exceptionMessage' => 'PHP Warning: A throwable thing happened in foo.php line 42',
233  ];
234  }
235 }
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest\errorTests
‪errorTests()
Definition: ErrorHandlerTest.php:129
‪TYPO3\CMS\Core\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Log\LogManagerInterface
Definition: LogManagerInterface.php:24
‪TYPO3\CMS\Core\Error\ErrorHandlerInterface\handleError
‪bool handleError($errorLevel, $errorMessage, $errorFile, $errorLine)
‪TYPO3\CMS\Core\Error\ErrorHandlerInterface\setExceptionalErrors
‪setExceptionalErrors($exceptionalErrors)
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest\DEFAULT_ERROR_HANDLER_LEVELS
‪const DEFAULT_ERROR_HANDLER_LEVELS
Definition: ErrorHandlerTest.php:41
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest\$trackingLogger
‪LoggerInterface $trackingLogger
Definition: ErrorHandlerTest.php:38
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest
Definition: ErrorHandlerTest.php:34
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest\setUp
‪setUp()
Definition: ErrorHandlerTest.php:49
‪TYPO3\CMS\Core\Error\ErrorHandlerInterface\PROPAGATE_ERROR
‪const PROPAGATE_ERROR
Definition: ErrorHandlerInterface.php:27
‪TYPO3\CMS\Core\Tests\Unit\Error
Definition: DebugExceptionHandlerTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest\errorHandlerLogsCorrectly
‪errorHandlerLogsCorrectly(int $levelsToHandle, int $levelsToThrow, int $levelToTrigger, string $message, string $file, int $line, ?bool $expectedReturn, ?string $deprecationsLogMessage, ?string $deprecationsLogLevel, ?string $errorsLogMessage, ?string $errorsLogLevel, ?string $exceptionMessage)
Definition: ErrorHandlerTest.php:71
‪TYPO3\CMS\Core\Error\ErrorHandlerInterface
Definition: ErrorHandlerInterface.php:24
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest\DEFAULT_EXCEPTIONAL_ERROR_LEVELS
‪const DEFAULT_EXCEPTIONAL_ERROR_LEVELS
Definition: ErrorHandlerTest.php:42
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest\$unusedLogger
‪LoggerInterface $unusedLogger
Definition: ErrorHandlerTest.php:37
‪TYPO3\CMS\Core\Error\ErrorHandlerInterface\ERROR_HANDLED
‪const ERROR_HANDLED
Definition: ErrorHandlerInterface.php:26
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest\$resetSingletonInstances
‪$resetSingletonInstances
Definition: ErrorHandlerTest.php:44
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:33
‪TYPO3\CMS\Core\Tests\Unit\Error\ErrorHandlerTest\$subject
‪ErrorHandlerInterface $subject
Definition: ErrorHandlerTest.php:35
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:50
‪TYPO3\CMS\Core\Error\ErrorHandler
Definition: ErrorHandler.php:40