Migrate all callers of Hooks::run() to use the new
HookContainer/HookRunner system.
General principles:
* Use DI if it is already used. We're not changing the way state is
managed in this patch.
* HookContainer is always injected, not HookRunner. HookContainer
is a service, it's a more generic interface, it is the only
thing that provides isRegistered() which is needed in some cases,
and a HookRunner can be efficiently constructed from it
(confirmed by benchmark). Because HookContainer is needed
for object construction, it is also needed by all factories.
* "Ask your friendly local base class". Big hierarchies like
SpecialPage and ApiBase have getHookContainer() and getHookRunner()
methods in the base class, and classes that extend that base class
are not expected to know or care where the base class gets its
HookContainer from.
* ProtectedHookAccessorTrait provides protected getHookContainer() and
getHookRunner() methods, getting them from the global service
container. The point of this is to ease migration to DI by ensuring
that call sites ask their local friendly base class rather than
getting a HookRunner from the service container directly.
* Private $this->hookRunner. In some smaller classes where accessor
methods did not seem warranted, there is a private HookRunner property
which is accessed directly. Very rarely (two cases), there is a
protected property, for consistency with code that conventionally
assumes protected=private, but in cases where the class might actually
be overridden, a protected accessor is preferred over a protected
property.
* The last resort: Hooks::runner(). Mostly for static, file-scope and
global code. In a few cases it was used for objects with broken
construction schemes, out of horror or laziness.
Constructors with new required arguments:
* AuthManager
* BadFileLookup
* BlockManager
* ClassicInterwikiLookup
* ContentHandlerFactory
* ContentSecurityPolicy
* DefaultOptionsManager
* DerivedPageDataUpdater
* FullSearchResultWidget
* HtmlCacheUpdater
* LanguageFactory
* LanguageNameUtils
* LinkRenderer
* LinkRendererFactory
* LocalisationCache
* MagicWordFactory
* MessageCache
* NamespaceInfo
* PageEditStash
* PageHandlerFactory
* PageUpdater
* ParserFactory
* PermissionManager
* RevisionStore
* RevisionStoreFactory
* SearchEngineConfig
* SearchEngineFactory
* SearchFormWidget
* SearchNearMatcher
* SessionBackend
* SpecialPageFactory
* UserNameUtils
* UserOptionsManager
* WatchedItemQueryService
* WatchedItemStore
Constructors with new optional arguments:
* DefaultPreferencesFactory
* Language
* LinkHolderArray
* MovePage
* Parser
* ParserCache
* PasswordReset
* Router
setHookContainer() now required after construction:
* AuthenticationProvider
* ResourceLoaderModule
* SearchEngine
Change-Id: Id442b0dbe43aba84bd5cf801d86dedc768b082c7
The new HookContainer.php introduces a scopedRegister() method for
temporarily setting hooks. Let's use that in MediaWikiUnitTestCase
and MediaWikiIntegrationTestCase instead of directly accessing
global $wgHooks to do so.
Also introduces setTemporaryHook() and removeTemporaryHook()
methods in MWIntegrationTestCase for easily adding/removing of
temporary hooks.
Bug: T250300
Change-Id: I8cefd41b66f882c53646b76de76c51f0d8730f72
This existed on MediaWikiIntegrationTestCase, but not on
MediaWikiUnitTestCase. As a result of that, I spent about four
days tracking down a dangling AtEase::suppressWarnings with
missing AtEase::restoreWarnings (as part of Ib6758d724c).
Move it to the common MediaWikiTestCaseTrait instead so that we
get it on unit/ as well.
Example:
> There was 1 failure:
>
> 1) Pbkdf2PasswordTest::testCryptThrows
> PHP error_reporting setting found dirty.
> Did you forget AtEase::restoreWarnings?
Change-Id: I7dc3fe90385c8066b89a5e06c55f5455edfbb4ca
This converts user options management to a separate
service for use in DI context.
User options are accessed quite early on in installation
process and full-on options management depends on the
database. Prior we have protected from accessing the DB
by setting a hacky $wgUser with 0 id, and relying on the
implementation that it doesn't go into the database to
get the default user options. Now we can't really do that
since DBLoadBalancer is required to instantiate the options
manager. Instead, we redefine the options manager with
a DefaultOptionsManager, that only provides access to
default options and doesn't require DB access.
UserOptionsManager uses PreferencesFactory, however
injecting it will produce a cyclic dependency. The problem
is that we separate options to different kinds, which are
inferred from the PreferencesFactory declaration for those
options (e.g. if it's a radio button in the UI declaration,
the option is of multiselect kind). This is plain wrong,
the dependency should be wise versa. This will be addressed
separately, since it's requires larger refactoring. For now
the PreferencesFactory is obtained on demand. This will be
addressed in a followup.
Bug: T248527
Change-Id: I74917c5eaec184d188911a319895b941ed55ee87
On PHP 7.4 and above, a memory leak can be observed in
ServiceContainer::loadWiringFiles when running PHPUnit tests. This patch aims to
work around the leak by changing
MediaWikiIntegrationTestCase::installMockMwServices to cache and reuse the
original service wirings if no config overrides were supplied. This
significantly reduces the amount of times that the wiring closures need to be
included; on PHP 8, it caused memory usage to drop to 894.25 MB from 4+ GB when
running the PHPUnit tests for MediaWiki core.
However, it seems to be causing some test failures and so it is currently a WIP.
Bug: T247990
Change-Id: I24971221b8accf78d61479d286e907c1111212a0
* Split MWDebug::sendRawDeprecated() from MWDebug::deprecated(). The new
function can be used to send arbitrary messages to the deprecation
log, rather than being constrained by the fixed format of
MWDebug::deprecated().
* Split formatCallerDescription() from sendMessage() to allow the caller
of sendRawDeprecated() to do its own caller formatting.
* Use the new function in MWLBFactory::logDeprecation()
* In tests, replace the ugly implementation of hideDeprecated() with one
that works by setting a list of regexes to filter. hideDeprecated()
now filters deprecation warnings that are a string match to the
supplied function. filterDeprecated() can be used to filter a regex,
and is intended to be used to filter warnings sent via
sendRawDeprecated(). The filter list is reset at the start of each
test, instead of leaking across tests as before.
Change-Id: I0d0df86db2e61cdd1769426bfa7bad4c2ae5e977
Only support passing RevisionRecord or int, remove use of
Revision::newFromId
Bug: T249021
Bug: T249561
Change-Id: Id4a8f64f239d0664865056887fe0a11c7e468d5f
Allow truncation of multiple tables. This also provides for
a way to avoid risky keywords like CASCADE for Postgres.
For Postgres, use RESTART IDENTITY, which has been supported
since Postgres 8.4.
Avoid TRUNCATE/DELETE queries for empty temp tables, which is
useful for integrations tests that frequently call this method.
Reorganize and tweak the regexes in Database::getTempWrites().
It now recognizes multi-table DROP/TRUNCATE (Postgres-style).
Change-Id: Idd49f118b20ea5a0f7a3e8c00369aabcd45dd44e
To disable mail in tests, use setTemporaryHook after the
service container setup, instead of the soon-to-be deprecated
Hooks::register().
Change-Id: I84ea69feb0ebf81855b745c14fdba50d4e121de8
== Motivation
Mute a log channel, for which the Logger object is injected by
service wiring, for a service that is overridden by default,
such as 'DBLoadBalancerFactory'. For that, calling setLogger()
mid-test would be too late.
== Changes
* Add a test-only method to LegacyLogger that makes it possible
to change its `minimumLevel` attribute, thus making it turn
itself into a NullLogger if raised to infinity. This is the
same principle we use already for disabled log channels when
using MediaWiki normally (see LegacyLogger::__construct).
* Previously, the developer's LocalSettings.php was loaded
which includes the Spi configuration. This meant other Spi's
could be configured which means we might not be dealing with
a LegacyLogger object.
Similar to what we do with ObjectCache and JobQueue already,
make the default Spi in tests the same as the normal MW default.
* Add setNullLogger() which makes use of these two.
Bug: T248195
Change-Id: Ieade3585812de47342259afa765e230fff06f526
Use it in MediaWikiIntegrationTestCase for resetting tables.
Also create Database::resetSequencesForTable() helper method from
the resetSequenceForTable() methods in the SQLite/Postgres classes.
Change-Id: I20945e20590e69340b1ce75f6bb2f6972375b00c
Also fix PHPUnit 9 warning in PNGMetadataExtractorTest about $delta.
This should fix all of the integration test warning spam.
Bug: T244095
Change-Id: I0e2a76d5df2685ae5ad1498864e0b5f9db60c0cc
Already soft-deprecated in 726f10b, which also removed the
unused assertTypeOrValue() method without deprecation.
Change-Id: I0d417bf79f03e899dccfa469f639c04d4cf999cf
assertArrayEquals is a generic assertion that does not have anything
to do with integration testing, and is quite useful for isolated
testing of classes which return unordered sets.
Change-Id: I45af77402a1bc922579aff14b21874ec8680e765
*assertType is marked as deprecated, and should ideally be removed soon
(i.e. no hard deprecation to follow)
*Most usages of assertType in core were autofixed by using I8ef556b630812aeea77c5606713f53d9af609f1b
*assertTypeOrValue was removed because only used in SiteTest
(codesearch: https://codesearch.wmflabs.org/search/?q=assertTypeOrValue&i=nope&files=&repos=)
*SiteTest::assertTypeOrFalse was removed because unused
Bug: T192167
Change-Id: Icb3014b8fe7d1c43e64a37e0bdaaffec18bb482f
We've decided to switch to PHPUnit 7 to make things easier. This also
means that we shouldn't suppress PHPUnit 8 warnings, otherwise we cannot
know if tests are already compatible with PHPUnit 8.
Note that the trait is not deleted, because it may still be necessary
for single tests -- we're just not including it by default. However, it
is now deprecated, and its use is discouraged.
Bug: T192167
Change-Id: If90e6b6ffe03dfb117ec2b4b13c79983fe1bd0f2
The class PHPMaintClass is meant to be loaded when running phpunit.php
which is only done when running tests with it. When running tests by
using the bootstrap file only, e.g. in an IDE, this class will not be
available. Relying on it in other classes will therefore break them.
Moving the required parts to another outside class and add it to the
test autoloader. My feeling says, that adding the PHPMaintClass to the
autoloader says "NOOOO", that's why I added a new one.
There also seems to be some CI builds failing because of that:
https://integration.wikimedia.org/ci/hob/quibble-vendor-mysql-php72-docker/30642/console
Bug: T151101
Change-Id: I33e27009657a951173694fc847973560a1ce967b
This is moved out of the main PHPUnit upgrade commit to allow
extensions to silence their warnings beforehand, to avoid breaking
their tests.
Bug: T192167
Change-Id: I60379a933a3a1b018d9f5ef6b51019002389dda3
These were made final in PHPUnit8. Since there seems to be no easy way
to work around that, partially revert
Ibcaf9ca81c8dc63cce6dc6f6fb1fffee19f8804e and start using static
properties again (cfr. T192167#5550034).
Split from Ic14f5debc53e55d67146dc96279d26dfd52b4000.
Bug: T192167
Change-Id: I3fe163738662ae41eb275a0327cb33187290a70f
No repo should be using PHPUnit4 features anymore. Removing this trait
from the test classes is the first step towards the complete removal,
see I84694e32c06f1f0f9fb8398b1f2b92d3df599ddb.
Bug: T192167
Change-Id: I60e66259ea920e84573ae99293b005306876b325
There is no reason this should be necessary. Resetting services should
do the trick, together with Language::$mLangObjCache while it exists.
Resetting only a subset of services is fragile and shouldn't be done,
because one of the reset services might later be injected into a service
that's not reset, resulting in bugs.
Change-Id: I8c72b466ba7337649f9256ee6c078c76163f9785
Otherwise bugs can be caused by services that hold stale service
references. These are very annoying to track down.
Change-Id: Id9e5a8a0fa3493af0855f4bf1816175ecff6136a
These appear to be unused. Moreover, their behavior doesn't match their
documentation. getDefault() claims to return NullLockManager if no lock
manager could be found, but really returns it if there's no lock manager
named 'default'. getAny() claims to throw if no lock manager can be
found, but actually throws if no lock manager is named 'default' or
'fsLockManager'. The behavior can be easily replicated by just using
get() yourself and catching any exception.
Bug: T234227
Change-Id: Iad083847f45d6e017a3f7dbfece1f9c155c5efd6
This a second attempt at 09407afd74, which was reverted due
to breaking Wikibase integration tests.
The original commit had two separate typos that made it not work at all.
Additionally, some things were apparently expecting $wgContLang to be an
actual Language and not a StubObject. To solve that, we just set it
directly and don't use a StubObject. Initialization should be cheap, and
it would probably have been unstubbed on every test anyway.
Bug: T231799
Change-Id: I6d68a22e53e17458d0a63c13bd97c19baff4d1c7