MediaWiki REL1_30
ApiStructureTest.php
Go to the documentation of this file.
1<?php
2
3use Wikimedia\TestingAccessWrapper;
4
15
17 private static $main;
18
20 private static $testGlobals = [
21 [
22 'MiserMode' => false,
23 'AllowCategorizedRecentChanges' => false,
24 ],
25 [
26 'MiserMode' => true,
27 'AllowCategorizedRecentChanges' => true,
28 ],
29 ];
30
35 private static function getMain() {
36 if ( !self::$main ) {
37 self::$main = new ApiMain( RequestContext::getMain() );
38 self::$main->getContext()->setLanguage( 'en' );
39 self::$main->getContext()->setTitle(
40 Title::makeTitle( NS_SPECIAL, 'Badtitle/dummy title for ApiStructureTest' )
41 );
42 }
43 return self::$main;
44 }
45
51 private function checkMessage( $msg, $what ) {
52 $msg = ApiBase::makeMessage( $msg, self::getMain()->getContext() );
53 $this->assertInstanceOf( 'Message', $msg, "$what message" );
54 $this->assertTrue( $msg->exists(), "$what message {$msg->getKey()} exists" );
55 }
56
62 public function testDocumentationExists( $path, array $globals ) {
64
65 // Set configuration variables
66 $main->getContext()->setConfig( new MultiConfig( [
67 new HashConfig( $globals ),
68 RequestContext::getMain()->getConfig(),
69 ] ) );
70 foreach ( $globals as $k => $v ) {
71 $this->setMwGlobals( "wg$k", $v );
72 }
73
74 // Fetch module.
75 $module = TestingAccessWrapper::newFromObject( $main->getModuleFromPath( $path ) );
76
77 // Test messages for flags.
78 foreach ( $module->getHelpFlags() as $flag ) {
79 $this->checkMessage( "api-help-flag-$flag", "Flag $flag" );
80 }
81
82 // Module description messages.
83 $this->checkMessage( $module->getSummaryMessage(), 'Module summary' );
84 $this->checkMessage( $module->getExtendedDescription(), 'Module help top text' );
85
86 // Parameters. Lots of messages in here.
87 $params = $module->getFinalParams( ApiBase::GET_VALUES_FOR_HELP );
88 $tags = [];
89 foreach ( $params as $name => $settings ) {
90 if ( !is_array( $settings ) ) {
91 $settings = [];
92 }
93
94 // Basic description message
95 if ( isset( $settings[ApiBase::PARAM_HELP_MSG] ) ) {
96 $msg = $settings[ApiBase::PARAM_HELP_MSG];
97 } else {
98 $msg = "apihelp-{$path}-param-{$name}";
99 }
100 $this->checkMessage( $msg, "Parameter $name description" );
101
102 // If param-per-value is in use, each value's message
103 if ( isset( $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE] ) ) {
104 $this->assertInternalType( 'array', $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE],
105 "Parameter $name PARAM_HELP_MSG_PER_VALUE is array" );
106 $this->assertInternalType( 'array', $settings[ApiBase::PARAM_TYPE],
107 "Parameter $name PARAM_TYPE is array for msg-per-value mode" );
108 $valueMsgs = $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE];
109 foreach ( $settings[ApiBase::PARAM_TYPE] as $value ) {
110 if ( isset( $valueMsgs[$value] ) ) {
111 $msg = $valueMsgs[$value];
112 } else {
113 $msg = "apihelp-{$path}-paramvalue-{$name}-{$value}";
114 }
115 $this->checkMessage( $msg, "Parameter $name value $value" );
116 }
117 }
118
119 // Appended messages (e.g. "disabled in miser mode")
120 if ( isset( $settings[ApiBase::PARAM_HELP_MSG_APPEND] ) ) {
121 $this->assertInternalType( 'array', $settings[ApiBase::PARAM_HELP_MSG_APPEND],
122 "Parameter $name PARAM_HELP_MSG_APPEND is array" );
123 foreach ( $settings[ApiBase::PARAM_HELP_MSG_APPEND] as $i => $msg ) {
124 $this->checkMessage( $msg, "Parameter $name HELP_MSG_APPEND #$i" );
125 }
126 }
127
128 // Info tags (e.g. "only usable in mode 1") are typically shared by
129 // several parameters, so accumulate them and test them later.
130 if ( !empty( $settings[ApiBase::PARAM_HELP_MSG_INFO] ) ) {
131 foreach ( $settings[ApiBase::PARAM_HELP_MSG_INFO] as $i ) {
132 $tags[array_shift( $i )] = 1;
133 }
134 }
135 }
136
137 // Info tags (e.g. "only usable in mode 1") accumulated above
138 foreach ( $tags as $tag => $dummy ) {
139 $this->checkMessage( "apihelp-{$path}-paraminfo-{$tag}", "HELP_MSG_INFO tag $tag" );
140 }
141
142 // Messages for examples.
143 foreach ( $module->getExamplesMessages() as $qs => $msg ) {
144 $this->assertStringStartsNotWith( 'api.php?', $qs,
145 "Query string must not begin with 'api.php?'" );
146 $this->checkMessage( $msg, "Example $qs" );
147 }
148 }
149
150 public static function provideDocumentationExists() {
152 $paths = self::getSubModulePaths( $main->getModuleManager() );
153 array_unshift( $paths, $main->getModulePath() );
154
155 $ret = [];
156 foreach ( $paths as $path ) {
157 foreach ( self::$testGlobals as $globals ) {
158 $g = [];
159 foreach ( $globals as $k => $v ) {
160 $g[] = "$k=" . var_export( $v, 1 );
161 }
162 $k = "Module $path with " . implode( ', ', $g );
163 $ret[$k] = [ $path, $globals ];
164 }
165 }
166 return $ret;
167 }
168
173 public function testParameterConsistency( $path ) {
175 $module = TestingAccessWrapper::newFromObject( $main->getModuleFromPath( $path ) );
176
177 $paramsPlain = $module->getFinalParams();
178 $paramsForHelp = $module->getFinalParams( ApiBase::GET_VALUES_FOR_HELP );
179
180 // avoid warnings about empty tests when no parameter needs to be checked
181 $this->assertTrue( true );
182
183 foreach ( [ $paramsPlain, $paramsForHelp ] as $params ) {
184 foreach ( $params as $param => $config ) {
185 if (
186 isset( $config[ApiBase::PARAM_ISMULTI_LIMIT1] )
187 || isset( $config[ApiBase::PARAM_ISMULTI_LIMIT2] )
188 ) {
189 $this->assertTrue( !empty( $config[ApiBase::PARAM_ISMULTI] ), $param
190 . ': PARAM_ISMULTI_LIMIT* only makes sense when PARAM_ISMULTI is true' );
191 $this->assertTrue( isset( $config[ApiBase::PARAM_ISMULTI_LIMIT1] )
192 && isset( $config[ApiBase::PARAM_ISMULTI_LIMIT2] ), $param
193 . ': PARAM_ISMULTI_LIMIT1 and PARAM_ISMULTI_LIMIT2 must be used together' );
194 $this->assertType( 'int', $config[ApiBase::PARAM_ISMULTI_LIMIT1], $param
195 . 'PARAM_ISMULTI_LIMIT1 must be an integer' );
196 $this->assertType( 'int', $config[ApiBase::PARAM_ISMULTI_LIMIT2], $param
197 . 'PARAM_ISMULTI_LIMIT2 must be an integer' );
198 $this->assertGreaterThanOrEqual( $config[ApiBase::PARAM_ISMULTI_LIMIT1],
199 $config[ApiBase::PARAM_ISMULTI_LIMIT2], $param
200 . 'PARAM_ISMULTI limit cannot be smaller for users with apihighlimits rights' );
201 }
202 }
203 }
204 }
205
209 public static function provideParameterConsistency() {
211 $paths = self::getSubModulePaths( $main->getModuleManager() );
212 array_unshift( $paths, $main->getModulePath() );
213
214 $ret = [];
215 foreach ( $paths as $path ) {
216 $ret[] = [ $path ];
217 }
218 return $ret;
219 }
220
226 protected static function getSubModulePaths( ApiModuleManager $manager ) {
227 $paths = [];
228 foreach ( $manager->getNames() as $name ) {
229 $module = $manager->getModule( $name );
230 $paths[] = $module->getModulePath();
231 $subManager = $module->getModuleManager();
232 if ( $subManager ) {
233 $paths = array_merge( $paths, self::getSubModulePaths( $subManager ) );
234 }
235 }
236 return $paths;
237 }
238}
getContext()
static makeMessage( $msg, IContextSource $context, array $params=null)
Create a Message from a string or array.
Definition ApiBase.php:1701
const PARAM_ISMULTI_LIMIT1
(integer) Maximum number of values, for normal users.
Definition ApiBase.php:211
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below.
Definition ApiBase.php:91
const PARAM_HELP_MSG_INFO
(array) Specify additional information tags for the parameter.
Definition ApiBase.php:145
const PARAM_HELP_MSG_APPEND
((string|array|Message)[]) Specify additional i18n messages to append to the normal message for this ...
Definition ApiBase.php:135
const PARAM_ISMULTI_LIMIT2
(integer) Maximum number of values, for users with the apihighimits right.
Definition ApiBase.php:218
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
Definition ApiBase.php:160
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition ApiBase.php:128
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When set, the result could take longer to generate, but should be more thoro...
Definition ApiBase.php:238
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
Definition ApiBase.php:55
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:45
This class holds a list of modules and handles instantiation.
getModule( $moduleName, $group=null, $ignoreCache=false)
Get module instance by name, or instantiate it if it does not exist.
getNames( $group=null)
Get an array of modules in a specific group or all if no group is set.
Checks that all API modules, core and extensions, conform to the conventions:
static provideDocumentationExists()
static array $testGlobals
Sets of globals to test.
static provideParameterConsistency()
static ApiMain $main
static getSubModulePaths(ApiModuleManager $manager)
Return paths of all submodules in an ApiModuleManager, recursively.
testDocumentationExists( $path, array $globals)
provideDocumentationExists
testParameterConsistency( $path)
provideParameterConsistency
checkMessage( $msg, $what)
Test a message.
static getMain()
Initialize/fetch the ApiMain instance for testing.
A Config instance which stores all settings as a member variable.
assertType( $type, $actual, $message='')
Asserts the type of the provided value.
setMwGlobals( $pairs, $value=null)
Sets a global, maintaining a stashed version of the previous global to be restored in tearDown.
Provides a fallback sequence for Config objects.
static getMain()
Static methods.
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition hooks.txt:1975
const NS_SPECIAL
Definition Defines.php:54
$params