phpunit.php: Move remaining CLI options to env variables

And write release notes for all changes so far.

Note: This should be announced to wikitech-l after merging.

Bug: T90875
Change-Id: I597ed2b5666f4214173609f7e77e23dbc4fd81ae
This commit is contained in:
Daimona Eaytoy 2021-03-17 19:19:25 +01:00
parent 0d8d71a7d1
commit 6507d6b2a4
3 changed files with 44 additions and 242 deletions

View file

@ -224,6 +224,27 @@ because of Phabricator reports.
- getEarliestRevTime, deprecated in 1.35
* UploadBase::stashFile, deprecated since 1.28, was removed.
* wfGetRusage(), deprecated since 1.35, has been removed.
* The following CLI options were removed from tests/phpunit.php:
- use-filebackend
- use-jobqueue
- use-bagostuff
The following options (inherited from Maintenance) were also removed:
- conf
- dbuser
- dbpass
- dbdefaultgroup
- globals
- memory-limit
- profiler
- server
The following options were changed to environment variables:
- wiki => PHPUNIT_WIKI
- use-normal-tables => PHPUNIT_USE_NORMAL_TABLES
- reuse-db => PHPUNIT_REUSE_DB
- use-filebackend => PHPUNIT_USE_FILEBACKEND
- use-bagostuff => PHPUNIT_USE_BAGOSTUFF
- use-jobqueue => PHPUNIT_USE_JOBQUEUE
This is so that we can use the default PHPUnit entry point (T90875).
* …
=== Deprecations in 1.37 ===

View file

@ -1,14 +1,26 @@
<?php
/**
* @todo Get rid of this class, the options we don't need (e.g. for filebackend, bagostuff and jobqueue
* we should have dedicated test subclasses), and use getenv directly in calling code.
*/
final class MediaWikiCliOptions {
/**
* @fixme This is an awful hack.
*/
public static $additionalOptions = [
'use-filebackend' => false,
'use-bagostuff' => false,
'use-jobqueue' => false,
'use-filebackend' => null,
'use-bagostuff' => null,
'use-jobqueue' => null,
'use-normal-tables' => false,
'reuse-db' => false,
];
public static function initialize() : void {
self::$additionalOptions['use-normal-tables'] = (bool)getenv( 'PHPUNIT_USE_NORMAL_TABLES' );
self::$additionalOptions['reuse-db'] = (bool)getenv( 'PHPUNIT_REUSE_DB' );
self::$additionalOptions['use-filebackend'] = getenv( 'PHPUNIT_USE_FILEBACKEND' ) ?: null;
self::$additionalOptions['use-bagostuff'] = getenv( 'PHPUNIT_USE_BAGOSTUFF' ) ?: null;
self::$additionalOptions['use-jobqueue'] = getenv( 'PHPUNIT_USE_JOBQUEUE' ) ?: null;
}
}

View file

@ -9,43 +9,6 @@
use MediaWiki\MediaWikiServices;
class PHPUnitMaintClass {
/**
* Array of desired/allowed params
* @var array[]
*/
private $mParams = [];
/** @var array This is the list of options that were actually passed */
private $mOptions = [];
/** @var bool Have we already loaded our user input? */
private $mInputLoaded = false;
public function __construct() {
$this->addOption( 'help', 'Display this help message' );
$this->addOption( 'wiki', 'For specifying the wiki ID', true );
$this->addOption( 'use-filebackend', 'Use filebackend', true );
$this->addOption( 'use-bagostuff', 'Use bagostuff', true );
$this->addOption( 'use-jobqueue', 'Use jobqueue', true );
$this->addOption( 'use-normal-tables', 'Use normal DB tables.' );
$this->addOption(
'reuse-db', 'Init DB only if tables are missing and keep after finish.'
);
}
/**
* Add a parameter to the script. Will be displayed on --help
* with the associated description
*
* @param string $name The name of the param (help, version, etc)
* @param string $description The description of the param to show on --help
* @param bool $withArg Is an argument required with this option?
*/
private function addOption( $name, $description, $withArg = false ) {
$this->mParams[$name] = [
'desc' => $description,
'withArg' => $withArg
];
}
public function setup() {
global $wgCommandLineMode;
@ -71,8 +34,6 @@ class PHPUnitMaintClass {
ini_set( 'display_errors', 'stderr' );
}
$this->loadParamsAndArgs();
# Disable the memory limit as it's not needed for tests.
# Note we need to set it again later in cache LocalSettings changed it
ini_set( 'memory_limit', -1 );
@ -93,136 +54,6 @@ class PHPUnitMaintClass {
TestSetup::snapshotGlobals();
}
/**
* Checks to see if a particular option exists.
* @param string $name The name of the option
* @return bool
*/
private function hasOption( $name ) {
return isset( $this->mOptions[$name] );
}
/**
* Get an option, or return the default.
*
* If the option was added to support multiple occurrences,
* this will return an array.
*
* @param string $name The name of the param
* @param mixed|null $default Anything you want, default null
* @return mixed
*/
private function getOption( $name, $default = null ) {
if ( $this->hasOption( $name ) ) {
return $this->mOptions[$name];
} else {
// Set it so we don't have to provide the default again
$this->mOptions[$name] = $default;
return $this->mOptions[$name];
}
}
/**
* Process command line arguments
* $mOptions becomes an array with keys set to the option names
* $mArgs becomes a zero-based array containing the non-option arguments
*/
private function loadParamsAndArgs() {
# If we've already loaded input (either by user values or from $argv)
# skip on loading it again. The array_shift() will corrupt values if
# it's run again and again
if ( $this->mInputLoaded ) {
return;
}
global $argv;
$this->loadWithArgv( array_slice( $argv, 1 ) );
}
/**
* Load params and arguments from a given array
* of command-line arguments
*
* @param array $argv
*/
private function loadWithArgv( $argv ) {
$options = [];
# Parse arguments
for ( $arg = reset( $argv ); $arg !== false; $arg = next( $argv ) ) {
if ( $arg !== '--' && substr( $arg, 0, 2 ) == '--' ) {
# Long options
$option = substr( $arg, 2 );
if ( isset( $this->mParams[$option] ) && $this->mParams[$option]['withArg'] ) {
$param = next( $argv );
if ( $param === false ) {
echo "\nERROR: $option parameter needs a value after it\n";
$this->maybeHelp( true );
}
$this->setParam( $options, $option, $param );
} else {
$bits = explode( '=', $option, 2 );
$this->setParam( $options, $bits[0], $bits[1] ?? 1 );
}
} elseif ( $arg !== '-' && substr( $arg, 0, 1 ) == '-' ) {
# Short options
$argLength = strlen( $arg );
for ( $p = 1; $p < $argLength; $p++ ) {
$option = $arg[$p];
if ( isset( $this->mParams[$option]['withArg'] ) && $this->mParams[$option]['withArg'] ) {
$param = next( $argv );
if ( $param === false ) {
echo "\nERROR: $option parameter needs a value after it\n";
$this->maybeHelp( true );
}
$this->setParam( $options, $option, $param );
} else {
$this->setParam( $options, $option, 1 );
}
}
}
}
$this->mOptions = $options;
$this->mInputLoaded = true;
}
/**
* Maybe show the help. If the help is shown, exit.
*
* @param bool $force Whether to force the help to show, default false
*/
public function maybeHelp( $force = false ) {
if ( !$force && !$this->hasOption( 'help' ) ) {
return;
}
$this->showHelp();
die( 1 );
}
/**
* Helper function used solely by loadParamsAndArgs
* to prevent code duplication
*
* This sets the param in the options array based on
* whether or not it can be specified multiple times.
*
* @param array &$options
* @param string $option
* @param mixed $value
*/
private function setParam( &$options, $option, $value ) {
$exists = array_key_exists( $option, $options );
if ( !$exists ) {
$options[$option] = $value;
} else {
echo "\nERROR: $option parameter given twice\n";
$this->maybeHelp( true );
}
}
/**
* Output a message and terminate the current script.
*
@ -292,8 +123,6 @@ class PHPUnitMaintClass {
// Setup.php is included, which calls MWExceptionHandler::installHandle().
restore_error_handler();
$this->forceFormatServerArgv();
if ( !class_exists( PHPUnit\Framework\TestCase::class ) ) {
echo "PHPUnit not found. Please install it and other dev dependencies by
running `composer install` in MediaWiki root directory.\n";
@ -306,76 +135,12 @@ class PHPUnitMaintClass {
fwrite( STDERR, 'Using PHP ' . PHP_VERSION . "\n" );
foreach ( MediaWikiCliOptions::$additionalOptions as $option => $default ) {
MediaWikiCliOptions::$additionalOptions[$option] = $this->getOption( $option );
}
MediaWikiCliOptions::initialize();
$command = new MediaWikiPHPUnitCommand();
$command->run( $_SERVER['argv'], true );
}
/**
* Force the format of elements in $_SERVER['argv']
* - Split args such as "wiki=enwiki" into two separate arg elements "wiki" and "enwiki"
*/
private function forceFormatServerArgv() {
$argv = [];
for ( $key = 0; $key < count( $_SERVER['argv'] ); $key++ ) {
$arg = $_SERVER['argv'][$key];
if ( $key === 0 ) {
$argv[0] = $arg;
continue;
}
if ( preg_match( '/^--(.*)$/', $arg, $match ) ) {
$opt = $match[1];
$parts = explode( '=', $opt, 2 );
$opt = $parts[0];
// Avoid confusing PHPUnit with MediaWiki-specific parameters
if ( isset( $this->mParams[$opt] ) ) {
if ( $this->mParams[$opt]['withArg'] && !isset( $parts[1] ) ) {
// skip the value after the option name as well
$key++;
}
continue;
}
}
$argv[] = $arg;
}
$_SERVER['argv'] = $argv;
}
private function showHelp() {
$tab = " ";
$descWidth = 80 - ( 2 * strlen( $tab ) );
ksort( $this->mParams );
$output = "\nUsage: php tests/phpunit.php";
$output .= " [--" . implode( "|--", array_keys( $this->mParams ) ) . "]";
echo "$output\n\n";
echo "MediaWiki specific parameters:\n";
foreach ( $this->mParams as $name => $info ) {
echo wordwrap(
"$tab--$name: " . $info['desc'],
$descWidth,
"\n$tab$tab"
) . "\n";
}
echo "\n";
echo "PHPUnit options:\n\n";
$command = new MediaWikiPHPUnitCommand();
$command->publicShowHelp();
}
/**
* Generic setup for most installs. Returns the location of LocalSettings
* @return string
@ -384,8 +149,8 @@ class PHPUnitMaintClass {
global $wgCommandLineMode, $IP;
$settingsFile = "$IP/LocalSettings.php";
if ( isset( $this->mOptions['wiki'] ) ) {
$bits = explode( '-', $this->mOptions['wiki'], 2 );
if ( getenv( 'PHPUNIT_WIKI' ) ) {
$bits = explode( '-', getenv( 'PHPUNIT_WIKI' ), 2 );
define( 'MW_DB', $bits[0] );
define( 'MW_PREFIX', $bits[1] ?? '' );
}
@ -431,5 +196,9 @@ define( 'MW_SETUP_CALLBACK', 'wfPHPUnitSetup' );
require_once "$IP/includes/Setup.php";
$wrapper->maybeHelp( false );
if ( in_array( '--help', $argv, true ) ) {
$command = new MediaWikiPHPUnitCommand();
$command->publicShowHelp();
die( 1 );
}
$wrapper->execute();