* Reset global services, and install testing environment.
* This is the testing equivalent of MediaWikiServices::resetGlobalInstance().
* This should only be used to set up the testing environment, not when
- * runnnig unit tests. Use overrideMwServices() for that.
+ * running unit tests. Use overrideMwServices() for that.
*
* @see MediaWikiServices::resetGlobalInstance()
* @see prepareServices()
/**
* Create a config suitable for testing, based on a base config, default overrides,
- * and custom overrdies.
+ * and custom overrides.
*
* @param Config|null $baseConfig
* @param Config|null $customOverrides
$defaultOverrides->set( 'ObjectCaches', $objectCaches );
$defaultOverrides->set( 'MainCacheType', CACHE_NONE );
+ // Use a fast hash algorithm to hash passwords.
+ $defaultOverrides->set( 'PasswordDefault', 'A' );
+
$testConfig = $customOverrides
? new MultiConfig( [ $customOverrides, $defaultOverrides, $baseConfig ] )
: new MultiConfig( [ $defaultOverrides, $baseConfig ] );
/**
* @param ConfigFactory $oldFactory
- * @param Config[] $config
+ * @param Config[] $configurations
*
* @return Closure
*/
private function doLightweightServiceReset() {
global $wgRequest;
- $services = MediaWikiServices::getInstance();
-
JobQueueGroup::destroySingletons();
ObjectCache::clear();
FileBackendGroup::destroySingleton();
}
$wgRequest = new FauxRequest();
MediaWiki\Session\SessionManager::resetCache();
+ MediaWiki\Auth\AuthManager::resetCache();
$phpErrorLevel = intval( ini_get( 'error_reporting' ) );
* Sets a service, maintaining a stashed version of the previous service to be
* restored in tearDown
*
+ * @since 1.27
+ *
* @param string $name
* @param object $object
*/
}
}
+ /**
+ * Check if we can back up a value by performing a shallow copy.
+ * Values which fail this test are copied recursively.
+ *
+ * @param mixed $value
+ * @return bool True if a shallow copy will do; false if a deep copy
+ * is required.
+ */
+ private static function canShallowCopy( $value ) {
+ if ( is_scalar( $value ) || $value === null ) {
+ return true;
+ }
+ if ( is_array( $value ) ) {
+ foreach ( $value as $subValue ) {
+ if ( !is_scalar( $subValue ) && $subValue !== null ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
/**
* Stashes the global, will be restored in tearDown()
*
// NOTE: we serialize then unserialize the value in case it is an object
// this stops any objects being passed by reference. We could use clone
// and if is_object but this does account for objects within objects!
- try {
- $this->mwGlobals[$globalKey] = unserialize( serialize( $GLOBALS[$globalKey] ) );
- }
- // NOTE; some things such as Closures are not serializable
- // in this case just set the value!
- catch ( Exception $e ) {
+ if ( self::canShallowCopy( $GLOBALS[$globalKey] ) ) {
$this->mwGlobals[$globalKey] = $GLOBALS[$globalKey];
+ } elseif (
+ // Many MediaWiki types are safe to clone. These are the
+ // ones that are most commonly stashed.
+ $GLOBALS[$globalKey] instanceof Language ||
+ $GLOBALS[$globalKey] instanceof User ||
+ $GLOBALS[$globalKey] instanceof FauxRequest
+ ) {
+ $this->mwGlobals[$globalKey] = clone $GLOBALS[$globalKey];
+ } else {
+ try {
+ $this->mwGlobals[$globalKey] = unserialize( serialize( $GLOBALS[$globalKey] ) );
+ } catch ( Exception $e ) {
+ $this->mwGlobals[$globalKey] = $GLOBALS[$globalKey];
+ }
}
}
}
if ( $user->idForName() == 0 ) {
$user->addToDatabase();
TestUser::setPasswordForUser( $user, 'UTSysopPassword' );
+ $user->addGroup( 'sysop' );
+ $user->addGroup( 'bureaucrat' );
}
- // Always set groups, because $this->resetDB() wipes them out
- $user->addGroup( 'sysop' );
- $user->addGroup( 'bureaucrat' );
-
// Make 1 page with 1 revision
$page = WikiPage::factory( Title::newFromText( 'UTPage' ) );
if ( $page->getId() == 0 ) {
*/
private function resetDB( $db, $tablesUsed ) {
if ( $db ) {
+ $userTables = [ 'user', 'user_groups', 'user_properties' ];
+ $coreDBDataTables = array_merge( $userTables, [ 'page', 'revision' ] );
+
+ // If any of the user tables were marked as used, we should clear all of them.
+ if ( array_intersect( $tablesUsed, $userTables ) ) {
+ $tablesUsed = array_unique( array_merge( $tablesUsed, $userTables ) );
+
+ // Totally clear User class in-process cache to avoid CAS errors
+ TestingAccessWrapper::newFromClass( 'User' )
+ ->getInProcessCache()
+ ->clear();
+ }
+
$truncate = in_array( $db->getType(), [ 'oracle', 'mysql' ] );
foreach ( $tablesUsed as $tbl ) {
- // TODO: reset interwiki and user tables to their original content.
- if ( $tbl == 'interwiki' || $tbl == 'user' ) {
+ // TODO: reset interwiki table to its original content.
+ if ( $tbl == 'interwiki' ) {
continue;
}
if ( $truncate ) {
$db->query( 'TRUNCATE TABLE ' . $db->tableName( $tbl ), __METHOD__ );
} else {
-
$db->delete( $tbl, '*', __METHOD__ );
}
LinkCache::singleton()->clear();
}
}
+
+ if ( array_intersect( $tablesUsed, $coreDBDataTables ) ) {
+ // Re-add core DB data that was deleted
+ $this->addCoreDBData();
+ }
}
}