/**
* @since 1.18
*/
-abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
+abstract class MediaWikiTestCase extends PHPUnit\Framework\TestCase {
use MediaWikiCoversValidator;
CACHE_MEMCACHED => $hashCache,
'apc' => $hashCache,
'apcu' => $hashCache,
- 'xcache' => $hashCache,
'wincache' => $hashCache,
] + $baseConfig->get( 'ObjectCaches' );
}
}
+ private static $schemaOverrideDefaults = [
+ 'scripts' => [],
+ 'create' => [],
+ 'drop' => [],
+ 'alter' => [],
+ ];
+
/**
* Stub. If a test suite needs to test against a specific database schema, it should
* override this method and return the appropriate information from it.
*
- * @return [ $tables, $scripts ] A tuple of two lists, with $tables being a list of tables
- * that will be re-created by the scripts, and $scripts being a list of SQL script
- * files for creating the tables listed.
+ * @param IMaintainableDatabase $db The DB connection to use for the mock schema.
+ * May be used to check the current state of the schema, to determine what
+ * overrides are needed.
+ *
+ * @return array An associative array with the following fields:
+ * - 'scripts': any SQL scripts to run. If empty or not present, schema overrides are skipped.
+ * - 'create': A list of tables created (may or may not exist in the original schema).
+ * - 'drop': A list of tables dropped (expected to be present in the original schema).
+ * - 'alter': A list of tables altered (expected to be present in the original schema).
*/
- protected function getSchemaOverrides() {
- return [ [], [] ];
+ protected function getSchemaOverrides( IMaintainableDatabase $db ) {
+ return [];
+ }
+
+ /**
+ * Undoes the dpecified schema overrides..
+ * Called once per test class, just before addDataOnce().
+ *
+ * @param IMaintainableDatabase $db
+ * @param array $oldOverrides
+ */
+ private function undoSchemaOverrides( IMaintainableDatabase $db, $oldOverrides ) {
+ $this->ensureMockDatabaseConnection( $db );
+
+ $oldOverrides = $oldOverrides + self::$schemaOverrideDefaults;
+ $originalTables = $this->listOriginalTables( $db );
+
+ // Drop tables that need to be restored or removed.
+ $tablesToDrop = array_merge( $oldOverrides['create'], $oldOverrides['alter'] );
+
+ // Restore tables that have been dropped or created or altered,
+ // if they exist in the original schema.
+ $tablesToRestore = array_merge( $tablesToDrop, $oldOverrides['drop'] );
+ $tablesToRestore = array_intersect( $originalTables, $tablesToRestore );
+
+ if ( $tablesToDrop ) {
+ $this->dropMockTables( $db, $tablesToDrop );
+ }
+
+ if ( $tablesToRestore ) {
+ $this->recloneMockTables( $db, $tablesToRestore );
+ }
}
/**
- * Applies any schema changes requested by calling setDbSchema().
+ * Applies the schema overrides returned by getSchemaOverrides(),
+ * after undoing any previously applied schema overrides.
* Called once per test class, just before addDataOnce().
*/
private function setUpSchema( IMaintainableDatabase $db ) {
- list( $tablesToAlter, $scriptsToRun ) = $this->getSchemaOverrides();
+ // Undo any active overrides.
+ $oldOverrides = isset( $db->_schemaOverrides ) ? $db->_schemaOverrides
+ : self::$schemaOverrideDefaults;
+
+ if ( $oldOverrides['alter'] || $oldOverrides['create'] || $oldOverrides['drop'] ) {
+ $this->undoSchemaOverrides( $db, $oldOverrides );
+ }
+
+ // Determine new overrides.
+ $overrides = $this->getSchemaOverrides( $db ) + self::$schemaOverrideDefaults;
+
+ $extraKeys = array_diff(
+ array_keys( $overrides ),
+ array_keys( self::$schemaOverrideDefaults )
+ );
- if ( $tablesToAlter && !$scriptsToRun ) {
+ if ( $extraKeys ) {
throw new InvalidArgumentException(
- 'No scripts supplied for applying the database schema.'
+ 'Schema override contains extra keys: ' . var_export( $extraKeys, true )
);
}
- if ( !$tablesToAlter && $scriptsToRun ) {
+ if ( !$overrides['scripts'] ) {
+ // no scripts to run
+ return;
+ }
+
+ if ( !$overrides['create'] && !$overrides['drop'] && !$overrides['alter'] ) {
throw new InvalidArgumentException(
- 'No tables declared to be altered by schema scripts.'
+ 'Schema override scripts given, but no tables are declared to be '
+ . 'created, dropped or altered.'
);
}
$this->ensureMockDatabaseConnection( $db );
- $previouslyAlteredTables = isset( $db->_alteredMockTables ) ? $db->_alteredMockTables : [];
-
- if ( !$tablesToAlter && !$previouslyAlteredTables ) {
- return; // nothing to do
- }
-
- $tablesToDrop = array_merge( $previouslyAlteredTables, $tablesToAlter );
- $tablesToRestore = array_diff( $previouslyAlteredTables, $tablesToAlter );
+ // Drop the tables that will be created by the schema scripts.
+ $originalTables = $this->listOriginalTables( $db );
+ $tablesToDrop = array_intersect( $originalTables, $overrides['create'] );
if ( $tablesToDrop ) {
$this->dropMockTables( $db, $tablesToDrop );
}
- if ( $tablesToRestore ) {
- $this->recloneMockTables( $db, $tablesToRestore );
- }
-
- foreach ( $scriptsToRun as $script ) {
+ // Run schema override scripts.
+ foreach ( $overrides['scripts'] as $script ) {
$db->sourceFile(
$script,
null,
);
}
- $db->_alteredMockTables = $tablesToAlter;
+ $db->_schemaOverrides = $overrides;
}
private function mungeSchemaUpdateQuery( $cmd ) {
}
}
+ /**
+ * Lists all tables in the live database schema.
+ *
+ * @param IMaintainableDatabase $db
+ * @return array
+ */
+ private function listOriginalTables( IMaintainableDatabase $db ) {
+ if ( !isset( $db->_originalTablePrefix ) ) {
+ throw new LogicException( 'No original table prefix know, cannot list tables!' );
+ }
+
+ $originalTables = $db->listTables( $db->_originalTablePrefix, __METHOD__ );
+ return $originalTables;
+ }
+
/**
* Re-clones the given mock tables to restore them based on the live database schema.
+ * The tables listed in $tables are expected to currently not exist, so dropMockTables()
+ * should be called first.
*
* @param IMaintainableDatabase $db
* @param array $tables
throw new LogicException( 'No original table prefix know, cannot restore tables!' );
}
- $originalTables = $db->listTables( $db->_originalTablePrefix, __METHOD__ );
+ $originalTables = $this->listOriginalTables( $db );
$tables = array_intersect( $tables, $originalTables );
$dbClone = new CloneDatabase( $db, $tables, $db->tablePrefix(), $db->_originalTablePrefix );
*/
private function resetDB( $db, $tablesUsed ) {
if ( $db ) {
- $userTables = [ 'user', 'user_groups', 'user_properties' ];
- $pageTables = [ 'page', 'revision', 'ip_changes', 'revision_comment_temp', 'comment' ];
+ $userTables = [ 'user', 'user_groups', 'user_properties', 'actor' ];
+ $pageTables = [ 'page', 'revision', 'ip_changes', 'revision_comment_temp',
+ 'revision_actor_temp', 'comment' ];
$coreDBDataTables = array_merge( $userTables, $pageTables );
// If any of the user or page tables were marked as used, we should clear all of them.
continue;
}
+ if ( !$db->tableExists( $tbl ) ) {
+ continue;
+ }
+
if ( $truncate ) {
$db->query( 'TRUNCATE TABLE ' . $db->tableName( $tbl ), __METHOD__ );
} else {
* @param string $function
*/
public function hideDeprecated( $function ) {
- MediaWiki\suppressWarnings();
+ Wikimedia\suppressWarnings();
wfDeprecated( $function );
- MediaWiki\restoreWarnings();
+ Wikimedia\restoreWarnings();
}
/**
# This check may also protect against code injection in
# case of broken installations.
- MediaWiki\suppressWarnings();
+ Wikimedia\suppressWarnings();
$haveDiff3 = $wgDiff3 && file_exists( $wgDiff3 );
- MediaWiki\restoreWarnings();
+ Wikimedia\restoreWarnings();
if ( !$haveDiff3 ) {
$this->markTestSkipped( "Skip test, since diff3 is not configured" );