‪TYPO3CMS  ‪main
DebugExceptionHandlerTest.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 PHPUnit\Framework\Attributes\DataProvider;
21 use PHPUnit\Framework\Attributes\Test;
22 use PHPUnit\Framework\MockObject\MockObject;
23 use Psr\Log\LoggerInterface;
24 use Psr\Log\LoggerTrait;
27 use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
28 
32 final class ‪DebugExceptionHandlerTest extends UnitTestCase
33 {
34  protected ‪DebugExceptionHandler&MockObject ‪$subject;
35 
39  protected function ‪setUp(): void
40  {
41  parent::setUp();
42  $this->subject = $this->getMockBuilder(DebugExceptionHandler::class)
43  ->onlyMethods(['sendStatusHeaders', 'writeLogEntries'])
44  ->disableOriginalConstructor()
45  ->getMock();
46  }
47 
48  protected function ‪tearDown(): void
49  {
50  $previousExceptionHandler = set_exception_handler(function () {});
51  restore_exception_handler();
52  if ($previousExceptionHandler !== null) {
53  // testcase exception handler detected, remove it
54  restore_exception_handler();
55  }
56  parent::tearDown();
57  }
58 
59  #[Test]
61  {
62  $message = '<b>b</b><script>alert(1);</script>';
63  $exception = new \Exception($message, 1476049363);
64  ob_start();
65  $this->subject->echoExceptionWeb($exception);
66  ‪$output = ob_get_contents();
67  ob_end_clean();
68 
69  self::assertStringContainsString(htmlspecialchars($message), ‪$output);
70  self::assertStringNotContainsString($message, ‪$output);
71  }
72 
78  public static function ‪exampleUrlsForTokenAnonymization(): array
79  {
80  return [
81  'url with valid token' => [
82  'http://localhost/typo3/index.php?M=foo&moduleToken=5f1f7d447f22886e8ea206693b0d530ccd6b2b36',
83  'http://localhost/typo3/index.php?M=foo&moduleToken=--AnonymizedToken--',
84  ],
85  'url with valid token and encoded token' => [
86  'http://localhost/typo3/index.php?M=foo&moduleToken=5f1f7d447f22886e8ea206693b0d530ccd6b2b36&returnUrl=%2Ftypo3%2Findex%2Ephp%3FM%3Dfoo%26moduleToken%3D5f1f7d447f22886e8ea206693b0d530ccd6b2b36',
87  'http://localhost/typo3/index.php?M=foo&moduleToken=--AnonymizedToken--&returnUrl=%2Ftypo3%2Findex%2Ephp%3FM%3Dfoo%26moduleToken%3D--AnonymizedToken--',
88  ],
89  'url with valid token in the middle' => [
90  'http://localhost/typo3/index.php?M=foo&moduleToken=5f1f7d447f22886e8ea206693b0d530ccd6b2b36&param=asdf',
91  'http://localhost/typo3/index.php?M=foo&moduleToken=--AnonymizedToken--&param=asdf',
92  ],
93  'url with invalid token' => [
94  'http://localhost/typo3/index.php?M=foo&moduleToken=5f1f7d447f22886e8/e',
95  'http://localhost/typo3/index.php?M=foo&moduleToken=5f1f7d447f22886e8/e',
96  ],
97  'url with empty token' => [
98  'http://localhost/typo3/index.php?M=foo&moduleToken=',
99  'http://localhost/typo3/index.php?M=foo&moduleToken=',
100  ],
101  'url with no token' => [
102  'http://localhost/typo3/index.php?M=foo',
103  'http://localhost/typo3/index.php?M=foo',
104  ],
105  ];
106  }
107 
108  #[DataProvider('exampleUrlsForTokenAnonymization')]
109  #[Test]
110  public function ‪logEntriesContainAnonymousTokens(string $originalUrl, string $expectedUrl): void
111  {
113 
114  $logger = new class () implements LoggerInterface {
115  use LoggerTrait;
116  public array $records = [];
117  public function log($level, string|\Stringable $message, array $context = []): void
118  {
119  $this->records[] = [
120  'level' => $level,
121  'message' => $message,
122  'context' => $context,
123  ];
124  }
125  };
126 
127  ‪$subject->setLogger($logger);
128 
129  GeneralUtility::setIndpEnv('TYPO3_REQUEST_URL', $originalUrl);
130 
131  $exception = new \Exception('message', 1476049367);
132  ob_start();
133  ‪$subject->‪echoExceptionWeb($exception);
134  // output is caught, so it does not pollute the test run
135  ob_end_clean();
136 
137  self::assertEquals('critical', $logger->records[0]['level']);
138  self::assertEquals($expectedUrl, $logger->records[0]['context']['request_url']);
139  }
140 }
‪TYPO3\CMS\Core\Error\DebugExceptionHandler
Definition: DebugExceptionHandler.php:28
‪TYPO3\CMS\Core\Tests\Unit\Error
Definition: DebugExceptionHandlerTest.php:18
‪TYPO3\CMS\Core\Tests\Unit\Error\DebugExceptionHandlerTest\logEntriesContainAnonymousTokens
‪logEntriesContainAnonymousTokens(string $originalUrl, string $expectedUrl)
Definition: DebugExceptionHandlerTest.php:110
‪TYPO3\CMS\Core\Tests\Unit\Error\DebugExceptionHandlerTest\echoExceptionWebEscapesExceptionMessage
‪echoExceptionWebEscapesExceptionMessage()
Definition: DebugExceptionHandlerTest.php:60
‪TYPO3\CMS\Core\Tests\Unit\Error\DebugExceptionHandlerTest
Definition: DebugExceptionHandlerTest.php:33
‪TYPO3\CMS\Core\Tests\Unit\Error\DebugExceptionHandlerTest\exampleUrlsForTokenAnonymization
‪static string[][] exampleUrlsForTokenAnonymization()
Definition: DebugExceptionHandlerTest.php:78
‪$output
‪$output
Definition: annotationChecker.php:114
‪TYPO3\CMS\Core\Tests\Unit\Error\DebugExceptionHandlerTest\setUp
‪setUp()
Definition: DebugExceptionHandlerTest.php:39
‪TYPO3\CMS\Core\Tests\Unit\Error\DebugExceptionHandlerTest\$subject
‪DebugExceptionHandler &MockObject $subject
Definition: DebugExceptionHandlerTest.php:34
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Error\DebugExceptionHandler\echoExceptionWeb
‪echoExceptionWeb(\Throwable $exception)
Definition: DebugExceptionHandler.php:47
‪TYPO3\CMS\Core\Tests\Unit\Error\DebugExceptionHandlerTest\tearDown
‪tearDown()
Definition: DebugExceptionHandlerTest.php:48