TL;DR: A bug in MariaDB 11.2.2 (possibly earlier 11.2.x, but seemingly not 11.1.3 yet), MDEV-32973, confused MediaWiki’s integration test setup; subsequent tests erroneously thought the test DB had been set up already, skipped setting it up again, and ran against the real DB. MediaWiki has been fixed to (try to) repeat the test DB setup in each test if it previously failed (Gerrit change); the MariaDB bug is also getting fixed.
I’ve somehow gotten my local development wiki into a state where running PHPUnit tests results in the real wiki database getting wiped. To my knowledge, this is something that should never ever ever happen.
For me, the steps to reproduce are quite simple:
- Have a database backup. Mine is unfortunately a few months old, but it’s the best I have now. If you’re experimenting with this task, make sure you have a more recent backup if you value your test data.
- Load the main page of your wiki in the browser. Confirm it shows up.
- Run (in the mw core directory): composer phpunit:entrypoint -- extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialNewItemTest.php
- Reload the main page. Observe that it’s gone now.
- Restore your database backup.
But presumably this error doesn’t happen for everyone, so it remains to be seen which parts of my setup are relevant to this.
The test output is:
> phpunit '-c' 'tests/phpunit/suite.xml' 'extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialNewItemTest.php' Using PHP 8.2.13 PHPUnit 9.5.28 by Sebastian Bergmann and contributors. E..................E....... 27 / 27 (100%) You should really speed up these slow tests (>50ms)... 1. 259ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testIdGeneratorRateLimit 2. 228ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testErrorBeingDisplayed_WhenItemWithTheSameLabelAndDescriptionInThisLanguageAlreadyExists 3. 193ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testSiteAndPageInputFieldsWithPredefinedValuesPresent_WhenRenderedWithGetParametersPassed 4. 187ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testEntityIsBeingCreated_WhenValidInputIsGiven with data set "multiple aliases" 5. 160ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testEntityIsBeingCreated_WhenValidInputIsGiven with data set "another language" 6. 160ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testEntityIsBeingCreated_WhenValidInputIsGiven with data set "nontrimmed description" 7. 151ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testEntityIsBeingCreated_WhenValidInputIsGiven with data set "only label is set" 8. 151ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testEntityIsBeingCreated_WhenValidInputIsGiven with data set "all input is present" 9. 147ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testEntityIsBeingCreated_WhenValidInputIsGiven with data set "nontrimmed label" 10. 145ms to run Wikibase\\Repo\\Tests\\Specials\\SpecialNewItemTest::testEntityIsBeingCreated_WhenValidInputIsGiven with data set "single alias" ...and there are 14 more above your threshold hidden from view Time: 00:02.880, Memory: 101.50 MB There were 2 errors: 1) Wikibase\Repo\Tests\Specials\SpecialNewItemTest::testAllNecessaryFormFieldsArePresent_WhenRendered Wikimedia\Rdbms\DBQueryError: Error 1051: Unknown table 'wiki1.unittest_abuse_filter_action' Function: CloneDatabase::cloneTableStructure Query: DROP TABLE `unittest_abuse_filter_action` CASCADE /srv/http/wiki1/includes/libs/rdbms/database/Database.php:1230 /srv/http/wiki1/includes/libs/rdbms/database/Database.php:1214 /srv/http/wiki1/includes/libs/rdbms/database/Database.php:1188 /srv/http/wiki1/includes/libs/rdbms/database/Database.php:674 /srv/http/wiki1/includes/libs/rdbms/database/Database.php:3022 /srv/http/wiki1/includes/db/CloneDatabase.php:103 /srv/http/wiki1/tests/phpunit/MediaWikiIntegrationTestCase.php:1749 /srv/http/wiki1/tests/phpunit/MediaWikiIntegrationTestCase.php:1813 /srv/http/wiki1/tests/phpunit/MediaWikiIntegrationTestCase.php:1768 /srv/http/wiki1/tests/phpunit/MediaWikiIntegrationTestCase.php:683 /srv/http/wiki1/tests/phpunit/MediaWikiIntegrationTestCase.php:631 === Logs generated by test case [wfDebug] [debug] CloneDatabase::cloneTableStructure dropping unittest_abuse_filter {"private":false} [wfDebug] [debug] CloneDatabase::cloneTableStructure duplicating abuse_filter to unittest_abuse_filter {"private":false} === 2) Wikibase\Repo\Tests\Specials\SpecialNewItemTest::testExceptionWhenUserBlockedOnNamespace RuntimeException: Can't create user on real database /srv/http/wiki1/tests/phpunit/includes/TestUser.php:35 /srv/http/wiki1/tests/phpunit/includes/TestUser.php:42 /srv/http/wiki1/tests/phpunit/includes/TestUserRegistry.php:78 /srv/http/wiki1/tests/phpunit/MediaWikiIntegrationTestCase.php:285 /srv/http/wiki1/extensions/Wikibase/repo/tests/phpunit/includes/Specials/SpecialNewEntityTestCase.php:65 === Logs generated by test case [objectcache] [debug] MainWANObjectCache using store {class} {"class":"HashBagOStuff"} [localisation] [debug] LocalisationCache using store LCStoreNull [] [localisation] [debug] LocalisationCache::loadCoreData: got localisation for qqx from source [] === ERRORS! Tests: 27, Assertions: 49, Errors: 2. Script phpunit handling the phpunit event returned with error code 2 Script @phpunit -c tests/phpunit/suite.xml was called via phpunit:entrypoint
My interpretation is that the first error causes all of MediaWikiIntegrationTestCase::setupDatabaseWithTestPrefix() and its callers to fail, which means the rest of the test suite runs against the real database. Some of the tests then touch the page table, causing it to be wiped during teardown. Eventually, the second error indicates that TestUser detects that the tests are targeting the main database.
Not all tests appear to be affected: Wikibase’s SpecialSetLabelTest, for instance, also shows similar errors (1× unknown table unittest_abuse_filter_action, 4× can’t create user on real database), but doesn’t seem to wipe the database as far as I can tell. I’m not yet sure why (SpecialSetLabelTest should also touch the page table as far as I can tell).