Page MenuHomePhabricator

MediaWikiUnitTestCase should prevent access to MediaWikiServices
Closed, ResolvedPublic

Description

MediaWikiUnitTestCase is intended to be used for "pure" unit tests, which mock dependencies in classes under test. To enforce that, we can block classes extending MediaWikiUnitTestCase from accessing MediaWikiServices. That goes a long way towards ensuring database, filesystem, network access etc are prevented in those types of tests.


Original report:

See T266389 for context.

For example, with AbuseFilter, there are tests in tests/phpunit/unit which access MediaWiki services and globals which are otherwise prohibited in MediaWikiUnitTestCase. If you try to run these locally with vendor/bin/phpunit they fail:

composer phpunit:unit -- --exclude-group Broken,ParserFuzz,Stub --stop-on-failure
There was 1 error:

1) AbuseFilterParserTest::testDUNDEFINED with data set #6 ('norm(user_name) !== rmspecials('')')
Error: Class 'Wikimedia\Equivset\Equivset' not found

/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:1610
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:1677
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:1219
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:1016
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:938
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:880
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:869
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:825
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:815
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:780
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:756
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:727
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:695
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:661
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:607
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:533
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:442
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:423
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:404
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:226
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/includes/parser/AbuseFilterParser.php:244
/home/kostajh/src/mediawiki/core/extensions/AbuseFilter/tests/phpunit/unit/AbuseFilterParserTest.php:978
/home/kostajh/src/mediawiki/core/tests/phpunit/MediaWikiUnitTestCase.php:112

But, in CI no error is thrown with the same command: https://integration.wikimedia.org/ci/job/quibble-vendor-mysql-php72-noselenium-docker/42693/consoleFull#console-section-9

I don't understand how or why that is happening, but it's supposed to throw an error. IIRC there was a task around this although the only thing I find at the moment is T229220: Unit tests are not being run for extensions under PHPUnit 4.x (HHVM) which is tangential. Pinging @hashar for ideas or clues.

Details

SubjectRepoBranchLines +/-
mediawiki/coremaster+53 -8
mediawiki/extensions/Wikibasemaster+64 -46
mediawiki/extensions/Wikibasemaster+214 -230
mediawiki/extensions/GrowthExperimentsmaster+333 -240
mediawiki/extensions/CirrusSearchmaster+14 -54
mediawiki/extensions/CirrusSearchmaster+4 -4
mediawiki/extensions/CirrusSearchmaster+53 -13
mediawiki/extensions/Citemaster+6 -6
mediawiki/extensions/Wikibasemaster+2 -1
mediawiki/coremaster+79 -1
integration/quibblemaster+74 -2
integration/quibblemaster+18 -13
integration/quibblemaster+10 -0
mediawiki/coremaster+1 -1
mediawiki/coremaster+15 -12
mediawiki/coremaster+7 -0
mediawiki/coremaster+2 -6
Show related patches Customize query in gerrit

Related Objects

Event Timeline

Note, as I wrote in the other task: interestingly, codehealth jobs are not affected, in that these tests fail correctly there, see https://integration.wikimedia.org/ci/job/mwext-codehealth-patch/25987/console.

Note, as I wrote in the other task: interestingly, codehealth jobs are not affected, in that these tests fail correctly there, see https://integration.wikimedia.org/ci/job/mwext-codehealth-patch/25987/console.

Yes, good addition, thanks for flagging. The differences with that one are:

  1. it's using mwext-phpunit-coverage script, which in turn executes:
php -d zend_extension=xdebug.so \
       vendor/bin/phpunit \
       --testsuite=extensions:unit \
       --exclude-group Dump,Broken,ParserFuzz,Stub \
       --coverage-clover "$LOG_DIR"/clover.xml \
       --log-junit "$LOG_DIR"/junit.xml &

That should be just about equivalent to composer phpunit:unit, since the composer script evaluates to vendor/bin/phpunit --colors=always --testsuite=core:unit,extensions:unit,skins:unit.

  1. In the codehealth job, only the AbuseFilter repository is cloned.

The lack of errors in the description could make sense if the AbuseFilter repository wasn't cloned at the time the tests were run, but it doesn't look like that is the case.

Hmm, so:

vendor/bin/phpunit --testsuite=core:unit,extensions:unit -- no errors

vendor/bin/phpunit --testsuite=skins:unit,extensions:unit -- errors

vendor/bin/phpunit --testsuite=extensions:unit -- errors

`vendor/bin/phpunit --testsuite=core:unit,skins:unit,extensions:unit -- no errors

OK, it looks like if you remove tests/phpunit/unit/includes/language/SpecialPageAliasTest.php then the AbuseFilter unit tests fail as they should.

I don't yet know why that test is bootstrapping MediaWiki nor why calls to MediaWikiServices are allowed inside a test that extends MediaWikiUnitTestCase.

One idea is to adjust quibble so that LocalSettings.php is moved out of the way before the unit tests run.

Change 636430 had a related patch set uploaded (by Kosta Harlan; owner: Kosta Harlan):
[integration/quibble@master] Move LocalSettings.php out of the way before running unit tests

https://gerrit.wikimedia.org/r/636430

OK, it looks like if you remove tests/phpunit/unit/includes/language/SpecialPageAliasTest.php then the AbuseFilter unit tests fail as they should.

I don't yet know why that test is bootstrapping MediaWiki nor why calls to MediaWikiServices are allowed inside a test that extends MediaWikiUnitTestCase.

validSpecialPageAliasesProvider, which is a data provider, is calling Language::fetchLanguageNames(), which calls MediaWikiServices::getInstance() etc. Might this be the cause? It seems a bit weak though, that a single test doing that will bootstrap MediaWiki and prevent further failures later.

OK, it looks like if you remove tests/phpunit/unit/includes/language/SpecialPageAliasTest.php then the AbuseFilter unit tests fail as they should.

I don't yet know why that test is bootstrapping MediaWiki nor why calls to MediaWikiServices are allowed inside a test that extends MediaWikiUnitTestCase.

validSpecialPageAliasesProvider, which is a data provider, is calling Language::fetchLanguageNames(), which calls MediaWikiServices::getInstance() etc. Might this be the cause? It seems a bit weak though, that a single test doing that will bootstrap MediaWiki and prevent further failures later.

Yeah, apparently that's all you need. :(

I think when this went live, we explicitly ran composer phpunit:unit without LocalSettings.php in place. It seems that this got revised at some point (possibly in the plan execution patches from a few months back?) since the MediaWiki install is happening before the unit tests are run in https://integration.wikimedia.org/ci/job/quibble-vendor-mysql-php72-noselenium-docker/42693/consoleFull#console-section-6 . cc @awight

I think we may want to avoid having to move the file in CI, so that out-of–the-box things are locally more similar to CI.

If use of MediaWikiServices is the issue, can we plant some kind of explosive there during the unit test run? It's not clear to me how calling MediaWikiServices would lead to inclusion of LocalSettings.php. I assume this isn't what's happening, but that it is included ahead of time, in which case we may want to fix that so that the composer entry point bootstrapping isn't including any LocalSettings.php file, regardless of whether it exists or not.

I think we may want to avoid having to move the file in CI, so that out-of–the-box things are locally more similar to CI.

Yeah. Even so, I think it would still be useful to have in quibble, but yes we want this to work locally.

If use of MediaWikiServices is the issue, can we plant some kind of explosive there during the unit test run? It's not clear to me how calling MediaWikiServices would lead to inclusion of LocalSettings.php. I assume this isn't what's happening, but that it is included ahead of time, in which case we may want to fix that so that the composer entry point bootstrapping isn't including any LocalSettings.php file, regardless of whether it exists or not.

Having looked at this more closely, it doesn't seem like LocalSettings.php is the culprit after all. I'm not sure why I thought that 😕

I think the main problem is that we have too much magic going on in our data providers, which are harder to intercept since they are evaluated independently of the MediaWikiUnitTestCase setup process.

Change 636913 had a related patch set uploaded (by Kosta Harlan; owner: Kosta Harlan):
[mediawiki/core@master] [WIP] Prevent access to MediaWikiServices in unit tests

https://gerrit.wikimedia.org/r/636913

Change 636915 had a related patch set uploaded (by Kosta Harlan; owner: Kosta Harlan):
[mediawiki/core@master] [WIP] Prevent access to MediaWikiServices in integration and unit tests

https://gerrit.wikimedia.org/r/636915

Change 637280 had a related patch set uploaded (by Kosta Harlan; owner: Kosta Harlan):
[mediawiki/core@master] phpunit: Block calls to MW services in data providers and in unit tests

https://gerrit.wikimedia.org/r/637280

Change 636915 abandoned by Kosta Harlan:
[mediawiki/core@master] [WIP] Prevent access to MediaWikiServices in integration and unit tests

Reason:
See I5913839d049916cf569efddb250644a47f3206d7

https://gerrit.wikimedia.org/r/636915

Change 636913 abandoned by Kosta Harlan:
[mediawiki/core@master] [WIP] Prevent access to MediaWikiServices in unit tests

Reason:
See I5913839d049916cf569efddb250644a47f3206d7

https://gerrit.wikimedia.org/r/636913

Change 641941 had a related patch set uploaded (by Kosta Harlan; owner: Kosta Harlan):
[mediawiki/core@master] phpunit: Use a closure for services to enable unit testing

https://gerrit.wikimedia.org/r/641941

Change 641944 had a related patch set uploaded (by Kosta Harlan; owner: Kosta Harlan):
[mediawiki/core@master] phpunit: Switch SpecialPageAliasTest to integration tests

https://gerrit.wikimedia.org/r/641944

Change 641941 merged by jenkins-bot:
[mediawiki/core@master] phpunit: Use a closure for services to enable unit testing

https://gerrit.wikimedia.org/r/641941

Change 641944 merged by jenkins-bot:
[mediawiki/core@master] phpunit: Switch SpecialPageAliasTest to integration tests

https://gerrit.wikimedia.org/r/641944

Change 644174 had a related patch set uploaded (by Kosta Harlan; owner: Kosta Harlan):
[integration/quibble@master] Run phpunit-unit before MediaWiki install

https://gerrit.wikimedia.org/r/644174

Change 636430 abandoned by Kosta Harlan:
[integration/quibble@master] Move LocalSettings.php out of the way before running unit tests

Reason:
We need to fix the bug referenced here in core; that said I took the idea to run phpunit-unit earlier and have a patch for that in I935004d8ed51d1c4a11c6db863ac182bd4d14b34

https://gerrit.wikimedia.org/r/636430

Change 644174 merged by jenkins-bot:
[integration/quibble@master] Run phpunit-unit before MediaWiki install

https://gerrit.wikimedia.org/r/644174

Change 654804 had a related patch set uploaded (by Hashar; owner: Hashar):
[integration/quibble@master] Release Quibble 0.0.46

https://gerrit.wikimedia.org/r/654804

Change 654804 merged by jenkins-bot:
[integration/quibble@master] Release Quibble 0.0.46

https://gerrit.wikimedia.org/r/654804

Change 813203 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/core@master] phpunit: Prevent access to MW services in unit test case

https://gerrit.wikimedia.org/r/813203

Change 637280 abandoned by Kosta Harlan:

[mediawiki/core@master] phpunit: Block calls to MW services in data providers and in unit tests

Reason:

See I1ae61d085cf038b68e27ea30c5db7a37c713f9ed

https://gerrit.wikimedia.org/r/637280

Change 813584 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/GrowthExperiments@master] WikiPageConfigLoaderTest: Don't access MW services from unit test

https://gerrit.wikimedia.org/r/813584

Change 813585 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/Wikibase@master] SiteLinksForDisplayLookupTest: Don't access MW services in unit test

https://gerrit.wikimedia.org/r/813585

Change 813586 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/Cite@master] phpunit: Unit tests may not access MW services

https://gerrit.wikimedia.org/r/813586

Change 813587 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/CirrusSearch@master] phpunit: Unit tests may not access MW services

https://gerrit.wikimedia.org/r/813587

Change 813585 merged by jenkins-bot:

[mediawiki/extensions/Wikibase@master] SiteLinksForDisplayLookupTest: Don't access MW services in unit test

https://gerrit.wikimedia.org/r/813585

Change 813586 merged by jenkins-bot:

[mediawiki/extensions/Cite@master] phpunit: Unit tests may not access MW services

https://gerrit.wikimedia.org/r/813586

Change 813587 merged by jenkins-bot:

[mediawiki/extensions/CirrusSearch@master] phpunit: Unit tests may not access MW services

https://gerrit.wikimedia.org/r/813587

Change 813664 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/CirrusSearch@master] [WIP] phpunit: Unit tests may not access MW services

https://gerrit.wikimedia.org/r/813664

Change 813325 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/CirrusSearch@master] Revert "phpunit: Unit tests may not access MW services"

https://gerrit.wikimedia.org/r/813325

Change 813664 abandoned by Kosta Harlan:

[mediawiki/extensions/CirrusSearch@master] [WIP] phpunit: Unit tests may not access MW services

Reason:

https://gerrit.wikimedia.org/r/813664

Change 813325 merged by jenkins-bot:

[mediawiki/extensions/CirrusSearch@master] phpunit: Convert Version/ElasticsearchIntermediary/UserTestingEngine to integration tests

https://gerrit.wikimedia.org/r/813325

Change 813584 abandoned by Kosta Harlan:

[mediawiki/extensions/GrowthExperiments@master] WikiPageConfigLoaderTest: Don't access MW services from unit test

Reason:

https://gerrit.wikimedia.org/r/813584

Change 813882 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/Wikibase@master] phpunit: Unit tests may not access MediaWikiServices

https://gerrit.wikimedia.org/r/813882

Change 813704 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/Wikibase@master] Convert PHPUnit\Framework\TestCase to MediaWikiUnitTestCase

https://gerrit.wikimedia.org/r/813704

kostajh renamed this task from Some unit tests are not executed with composer phpunit:unit to MediaWikiUnitTestCase should prevent access to MediaWikiServices.Jul 14 2022, 11:42 AM

Change 813704 abandoned by Kosta Harlan:

[mediawiki/extensions/Wikibase@master] Convert PHPUnit\Framework\TestCase to MediaWikiUnitTestCase

Reason:

https://gerrit.wikimedia.org/r/813704

Change 813882 abandoned by Kosta Harlan:

[mediawiki/extensions/Wikibase@master] phpunit: Unit tests may not access MediaWikiServices

Reason:

https://gerrit.wikimedia.org/r/813882

Change 813203 abandoned by Kosta Harlan:

[mediawiki/core@master] phpunit: Prevent access to services in UnitTestCase

Reason:

https://gerrit.wikimedia.org/r/813203

Sorry, I had completely forgotten about this task, but I've been independently working on this and the patch which finally implements this restriction, r938019, was merged yesterday.