wiki.techinc.nl/tests/phpunit/includes/TestUserRegistry.php
Timo Tijhof 4938038175 tests: Remove use of wfRandomString() for test fixtures
This reduces confidence in the test. There is no guruantee that
it won't return the same value twice during the duration of a full
PHPUnit run of all test suites, whether twice in a row or 20 minutes
apart.

For a test that needs a string of any kind, use an explicit, consinstent
and cheap literal value.

For a test that specifically needs some kind of uniqueness compared to
something else within the same test case, do so explicitly.

Tests that require something globally unique (for some undefined/vague
definition of "global") were not found, and should not exist anyway.

Also, in libs/objectcache tests, fix order of parameters in some
assertions (expected first, then actual), and use assertFalse/assertSame
instead of assertEqual for cases where false is expected to remove
tolerance of other loosely equal values.

Change-Id: Ifc60e88178da471330b94bfbf12e2731d2efc77d
2019-05-06 17:22:03 +00:00

123 lines
3.4 KiB
PHP

<?php
/**
* @since 1.28
*/
class TestUserRegistry {
/** @var TestUser[] (group key => TestUser) */
private static $testUsers = [];
/** @var int Count of users that have been generated */
private static $counter = 0;
/** @var int Random int, included in IDs */
private static $randInt;
public static function getNextId() {
if ( !self::$randInt ) {
self::$randInt = mt_rand( 1, 0xFFFFFF );
}
return sprintf( '%06x.%03x', self::$randInt, ++self::$counter );
}
/**
* Get a TestUser object that the caller may modify.
*
* @since 1.28
*
* @param string $testName Caller's __CLASS__. Used to generate the
* user's username.
* @param string|string[] $groups Groups the test user should be added to.
* @return TestUser
*/
public static function getMutableTestUser( $testName, $groups = [] ) {
$id = self::getNextId();
$password = "password_for_test_user_id_{$id}";
$testUser = new TestUser(
"TestUser $testName $id", // username
"Name $id", // real name
"$id@mediawiki.test", // e-mail
(array)$groups, // groups
$password // password
);
$testUser->getUser()->clearInstanceCache();
return $testUser;
}
/**
* Get a TestUser object that the caller may not modify.
*
* Whenever possible, unit tests should use immutable users, because
* immutable users can be reused in multiple tests, which helps keep
* the unit tests fast.
*
* @since 1.28
*
* @param string|string[] $groups Groups the test user should be added to.
* @return TestUser
*/
public static function getImmutableTestUser( $groups = [] ) {
$groups = array_unique( (array)$groups );
sort( $groups );
$key = implode( ',', $groups );
$testUser = self::$testUsers[$key] ?? false;
if ( !$testUser || !$testUser->getUser()->isLoggedIn() ) {
$id = self::getNextId();
// Hack! If this is the primary sysop account, make the username
// be 'UTSysop', for back-compat, and for the sake of PHPUnit data
// provider methods, which are executed before the test database
// is set up. See T136348.
if ( $groups === [ 'bureaucrat', 'sysop' ] ) {
$username = 'UTSysop';
$password = 'UTSysopPassword';
} else {
$username = "TestUser $id";
$password = "password_for_test_user_id_{$id}";
}
self::$testUsers[$key] = $testUser = new TestUser(
$username, // username
"Name $id", // real name
"$id@mediawiki.test", // e-mail
$groups, // groups
$password // password
);
}
$testUser->getUser()->clearInstanceCache();
return self::$testUsers[$key];
}
/**
* Clear the registry.
*
* TestUsers created by this class will not be deleted, but any handles
* to existing immutable TestUsers will be deleted, ensuring these users
* are not reused. We don't reset the counter or random string by design.
*
* @since 1.28
*
* @param string[] $groups Groups the test user should be added to.
* @return TestUser
*/
public static function clear() {
self::$testUsers = [];
}
/**
* @todo It would be nice if this were a non-static method of TestUser
* instead, but that doesn't seem possible without friends?
*
* @return bool True if it's safe to modify the user
*/
public static function isMutable( User $user ) {
foreach ( self::$testUsers as $key => $testUser ) {
if ( $user === $testUser->getUser() ) {
return false;
}
}
return true;
}
}