3 use MediaWiki\Auth\LocalPasswordPrimaryAuthenticationProvider
;
4 use MediaWiki\Auth\TemporaryPasswordPrimaryAuthenticationProvider
;
5 use MediaWiki\Logger\LegacySpi
;
6 use MediaWiki\MediaWikiServices
;
7 use MediaWiki\Registration\ExtensionRegistry
;
8 use MediaWiki\Session\CookieSessionProvider
;
11 * Common code for test environment initialisation and teardown
15 public static $bootstrapGlobals;
18 * For use in MediaWikiUnitTestCase.
20 * This should be called before default settings are applied or Setup.php loads.
22 public static function snapshotGlobals() {
23 self
::$bootstrapGlobals = [];
24 foreach ( $GLOBALS as $key => $_ ) {
25 // Support: HHVM (avoid self-ref)
26 if ( $key !== 'GLOBALS' ) {
27 self
::$bootstrapGlobals[ $key ] =& $GLOBALS[$key];
33 * Overrides config settings for testing.
34 * This should be called after loading local settings, typically from the finalSetup() method
35 * of a Maintenance subclass which then gets called via MW_SETUP_CALLBACK in Setup.php.
37 public static function applyInitialConfig() {
38 global $wgScriptPath, $wgScript, $wgResourceBasePath, $wgStylePath, $wgExtensionAssetsPath;
39 global $wgArticlePath, $wgActionPaths, $wgVariantArticlePath, $wgUploadNavigationUrl;
40 global $wgMainCacheType, $wgMessageCacheType, $wgParserCacheType, $wgSessionCacheType;
42 global $wgLanguageConverterCacheType, $wgUseDatabaseMessages;
43 global $wgLocaltimezone, $wgLocalTZoffset, $wgLocalisationCacheConf;
45 global $wgDevelopmentWarnings;
46 global $wgSessionProviders, $wgSessionPbkdf2Iterations;
47 global $wgJobTypeConf;
48 global $wgMWLoggerDefaultSpi;
49 global $wgAuthManagerConfig;
50 global $wgShowExceptionDetails, $wgShowHostnames;
51 global $wgDBStrictWarnings, $wgUsePigLatinVariant;
52 global $wgOpenTelemetryConfig;
54 $wgShowExceptionDetails = true;
55 $wgShowHostnames = true;
57 // wfWarn should cause tests to fail
58 $wgDevelopmentWarnings = true;
59 $wgDBStrictWarnings = true;
63 $wgScript = '/index.php';
64 $wgResourceBasePath = '';
65 $wgStylePath = '/skins';
66 $wgExtensionAssetsPath = '/extensions';
67 $wgArticlePath = '/wiki/$1';
69 $wgVariantArticlePath = false;
70 $wgUploadNavigationUrl = false;
72 // Make sure all caches and stashes are either disabled or use
73 // in-process cache only to prevent tests from using any preconfigured
74 // cache meant for the local wiki from outside the test run.
75 // See also MediaWikiIntegrationTestCase::run() which mocks CACHE_DB and APC.
77 // Disabled by default in MainConfigSchema, override local settings
78 $wgMainCacheType = CACHE_NONE
;
79 // Uses CACHE_ANYTHING by default in MainConfigSchema, use hash instead of db
83 $wgLanguageConverterCacheType = 'hash';
84 // Uses db-replicated by default in MainConfigSchema
85 $wgMainStash = 'hash';
86 // Use memory job queue
88 'default' => [ 'class' => JobQueueMemory
::class, 'order' => 'fifo' ],
90 // Always default to LegacySpi and LegacyLogger during test
91 // See also MediaWikiIntegrationTestCase::setNullLogger().
92 // Note that MediaWikiLoggerPHPUnitTestListener may wrap this in
93 // a MediaWiki\Logger\LogCapturingSpi at run-time.
94 $wgMWLoggerDefaultSpi = [
95 'class' => LegacySpi
::class,
98 $wgUseDatabaseMessages = false; # Set for future resets
100 // Assume UTC for testing purposes
101 $wgLocaltimezone = 'UTC';
102 $wgLocalTZoffset = 0;
104 $wgLocalisationCacheConf['class'] = TestLocalisationCache
::class;
105 $wgLocalisationCacheConf['storeClass'] = LCStoreNull
::class;
107 // Do not bother updating search tables
108 $wgSearchType = SearchEngineDummy
::class;
110 // Generic MediaWiki\Session\SessionManager configuration for tests
111 // We use CookieSessionProvider because things might be expecting
112 // cookies to show up in a MediaWiki\Request\FauxRequest somewhere.
113 $wgSessionProviders = [
115 'class' => CookieSessionProvider
::class,
122 // Single-iteration PBKDF2 session secret derivation, for speed.
123 $wgSessionPbkdf2Iterations = 1;
125 // Generic AuthManager configuration for testing
126 $wgAuthManagerConfig = [
130 'class' => TemporaryPasswordPrimaryAuthenticationProvider
::class,
132 'DBLoadBalancerFactory',
136 'authoritative' => false,
140 'class' => LocalPasswordPrimaryAuthenticationProvider
::class,
142 'DBLoadBalancerFactory',
145 'authoritative' => true,
149 'secondaryauth' => [],
152 // This is often used for variant testing
153 $wgUsePigLatinVariant = true;
155 // Disable tracing in tests.
156 $wgOpenTelemetryConfig = null;
158 // xdebug's default of 100 is too low for MediaWiki
159 ini_set( 'xdebug.max_nesting_level', 1000 );
161 // Make sure that serialize_precision is set to its default value
162 // so floating-point numbers within serialized or JSON-encoded data
163 // will match the expected string representations (T116683).
164 ini_set( 'serialize_precision', -1 );
168 * @internal Should only be used in bootstrap.php and boostrap.maintenance.php
170 * PHPUnit includes the bootstrap file inside a method body, while most MediaWiki startup files
171 * assume to be included in the global scope.
172 * This utility provides a way to include these files: it makes all globals available in the
173 * inclusion scope before including the file, then exports all new or changed globals.
175 * @param string $fileName the file to include
177 public static function requireOnceInGlobalScope( string $fileName ): void
{
180 'originalGlobalsMap' => true,
184 'wgAutoloadClasses' => true,
187 // Import $GLOBALS into local scope for the file.
188 // Modifications to these from the required file automatically affect the real global.
189 foreach ( $GLOBALS as $key => $_ ) {
190 $ignore[$key] = true;
191 // phpcs:ignore MediaWiki.VariableAnalysis.UnusedGlobalVariables,MediaWiki.NamingConventions.ValidGlobalName.allowedPrefix
195 // Setup.php creates this variable, but we cannot wait for the below code to make it global,
196 // because Setup.php (and MW_SETUP_CALLBACK -> TestsAutoLoader.php) needs this to be a
197 // global during its execution (not just after).
198 // phpcs:ignore MediaWiki.VariableAnalysis.UnusedGlobalVariables
199 global $wgAutoloadClasses;
201 require_once $fileName;
203 // Create any new variables as actual globals.
204 foreach ( get_defined_vars() as $varName => $value ) {
205 // Skip our own internal variables, and variables that were already global.
206 if ( array_key_exists( $varName, $ignore ) ) {
209 $GLOBALS[$varName] = $value;
214 * Verifies that the composer.lock file is up-to-date, unless this check is disabled.
216 public static function maybeCheckComposerLockUpToDate(): void
{
217 if ( !getenv( 'MW_SKIP_EXTERNAL_DEPENDENCIES' ) ) {
218 $composerLockUpToDate = new CheckComposerLockUpToDate();
219 $composerLockUpToDate->loadParamsAndArgs( 'phpunit', [ 'quiet' => true ] );
220 $composerLockUpToDate->execute();
224 public static function loadSettingsFiles(): void
{
225 // phpcs:ignore MediaWiki.Usage.ForbiddenFunctions.define
226 define( 'MW_SETUP_CALLBACK', [ self
::class, 'setupCallback' ] );
227 self
::requireOnceInGlobalScope( MW_INSTALL_PATH
. "/includes/Setup.php" );
231 * @internal Should only be used in self::loadSettingsFiles
233 public static function setupCallback() {
234 global $wgDBadminuser, $wgDBadminpassword;
235 global $wgDBuser, $wgDBpassword, $wgDBservers, $wgLBFactoryConf;
237 // These are already set in the PHPUnit config, but set them again in case they were changed in a settings file
238 ini_set( 'memory_limit', '-1' );
239 ini_set( 'max_execution_time', '0' );
241 if ( $wgDBadminuser !== null ) {
242 $wgDBuser = $wgDBadminuser;
243 $wgDBpassword = $wgDBadminpassword;
245 if ( $wgDBservers ) {
247 * @var array $wgDBservers
249 foreach ( $wgDBservers as $i => $server ) {
250 $wgDBservers[$i]['user'] = $wgDBuser;
251 $wgDBservers[$i]['password'] = $wgDBpassword;
254 if ( isset( $wgLBFactoryConf['serverTemplate'] ) ) {
255 $wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser;
256 $wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword;
258 $service = MediaWikiServices
::getInstance()->peekService( 'DBLoadBalancerFactory' );
264 self
::requireOnceInGlobalScope( __DIR__
. '/TestsAutoLoader.php' );
266 self
::applyInitialConfig();
268 ExtensionRegistry
::getInstance()->setLoadTestClassesAndNamespaces( true );