3 use MediaWiki\Api\ApiFormatXml
;
4 use MediaWiki\Api\ApiResult
;
5 use MediaWiki\Context\RequestContext
;
6 use MediaWiki\Debug\MWDebug
;
7 use MediaWiki\Logger\LoggerFactory
;
8 use MediaWiki\MainConfigNames
;
9 use MediaWiki\Request\FauxRequest
;
10 use MediaWiki\Title\TitleValue
;
11 use Psr\Log\LoggerInterface
;
14 * @covers \MediaWiki\Debug\MWDebug
16 class MWDebugTest
extends MediaWikiIntegrationTestCase
{
18 protected function setUp(): void
{
19 $this->overrideConfigValue( MainConfigNames
::DevelopmentWarnings
, false );
22 /** Clear log before each test */
26 public static function setUpBeforeClass(): void
{
27 parent
::setUpBeforeClass();
31 public static function tearDownAfterClass(): void
{
33 parent
::tearDownAfterClass();
36 public function testLog() {
37 @MWDebug
::log( 'logging a string' );
40 'msg' => 'logging a string',
42 'caller' => 'MWDebugTest->testLog',
48 public function testWarningProduction() {
49 $logger = $this->createMock( LoggerInterface
::class );
50 $logger->expects( $this->once() )->method( 'info' );
51 $this->setLogger( 'warning', $logger );
53 @MWDebug
::warning( 'Ohnosecond!' );
56 public function testWarningDevelopment() {
57 $this->overrideConfigValue( MainConfigNames
::DevelopmentWarnings
, true );
59 $this->expectPHPError(
62 MWDebug
::warning( 'Ohnosecond!' );
69 * Message from the error channel are copied to the debug toolbar "Console" log.
71 * This normally happens via wfDeprecated -> MWDebug::deprecated -> trigger_error
72 * -> MWExceptionHandler -> LoggerFactory -> LegacyLogger -> MWDebug::debugMsg.
74 * The above test asserts up until trigger_error.
75 * This test asserts from LegacyLogger down.
77 public function testMessagesFromErrorChannel() {
78 // Turn off to keep mw-error.log file empty in CI (and thus avoid build failure)
79 $this->overrideConfigValue( MainConfigNames
::DebugLogGroups
, [] );
81 MWExceptionHandler
::handleError( E_USER_DEPRECATED
, 'Warning message' );
84 'msg' => 'PHP Deprecated: Warning message',
86 'caller' => 'MWDebugTest::testMessagesFromErrorChannel',
92 public function testDetectDeprecatedOverride() {
93 $baseclassInstance = new TitleValue( NS_MAIN
, 'Test' );
96 MWDebug
::detectDeprecatedOverride(
104 // create a dummy subclass that overrides a method
105 $subclassInstance = new class ( NS_MAIN
, 'Test' ) extends TitleValue
{
106 public function getNamespace(): int {
112 $this->expectPHPError(
114 static function () use ( $subclassInstance ) {
115 MWDebug
::detectDeprecatedOverride(
126 public function testDeprecated() {
127 $this->expectPHPError(
130 MWDebug
::deprecated( 'wfOldFunction', '1.0', 'component' );
137 * @doesNotPerformAssertions
139 public function testDeprecatedIgnoreDuplicate() {
140 @MWDebug
::deprecated( 'wfOldFunction', '1.0', 'component' );
141 MWDebug
::deprecated( 'wfOldFunction', '1.0', 'component' );
143 // If we reach here, than the second one did not throw any deprecation warning.
144 // The first one was silenced to seed the ignore logic.
148 * @doesNotPerformAssertions
150 public function testDeprecatedIgnoreNonConsecutivesDuplicate() {
151 @MWDebug
::deprecated( 'wfOldFunction', '1.0', 'component' );
152 @MWDebug
::warning( 'some warning' );
153 @MWDebug
::log( 'we could have logged something too' );
154 // Another deprecation (not silenced)
155 MWDebug
::deprecated( 'wfOldFunction', '1.0', 'component' );
158 public function testDebugMsg() {
159 $this->overrideConfigValue( MainConfigNames
::ShowDebug
, true );
161 // Generate a log to be sure there is at least one
162 $logger = LoggerFactory
::getInstance( 'test-debug-channel' );
163 $logger->debug( 'My message', [] );
164 $debugLog = (string)MWDebug
::getHTMLDebugLog();
166 $this->assertNotSame( '', $debugLog, 'MWDebug::getHTMLDebugLog() should not be an empty string' );
167 $this->assertStringNotContainsString( "<ul id=\"mw-debug-html\">\n</ul>", $debugLog,
168 'MWDebug::getHTMLDebugLog() should contain a non-empty debug log'
172 public function testAppendDebugInfoToApiResultXmlFormat() {
173 $request = $this->newApiRequest(
174 [ 'action' => 'help', 'format' => 'xml' ],
175 '/api.php?action=help&format=xml'
178 $context = new RequestContext();
179 $context->setRequest( $request );
181 $result = new ApiResult( false );
183 MWDebug
::appendDebugInfoToApiResult( $context, $result );
185 $this->assertInstanceOf( ApiResult
::class, $result );
186 $data = $result->getResultData();
188 $expectedKeys = [ 'mwVersion', 'phpEngine', 'phpVersion', 'gitRevision', 'gitBranch',
189 'gitViewUrl', 'time', 'log', 'debugLog', 'queries', 'request', 'memory',
190 'memoryPeak', 'includes', '_element' ];
192 foreach ( $expectedKeys as $expectedKey ) {
193 $this->assertArrayHasKey( $expectedKey, $data['debuginfo'], "debuginfo has $expectedKey" );
196 $xml = ApiFormatXml
::recXmlPrint( 'help', $data, null );
198 // exception not thrown
199 $this->assertIsString( $xml );
203 * @param string[] $params
204 * @param string $requestUrl
205 * @return FauxRequest
207 private function newApiRequest( array $params, $requestUrl ) {
208 $req = new FauxRequest( $params );
209 $req->setRequestURL( $requestUrl );