use Wikimedia\Rdbms\IMaintainableDatabase;
use Wikimedia\Rdbms\Database;
use Wikimedia\TestingAccessWrapper;
+use Wikimedia\Timestamp\ConvertibleTimestamp;
/**
* @since 1.18
global $IP;
parent::setUpBeforeClass();
if ( !file_exists( "$IP/LocalSettings.php" ) ) {
- echo 'A working MediaWiki installation with a configured LocalSettings.php file is'
- . ' required for tests that extend ' . self::class;
+ echo "File \"$IP/LocalSettings.php\" could not be found. "
+ . "Test case " . static::class . " extends " . self::class . " "
+ . "which requires a working MediaWiki installation.\n"
+ . ( new RuntimeException() )->getTraceAsString();
die();
}
self::initializeForStandardPhpunitEntrypointIfNeeded();
$this->tmpFiles = array_merge( $this->tmpFiles, (array)$files );
}
- // @todo Make const when we no longer support HHVM (T192166)
- private static $namespaceAffectingSettings = [
- 'wgAllowImageMoving',
- 'wgCanonicalNamespaceNames',
- 'wgCapitalLinkOverrides',
- 'wgCapitalLinks',
- 'wgContentNamespaces',
- 'wgExtensionMessagesFiles',
- 'wgExtensionNamespaces',
- 'wgExtraNamespaces',
- 'wgExtraSignatureNamespaces',
- 'wgNamespaceContentModels',
- 'wgNamespaceProtection',
- 'wgNamespacesWithSubpages',
- 'wgNonincludableNamespaces',
- 'wgRestrictionLevels',
- ];
+ private static function formatErrorLevel( $errorLevel ) {
+ switch ( gettype( $errorLevel ) ) {
+ case 'integer':
+ return '0x' . strtoupper( dechex( $errorLevel ) );
+ case 'NULL':
+ return 'null';
+ default:
+ throw new MWException( 'Unexpected error level type ' . gettype( $errorLevel ) );
+ }
+ }
protected function tearDown() {
global $wgRequest, $wgSQLMode;
foreach ( $this->iniSettings as $name => $value ) {
ini_set( $name, $value );
}
- if (
- array_intersect( self::$namespaceAffectingSettings, array_keys( $this->mwGlobals ) ) ||
- array_intersect( self::$namespaceAffectingSettings, $this->mwGlobalsToUnset )
- ) {
- $this->resetNamespaces();
- }
$this->mwGlobals = [];
$this->mwGlobalsToUnset = [];
$this->restoreLoggers();
if ( $phpErrorLevel !== $this->phpErrorLevel ) {
ini_set( 'error_reporting', $this->phpErrorLevel );
- $oldHex = strtoupper( dechex( $this->phpErrorLevel ) );
- $newHex = strtoupper( dechex( $phpErrorLevel ) );
+ $oldVal = self::formatErrorLevel( $this->phpErrorLevel );
+ $newVal = self::formatErrorLevel( $phpErrorLevel );
$message = "PHP error_reporting setting was left dirty: "
- . "was 0x$oldHex before test, 0x$newHex after test!";
+ . "was $oldVal before test, $newVal after test!";
$this->fail( $message );
}
+ // If anything faked the time, reset it
+ ConvertibleTimestamp::setFakeTime( false );
+
parent::tearDown();
}
);
if ( $name === 'ContentLanguage' ) {
- $this->doSetMwGlobals( [ 'wgContLang' => $this->localServices->getContentLanguage() ] );
+ $this->setMwGlobals( [ 'wgContLang' => $this->localServices->getContentLanguage() ] );
}
}
* The key is added to the array of globals that will be reset afterwards
* in the tearDown().
*
- * It may be necessary to call resetServices() to allow any changed configuration variables
- * to take effect on services that get initialized based on these variables.
- *
* @par Example
* @code
* protected function setUp() {
* @param mixed|null $value Value to set the global to (ignored
* if an array is given as first argument).
*
- * @note To allow changes to global variables to take effect on global service instances,
- * call resetServices().
+ * @note This will call resetServices().
*
* @since 1.21
*/
$pairs = [ $pairs => $value ];
}
- if ( isset( $pairs['wgContLang'] ) ) {
- throw new MWException(
- 'No setting $wgContLang, use setContentLang() or setService( \'ContentLanguage\' )'
- );
- }
-
- $this->doSetMwGlobals( $pairs, $value );
- }
-
- /**
- * An internal method that allows setService() to set globals that tests are not supposed to
- * touch.
- */
- private function doSetMwGlobals( $pairs, $value = null ) {
$this->doStashMwGlobals( array_keys( $pairs ) );
foreach ( $pairs as $key => $value ) {
$GLOBALS[$key] = $value;
}
- if ( array_intersect( self::$namespaceAffectingSettings, array_keys( $pairs ) ) ) {
- $this->resetNamespaces();
- }
+ $this->resetServices();
}
/**
ini_set( $name, $value );
}
- /**
- * Must be called whenever namespaces are changed, e.g., $wgExtraNamespaces is altered.
- * Otherwise old namespace data will lurk and cause bugs.
- */
- private function resetNamespaces() {
- if ( !$this->localServices ) {
- throw new Exception( __METHOD__ . ' must be called after MediaWikiTestCase::run()' );
- }
-
- if ( $this->localServices !== MediaWikiServices::getInstance() ) {
- throw new Exception( __METHOD__ . ' will not work because the global MediaWikiServices '
- . 'instance has been replaced by test code.' );
- }
-
- Language::clearCaches();
- }
-
/**
* Check if we can back up a value by performing a shallow copy.
* Values which fail this test are copied recursively.
* Useful for setting some entries in a configuration array, instead of
* setting the entire array.
*
- * It may be necessary to call resetServices() to allow any changed configuration variables
- * to take effect on services that get initialized based on these variables.
- *
* @param string $name The name of the global, as in wgFooBar
* @param array $values The array containing the entries to set in that global
*
* @throws MWException If the designated global is not an array.
*
- * @note To allow changes to global variables to take effect on global service instances,
- * call resetServices().
+ * @note This will call resetServices().
*
* @since 1.21
*/
}
self::resetGlobalParser();
+ Language::clearCaches();
}
/**
*/
public function setContentLang( $lang ) {
if ( $lang instanceof Language ) {
- $this->setMwGlobals( 'wgLanguageCode', $lang->getCode() );
// Set to the exact object requested
$this->setService( 'ContentLanguage', $lang );
+ $this->setMwGlobals( 'wgLanguageCode', $lang->getCode() );
} else {
- $this->setMwGlobals( 'wgLanguageCode', $lang );
- // Let the service handler make up the object. Avoid calling setService(), because if
- // we do, overrideMwServices() will complain if it's called later on.
- $services = MediaWikiServices::getInstance();
- $services->resetServiceForTesting( 'ContentLanguage' );
- $this->doSetMwGlobals( [ 'wgContLang' => $services->getContentLanguage() ] );
+ $this->setMwGlobals( [
+ 'wgLanguageCode' => $lang,
+ 'wgContLang' => Language::factory( $lang ),
+ ] );
}
}
* or three values to set a single permission, like
* $this->setGroupPermissions( '*', 'read', false );
*
+ * @note This will call resetServices().
+ *
* @since 1.31
* @param array|string $newPerms Either an array of permissions to change,
* in which case the next two parameters are ignored; or a single string
}
$this->setMwGlobals( 'wgGroupPermissions', $newPermissions );
-
- // Reset services so they pick up the new permissions.
- // Resetting just PermissionManager is not sufficient, since other services may
- // have the old instance of PermissionManager injected.
- $this->resetServices();
}
/**
/**
* Create a temporary hook handler which will be reset by tearDown.
* This replaces other handlers for the same hook.
+ *
+ * @note This will call resetServices().
+ *
* @param string $hookName Hook name
* @param mixed $handler Value suitable for a hook handler
* @since 1.28