From be39c351d47d3b7d57e123f35ddc063ab1678a89 Mon Sep 17 00:00:00 2001 From: daniel Date: Tue, 13 Nov 2012 17:48:15 +0100 Subject: [PATCH] Clean up database cloning for tests. This change makes the operation for overlaying the wiki database with a structurally equivalent test database statically accessible, and adds a function to revert that operation. This is a precondition to logging profiling info to the database after the test run has finished. Change-Id: I2e8335d50eefcc7a97c1cd122b509f0939eacc92 --- tests/phpunit/MediaWikiTestCase.php | 95 +++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/tests/phpunit/MediaWikiTestCase.php b/tests/phpunit/MediaWikiTestCase.php index db41a4d8ab..c619dab805 100644 --- a/tests/phpunit/MediaWikiTestCase.php +++ b/tests/phpunit/MediaWikiTestCase.php @@ -14,12 +14,12 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { * @var DatabaseBase */ protected $db; - protected $oldTablePrefix; - protected $useTemporaryTables = true; - protected $reuseDB = false; protected $tablesUsed = array(); // tables with data + private static $useTemporaryTables = true; + private static $reuseDB = false; private static $dbSetup = false; + private static $oldTablePrefix = false; /** * Holds the paths of temporary files/directories created through getNewTempFile, @@ -65,20 +65,22 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { ObjectCache::$instances[CACHE_DB] = new HashBagOStuff; if( $this->needsDB() ) { - global $wgDBprefix; - - $this->useTemporaryTables = !$this->getCliArg( 'use-normal-tables' ); - $this->reuseDB = $this->getCliArg('reuse-db'); + // set up a DB connection for this test to use + + self::$useTemporaryTables = !$this->getCliArg( 'use-normal-tables' ); + self::$reuseDB = $this->getCliArg('reuse-db'); $this->db = wfGetDB( DB_MASTER ); $this->checkDbIsSupported(); - $this->oldTablePrefix = $wgDBprefix; - if( !self::$dbSetup ) { - $this->initDB(); - self::$dbSetup = true; + // 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(); + } } $this->addCoreDBData(); @@ -349,26 +351,67 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { } } - private function initDB() { + /** + * Restores MediaWiki to using the table set (table prefix) it was using before + * setupTestDB() was called. Useful if we need to perform database operations + * after the test run has finished (such as saving logs or profiling info). + */ + public static function teardownTestDB() { + if ( !self::$dbSetup ) { + return; + } + + CloneDatabase::changePrefix( self::$oldTablePrefix ); + + self::$oldTablePrefix = false; + self::$dbSetup = false; + } + + /** + * Creates an empty skeleton of the wiki database by cloning its structure + * to equivalent tables using the given $prefix. Then sets MediaWiki to + * use the new set of tables (aka schema) instead of the original set. + * + * This is used to generate a dummy table set, typically consisting of temporary + * tables, that will be used by tests instead of the original wiki database tables. + * + * @note: the original table prefix is stored in self::$oldTablePrefix. This is used + * by teardownTestDB() to return the wiki to using the original table set. + * + * @note: this method only works when first called. Subsequent calls have no effect, + * even if using different parameters. + * + * @param DatabaseBase $db The database connection + * @param String $prefix The prefix to use for the new table set (aka schema). + * + * @throws MWException if the database table prefix is already $prefix + */ + public static function setupTestDB( DatabaseBase $db, $prefix ) { global $wgDBprefix; - if ( $wgDBprefix === $this->dbPrefix() ) { - throw new MWException( 'Cannot run unit tests, the database prefix is already "unittest_"' ); + if ( $wgDBprefix === $prefix ) { + throw new MWException( 'Cannot run unit tests, the database prefix is already "' . $prefix . '"' ); } - $tablesCloned = $this->listTables(); - $dbClone = new CloneDatabase( $this->db, $tablesCloned, $this->dbPrefix() ); - $dbClone->useTemporaryTables( $this->useTemporaryTables ); + if ( self::$dbSetup ) { + return; + } - if ( ( $this->db->getType() == 'oracle' || !$this->useTemporaryTables ) && $this->reuseDB ) { - CloneDatabase::changePrefix( $this->dbPrefix() ); - $this->resetDB(); + $tablesCloned = self::listTables( $db ); + $dbClone = new CloneDatabase( $db, $tablesCloned, $prefix ); + $dbClone->useTemporaryTables( self::$useTemporaryTables ); + + self::$dbSetup = true; + self::$oldTablePrefix = $wgDBprefix; + + if ( ( $db->getType() == 'oracle' || !self::$useTemporaryTables ) && self::$reuseDB ) { + CloneDatabase::changePrefix( $prefix ); return; } else { $dbClone->cloneTableStructure(); } - if ( $this->db->getType() == 'oracle' ) { - $this->db->query( 'BEGIN FILL_WIKI_INFO; END;' ); + if ( $db->getType() == 'oracle' ) { + $db->query( 'BEGIN FILL_WIKI_INFO; END;' ); } } @@ -378,7 +421,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { private function resetDB() { if( $this->db ) { if ( $this->db->getType() == 'oracle' ) { - if ( $this->useTemporaryTables ) { + if ( self::$useTemporaryTables ) { wfGetLB()->closeAll(); $this->db = wfGetDB( DB_MASTER ); } else { @@ -427,16 +470,16 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase { return strpos( $table, 'unittest_' ) !== 0; } - protected function listTables() { + public static function listTables( $db ) { global $wgDBprefix; - $tables = $this->db->listTables( $wgDBprefix, __METHOD__ ); + $tables = $db->listTables( $wgDBprefix, __METHOD__ ); $tables = array_map( array( __CLASS__, 'unprefixTable' ), $tables ); // Don't duplicate test tables from the previous fataled run $tables = array_filter( $tables, array( __CLASS__, 'isNotUnittest' ) ); - if ( $this->db->getType() == 'sqlite' ) { + if ( $db->getType() == 'sqlite' ) { $tables = array_flip( $tables ); // these are subtables of searchindex and don't need to be duped/dropped separately unset( $tables['searchindex_content'] ); -- 2.20.1