Merge "Drop cache interwiki"
[mediawiki.git] / tests / phpunit / includes / debug / MWDebugTest.php
bloba55fd39df2162814e8560e1cffea3e826e5edb53
1 <?php
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;
13 /**
14 * @covers \MediaWiki\Debug\MWDebug
16 class MWDebugTest extends MediaWikiIntegrationTestCase {
18 protected function setUp(): void {
19 $this->overrideConfigValue( MainConfigNames::DevelopmentWarnings, false );
21 parent::setUp();
22 /** Clear log before each test */
23 MWDebug::clearLog();
26 public static function setUpBeforeClass(): void {
27 parent::setUpBeforeClass();
28 MWDebug::init();
31 public static function tearDownAfterClass(): void {
32 MWDebug::deinit();
33 parent::tearDownAfterClass();
36 public function testLog() {
37 @MWDebug::log( 'logging a string' );
38 $this->assertEquals(
39 [ [
40 'msg' => 'logging a string',
41 'type' => 'log',
42 'caller' => 'MWDebugTest->testLog',
43 ] ],
44 MWDebug::getLog()
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(
60 E_USER_NOTICE,
61 static function () {
62 MWDebug::warning( 'Ohnosecond!' );
64 'Ohnosecond!'
68 /**
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' );
82 $this->assertEquals(
83 [ [
84 'msg' => 'PHP Deprecated: Warning message',
85 'type' => 'warn',
86 'caller' => 'MWDebugTest::testMessagesFromErrorChannel',
87 ] ],
88 MWDebug::getLog()
92 public function testDetectDeprecatedOverride() {
93 $baseclassInstance = new TitleValue( NS_MAIN, 'Test' );
95 $this->assertFalse(
96 MWDebug::detectDeprecatedOverride(
97 $baseclassInstance,
98 TitleValue::class,
99 'getNamespace',
100 MW_VERSION
104 // create a dummy subclass that overrides a method
105 $subclassInstance = new class ( NS_MAIN, 'Test' ) extends TitleValue {
106 public function getNamespace(): int {
107 // never called
108 return -100;
112 $this->expectPHPError(
113 E_USER_DEPRECATED,
114 static function () use ( $subclassInstance ) {
115 MWDebug::detectDeprecatedOverride(
116 $subclassInstance,
117 TitleValue::class,
118 'getNamespace',
119 MW_VERSION
122 '@anonymous'
126 public function testDeprecated() {
127 $this->expectPHPError(
128 E_USER_DEPRECATED,
129 static function () {
130 MWDebug::deprecated( 'wfOldFunction', '1.0', 'component' );
132 'wfOldFunction'
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 );
210 return $req;