Merge "Add MediaWikiTestCase convenience method for mocking a logger"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 12 Feb 2016 00:14:07 +0000 (00:14 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 12 Feb 2016 00:14:07 +0000 (00:14 +0000)
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/tests/MediaWikiTestCaseTest.php

index f69e342..2e1e270 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+use MediaWiki\Logger\LegacySpi;
+use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\Logger\MonologSpi;
+use Psr\Log\LoggerInterface;
 
 /**
  * @since 1.18
@@ -64,6 +68,12 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         */
        private $mwGlobals = array();
 
+       /**
+        * Holds original loggers which have been replaced by setLogger()
+        * @var LoggerInterface[]
+        */
+       private $loggers = array();
+
        /**
         * Table name prefixes. Oracle likes it shorter.
         */
@@ -252,6 +262,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        $GLOBALS[$key] = $value;
                }
                $this->mwGlobals = array();
+               $this->restoreLoggers();
                RequestContext::resetMain();
                MediaHandler::resetCache();
                if ( session_id() !== '' ) {
@@ -404,6 +415,61 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                $this->setMwGlobals( $name, $merged );
        }
 
+       /**
+        * Sets the logger for a specified channel, for the duration of the test.
+        * @since 1.27
+        * @param string $channel
+        * @param LoggerInterface $logger
+        */
+       protected function setLogger( $channel, LoggerInterface $logger ) {
+               $provider = LoggerFactory::getProvider();
+               $wrappedProvider = TestingAccessWrapper::newFromObject( $provider );
+               $singletons = $wrappedProvider->singletons;
+               if ( $provider instanceof MonologSpi ) {
+                       if ( !isset( $this->loggers[$channel] ) ) {
+                               $this->loggers[$channel] = isset( $singletons['loggers'][$channel] )
+                                       ? $singletons['loggers'][$channel] : null;
+                       }
+                       $singletons['loggers'][$channel] = $logger;
+               } elseif ( $provider instanceof LegacySpi ) {
+                       if ( !isset( $this->loggers[$channel] ) ) {
+                               $this->loggers[$channel] = isset( $singletons[$channel] ) ? $singletons[$channel] : null;
+                       }
+                       $singletons[$channel] = $logger;
+               } else {
+                       throw new LogicException( __METHOD__ . ': setting a logger for ' . get_class( $provider )
+                               . ' is not implemented' );
+               }
+               $wrappedProvider->singletons = $singletons;
+       }
+
+       /**
+        * Restores loggers replaced by setLogger().
+        * @since 1.27
+        */
+       private function restoreLoggers() {
+               $provider = LoggerFactory::getProvider();
+               $wrappedProvider = TestingAccessWrapper::newFromObject( $provider );
+               $singletons = $wrappedProvider->singletons;
+               foreach ( $this->loggers as $channel => $logger ) {
+                       if ( $provider instanceof MonologSpi ) {
+                               if ( $logger === null ) {
+                                       unset( $singletons['loggers'][$channel] );
+                               } else {
+                                       $singletons['loggers'][$channel] = $logger;
+                               }
+                       } elseif ( $provider instanceof LegacySpi ) {
+                               if ( $logger === null ) {
+                                       unset( $singletons[$channel] );
+                               } else {
+                                       $singletons[$channel] = $logger;
+                               }
+                       }
+               }
+               $wrappedProvider->singletons = $singletons;
+               $this->loggers = array();
+       }
+
        /**
         * @return string
         * @since 1.18
index 8887499..3361166 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+use MediaWiki\Logger\LoggerFactory;
 
 /**
  * @covers MediaWikiTestCase
@@ -97,4 +98,37 @@ class MediaWikiTestCaseTest extends MediaWikiTestCase {
                $this->stashMwGlobals( self::GLOBAL_KEY_NONEXISTING );
        }
 
+       /**
+        * @covers MediaWikiTestCase::setLogger
+        * @covers MediaWikiTestCase::restoreLogger
+        */
+       public function testLoggersAreRestoredOnTearDown() {
+               // replacing an existing logger
+               $logger1 = LoggerFactory::getInstance( 'foo' );
+               $this->setLogger( 'foo', $this->getMock( '\Psr\Log\LoggerInterface' ) );
+               $logger2 = LoggerFactory::getInstance( 'foo' );
+               $this->tearDown();
+               $logger3 = LoggerFactory::getInstance( 'foo' );
+
+               $this->assertSame( $logger1, $logger3 );
+               $this->assertNotSame( $logger1, $logger2 );
+
+               // replacing a non-existing logger
+               $this->setLogger( 'bar', $this->getMock( '\Psr\Log\LoggerInterface' ) );
+               $logger1 = LoggerFactory::getInstance( 'bar' );
+               $this->tearDown();
+               $logger2 = LoggerFactory::getInstance( 'bar' );
+
+               $this->assertNotSame( $logger1, $logger2 );
+               $this->assertInstanceOf( '\Psr\Log\LoggerInterface', $logger2 );
+
+               // replacing same logger twice
+               $logger1 = LoggerFactory::getInstance( 'baz' );
+               $this->setLogger( 'baz', $this->getMock( '\Psr\Log\LoggerInterface' ) );
+               $this->setLogger( 'baz', $this->getMock( '\Psr\Log\LoggerInterface' ) );
+               $this->tearDown();
+               $logger2 = LoggerFactory::getInstance( 'baz' );
+
+               $this->assertSame( $logger1, $logger2 );
+       }
 }