Merge "(bug 44459) Ensure jqueryMsg treats plain messages as plain, with tests."
[lhc/web/wiklou.git] / tests / phpunit / MediaWikiTestCase.php
index 99c96f2..dfc5881 100644 (file)
@@ -5,6 +5,20 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        public $regex = '';
        public $runDisabled = false;
 
+       /**
+        * $called tracks whether the setUp and tearDown method has been called.
+        * class extending MediaWikiTestCase usually override setUp and tearDown
+        * but forget to call the parent.
+        *
+        * The array format takes a method name as key and anything as a value.
+        * By asserting the key exist, we know the child class has called the
+        * parent.
+        *
+        * This property must be private, we do not want child to override it,
+        * they should call the appropriate parent method instead.
+        */
+       private $called = array();
+
        /**
         * @var Array of TestUser
         */
@@ -57,13 +71,16 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                $this->backupStaticAttributes = false;
        }
 
-       function run( PHPUnit_Framework_TestResult $result = NULL ) {
+       function run( PHPUnit_Framework_TestResult $result = null ) {
                /* Some functions require some kind of caching, and will end up using the db,
                 * which we can't allow, as that would open a new connection for mysql.
                 * Replace with a HashBag. They would not be going to persist anyway.
                 */
                ObjectCache::$instances[CACHE_DB] = new HashBagOStuff;
 
+               $needsResetDB = false;
+               $logName = get_class( $this ) . '::' . $this->getName( false );
+
                if( $this->needsDB() ) {
                        // set up a DB connection for this test to use
 
@@ -75,22 +92,34 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        $this->checkDbIsSupported();
 
                        if( !self::$dbSetup ) {
+                               wfProfileIn( $logName . ' (clone-db)' );
+
                                // switch to a temporary clone of the database
                                self::setupTestDB( $this->db, $this->dbPrefix() );
 
                                if ( ( $this->db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) {
                                        $this->resetDB();
                                }
+
+                               wfProfileOut( $logName . ' (clone-db)' );
                        }
 
+                       wfProfileIn( $logName . ' (prepare-db)' );
                        $this->addCoreDBData();
                        $this->addDBData();
+                       wfProfileOut( $logName . ' (prepare-db)' );
+
+                       $needsResetDB = true;
+               }
 
-                       parent::run( $result );
+               wfProfileIn( $logName );
+               parent::run( $result );
+               wfProfileOut( $logName );
 
+               if( $needsResetDB ) {
+                       wfProfileIn( $logName . ' (reset-db)' );
                        $this->resetDB();
-               } else {
-                       parent::run( $result );
+                       wfProfileOut( $logName . ' (reset-db)' );
                }
        }
 
@@ -133,7 +162,9 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * happen in reverse order.
         */
        protected function setUp() {
+               wfProfileIn( __METHOD__ );
                parent::setUp();
+               $this->called['setUp'] = 1;
 
                /*
                //@todo: global variables to restore for *every* test
@@ -155,15 +186,22 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        }
                }
 
-               // Clean up open transactions
                if ( $this->needsDB() && $this->db ) {
+                       // Clean up open transactions
                        while( $this->db->trxLevel() > 0 ) {
                                $this->db->rollback();
                        }
+
+                       // don't ignore DB errors
+                       $this->db->ignoreErrors( false );
                }
+
+               wfProfileOut( __METHOD__ );
        }
 
        protected function tearDown() {
+               wfProfileIn( __METHOD__ );
+
                // Cleaning up temporary files
                foreach ( $this->tmpfiles as $fname ) {
                        if ( is_file( $fname ) || ( is_link( $fname ) ) ) {
@@ -173,11 +211,14 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        }
                }
 
-               // Clean up open transactions
                if ( $this->needsDB() && $this->db ) {
+                       // Clean up open transactions
                        while( $this->db->trxLevel() > 0 ) {
                                $this->db->rollback();
                        }
+
+                       // don't ignore DB errors
+                       $this->db->ignoreErrors( false );
                }
 
                // Restore mw globals
@@ -187,6 +228,17 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                $this->mwGlobals = array();
 
                parent::tearDown();
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * Make sure MediaWikiTestCase extending classes have called their
+        * parent setUp method
+        */
+       final public function testMediaWikiTestCaseParentSetupCalled() {
+               $this->assertArrayHasKey( 'setUp', $this->called,
+                       get_called_class() . "::setUp() must call parent::setUp()"
+               );
        }
 
        /**
@@ -313,7 +365,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                                'page_id' => 0,
                                'page_namespace' => 0,
                                'page_title' => ' ',
-                               'page_restrictions' => NULL,
+                               'page_restrictions' => null,
                                'page_counter' => 0,
                                'page_is_redirect' => 0,
                                'page_is_new' => 0,
@@ -461,12 +513,12 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                return $this->assertTrue( $value == '', $msg );
        }
 
-       static private function unprefixTable( $tableName ) {
+       private static function unprefixTable( $tableName ) {
                global $wgDBprefix;
                return substr( $tableName, strlen( $wgDBprefix ) );
        }
 
-       static private function isNotUnittest( $table ) {
+       private static function isNotUnittest( $table ) {
                return strpos( $table, 'unittest_' ) !== 0;
        }
 
@@ -809,4 +861,72 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                        $this->markTestSkipped( "Skip test, since diff3 is not configured" );
                }
        }
+
+       /**
+        * Check whether we have the 'gzip' commandline utility, will skip
+        * the test whenever "gzip -V" fails.
+        *
+        * Result is cached at the process level.
+        *
+        * @return bool
+        *
+        * @since 1.21
+        */
+       protected function checkHasGzip() {
+               static $haveGzip;
+
+               if( $haveGzip === null ) {
+                       $retval = null;
+                       wfShellExec( 'gzip -V', $retval );
+                       $haveGzip = ($retval === 0);
+               }
+
+               if( !$haveGzip ) {
+                       $this->markTestSkipped( "Skip test, requires the gzip utility in PATH" );
+               }
+
+               return $haveGzip;
+       }
+
+       /**
+        * Check if $extName is a loaded PHP extension, will skip the
+        * test whenever it is not loaded.
+        *
+        * @since 1.21
+        */
+       protected function checkPHPExtension( $extName ) {
+               $loaded = extension_loaded( $extName );
+               if( ! $loaded ) {
+                       $this->markTestSkipped( "PHP extension '$extName' is not loaded, skipping." );
+               }
+               return $loaded;
+       }
+
+       /**
+        * Asserts that an exception of the specified type occurs when running
+        * the provided code.
+        *
+        * @since 1.21
+        *
+        * @param callable $code
+        * @param string $expected
+        * @param string $message
+        */
+       protected function assertException( $code, $expected = 'Exception', $message = '' ) {
+               $pokemons = null;
+
+               try {
+                       call_user_func( $code );
+               }
+               catch ( Exception $pokemons ) {
+                       // Gotta Catch 'Em All!
+               }
+
+               if ( $message === '' ) {
+                       $message = 'An exception of type "' . $expected . '" should have been thrown';
+               }
+
+               $this->assertInstanceOf( $expected, $pokemons, $message );
+       }
+
 }