MediaWiki  REL1_31
editTests.php
Go to the documentation of this file.
1 <?php
2 
3 require __DIR__.'/../../maintenance/Maintenance.php';
4 
5 define( 'MW_PARSER_TEST', true );
6 
11  private $termWidth;
12  private $testFiles;
13  private $testCount;
14  private $recorder;
15  private $runner;
16  private $numExecuted;
17  private $numSkipped;
18  private $numFailed;
19 
20  function __construct() {
21  parent::__construct();
22  $this->addOption( 'session-data', 'internal option, do not use', false, true );
23  $this->addOption( 'use-tidy-config',
24  'Use the wiki\'s Tidy configuration instead of known-good' .
25  'defaults.' );
26  }
27 
28  public function finalSetup() {
29  parent::finalSetup();
32  }
33 
34  public function execute() {
35  $this->termWidth = $this->getTermSize()[0] - 1;
36 
37  $this->recorder = new TestRecorder();
38  $this->setupFileData();
39 
40  if ( $this->hasOption( 'session-data' ) ) {
41  $this->session = json_decode( $this->getOption( 'session-data' ), true );
42  } else {
43  $this->session = [ 'options' => [] ];
44  }
45  if ( $this->hasOption( 'use-tidy-config' ) ) {
46  $this->session['options']['use-tidy-config'] = true;
47  }
48  $this->runner = new ParserTestRunner( $this->recorder, $this->session['options'] );
49 
50  $this->runTests();
51 
52  if ( $this->numFailed === 0 ) {
53  if ( $this->numSkipped === 0 ) {
54  print "All tests passed!\n";
55  } else {
56  print "All tests passed (but skipped {$this->numSkipped})\n";
57  }
58  return;
59  }
60  print "{$this->numFailed} test(s) failed.\n";
61  $this->showResults();
62  }
63 
64  protected function setupFileData() {
65  $this->testFiles = [];
66  $this->testCount = 0;
67  foreach ( ParserTestRunner::getParserTestFiles() as $file ) {
68  $fileInfo = TestFileReader::read( $file );
69  $this->testFiles[$file] = $fileInfo;
70  $this->testCount += count( $fileInfo['tests'] );
71  }
72  }
73 
74  protected function runTests() {
75  $teardown = $this->runner->staticSetup();
76  $teardown = $this->runner->setupDatabase( $teardown );
77  $teardown = $this->runner->setupUploads( $teardown );
78 
79  print "Running tests...\n";
80  $this->results = [];
81  $this->numExecuted = 0;
82  $this->numSkipped = 0;
83  $this->numFailed = 0;
84  foreach ( $this->testFiles as $fileName => $fileInfo ) {
85  $this->runner->addArticles( $fileInfo['articles'] );
86  foreach ( $fileInfo['tests'] as $testInfo ) {
87  $result = $this->runner->runTest( $testInfo );
88  if ( $result === false ) {
89  $this->numSkipped++;
90  } elseif ( !$result->isSuccess() ) {
91  $this->results[$fileName][$testInfo['desc']] = $result;
92  $this->numFailed++;
93  }
94  $this->numExecuted++;
95  $this->showProgress();
96  }
97  }
98  print "\n";
99  }
100 
101  protected function showProgress() {
102  $done = $this->numExecuted;
103  $total = $this->testCount;
104  $width = $this->termWidth - 9;
105  $pos = round( $width * $done / $total );
106  printf( '│' . str_repeat( '█', $pos ) . str_repeat( '-', $width - $pos ) .
107  "│ %5.1f%%\r", $done / $total * 100 );
108  }
109 
110  protected function showResults() {
111  if ( isset( $this->session['startFile'] ) ) {
112  $startFile = $this->session['startFile'];
113  $startTest = $this->session['startTest'];
114  $foundStart = false;
115  } else {
116  $startFile = false;
117  $startTest = false;
118  $foundStart = true;
119  }
120 
121  $testIndex = 0;
122  foreach ( $this->testFiles as $fileName => $fileInfo ) {
123  if ( !isset( $this->results[$fileName] ) ) {
124  continue;
125  }
126  if ( !$foundStart && $startFile !== false && $fileName !== $startFile ) {
127  $testIndex += count( $this->results[$fileName] );
128  continue;
129  }
130  foreach ( $fileInfo['tests'] as $testInfo ) {
131  if ( !isset( $this->results[$fileName][$testInfo['desc']] ) ) {
132  continue;
133  }
134  $result = $this->results[$fileName][$testInfo['desc']];
135  $testIndex++;
136  if ( !$foundStart && $startTest !== false ) {
137  if ( $testInfo['desc'] !== $startTest ) {
138  continue;
139  }
140  $foundStart = true;
141  }
142 
143  $this->handleFailure( $testIndex, $testInfo, $result );
144  }
145  }
146 
147  if ( !$foundStart ) {
148  print "Could not find the test after a restart, did you rename it?";
149  unset( $this->session['startFile'] );
150  unset( $this->session['startTest'] );
151  $this->showResults();
152  }
153  print "All done\n";
154  }
155 
156  protected function heading( $text ) {
157  $term = new AnsiTermColorer;
158  $heading = "─── $text ";
159  $heading .= str_repeat( '─', $this->termWidth - mb_strlen( $heading ) );
160  $heading = $term->color( 34 ) . $heading . $term->reset() . "\n";
161  return $heading;
162  }
163 
164  protected function unifiedDiff( $left, $right ) {
165  $fromLines = explode( "\n", $left );
166  $toLines = explode( "\n", $right );
167  $formatter = new UnifiedDiffFormatter;
168  return $formatter->format( new Diff( $fromLines, $toLines ) );
169  }
170 
171  protected function handleFailure( $index, $testInfo, $result ) {
172  $term = new AnsiTermColorer;
173  $div1 = $term->color( 34 ) . str_repeat( '━', $this->termWidth ) .
174  $term->reset() . "\n";
175  $div2 = $term->color( 34 ) . str_repeat( '─', $this->termWidth ) .
176  $term->reset() . "\n";
177 
178  print $div1;
179  print "Failure $index/{$this->numFailed}: {$testInfo['file']} line {$testInfo['line']}\n" .
180  "{$testInfo['desc']}\n";
181 
182  print $this->heading( 'Input' );
183  print "{$testInfo['input']}\n";
184 
185  print $this->heading( 'Alternating expected/actual output' );
186  print $this->alternatingAligned( $result->expected, $result->actual );
187 
188  print $this->heading( 'Diff' );
189 
190  $dwdiff = $this->dwdiff( $result->expected, $result->actual );
191  if ( $dwdiff !== false ) {
192  $diff = $dwdiff;
193  } else {
194  $diff = $this->unifiedDiff( $result->expected, $result->actual );
195  }
196  print $diff;
197 
198  if ( $testInfo['options'] || $testInfo['config'] ) {
199  print $this->heading( 'Options / Config' );
200  if ( $testInfo['options'] ) {
201  print $testInfo['options'] . "\n";
202  }
203  if ( $testInfo['config'] ) {
204  print $testInfo['config'] . "\n";
205  }
206  }
207 
208  print $div2;
209  print "What do you want to do?\n";
210  $specs = [
211  '[R]eload code and run again',
212  '[U]pdate source file, copy actual to expected',
213  '[I]gnore' ];
214 
215  if ( strpos( $testInfo['options'], ' tidy' ) === false ) {
216  if ( empty( $testInfo['isSubtest'] ) ) {
217  $specs[] = "Enable [T]idy";
218  }
219  } else {
220  $specs[] = 'Disable [T]idy';
221  }
222 
223  if ( !empty( $testInfo['isSubtest'] ) ) {
224  $specs[] = 'Delete [s]ubtest';
225  }
226  $specs[] = '[D]elete test';
227  $specs[] = '[Q]uit';
228 
229  $options = [];
230  foreach ( $specs as $spec ) {
231  if ( !preg_match( '/^(.*\[)(.)(\].*)$/', $spec, $m ) ) {
232  throw new MWException( 'Invalid option spec: ' . $spec );
233  }
234  print '* ' . $m[1] . $term->color( 35 ) . $m[2] . $term->color( 0 ) . $m[3] . "\n";
235  $options[strtoupper( $m[2] )] = true;
236  }
237 
238  do {
239  $response = $this->readconsole();
240  $cmdResult = false;
241  if ( $response === false ) {
242  exit( 0 );
243  }
244 
245  $response = strtoupper( trim( $response ) );
246  if ( !isset( $options[$response] ) ) {
247  print "Invalid response, please enter a single letter from the list above\n";
248  continue;
249  }
250 
251  switch ( strtoupper( trim( $response ) ) ) {
252  case 'R':
253  $cmdResult = $this->reload( $testInfo );
254  break;
255  case 'U':
256  $cmdResult = $this->update( $testInfo, $result );
257  break;
258  case 'I':
259  return;
260  case 'T':
261  $cmdResult = $this->switchTidy( $testInfo );
262  break;
263  case 'S':
264  $cmdResult = $this->deleteSubtest( $testInfo );
265  break;
266  case 'D':
267  $cmdResult = $this->deleteTest( $testInfo );
268  break;
269  case 'Q':
270  exit( 0 );
271  }
272  } while ( !$cmdResult );
273  }
274 
275  protected function dwdiff( $expected, $actual ) {
276  if ( !is_executable( '/usr/bin/dwdiff' ) ) {
277  return false;
278  }
279 
280  $markers = [
281  "\n" => '¶',
282  ' ' => '·',
283  "\t" => '→'
284  ];
285  $markedExpected = strtr( $expected, $markers );
286  $markedActual = strtr( $actual, $markers );
287  $diff = $this->unifiedDiff( $markedExpected, $markedActual );
288 
289  $tempFile = tmpfile();
290  fwrite( $tempFile, $diff );
291  fseek( $tempFile, 0 );
292  $pipes = [];
293  $proc = proc_open( '/usr/bin/dwdiff -Pc --diff-input',
294  [ 0 => $tempFile, 1 => [ 'pipe', 'w' ], 2 => STDERR ],
295  $pipes );
296 
297  if ( !$proc ) {
298  return false;
299  }
300 
301  $result = stream_get_contents( $pipes[1] );
302  proc_close( $proc );
303  fclose( $tempFile );
304  return $result;
305  }
306 
307  protected function alternatingAligned( $expectedStr, $actualStr ) {
308  $expectedLines = explode( "\n", $expectedStr );
309  $actualLines = explode( "\n", $actualStr );
310  $maxLines = max( count( $expectedLines ), count( $actualLines ) );
311  $result = '';
312  for ( $i = 0; $i < $maxLines; $i++ ) {
313  if ( $i < count( $expectedLines ) ) {
314  $expectedLine = $expectedLines[$i];
315  $expectedChunks = str_split( $expectedLine, $this->termWidth - 3 );
316  } else {
317  $expectedChunks = [];
318  }
319 
320  if ( $i < count( $actualLines ) ) {
321  $actualLine = $actualLines[$i];
322  $actualChunks = str_split( $actualLine, $this->termWidth - 3 );
323  } else {
324  $actualChunks = [];
325  }
326 
327  $maxChunks = max( count( $expectedChunks ), count( $actualChunks ) );
328 
329  for ( $j = 0; $j < $maxChunks; $j++ ) {
330  if ( isset( $expectedChunks[$j] ) ) {
331  $result .= "E: " . $expectedChunks[$j];
332  if ( $j === count( $expectedChunks ) - 1 ) {
333  $result .= "¶";
334  }
335  $result .= "\n";
336  } else {
337  $result .= "E:\n";
338  }
339  $result .= "\33[4m" . // underline
340  "A: ";
341  if ( isset( $actualChunks[$j] ) ) {
342  $result .= $actualChunks[$j];
343  if ( $j === count( $actualChunks ) - 1 ) {
344  $result .= "¶";
345  }
346  }
347  $result .= "\33[0m\n"; // reset
348  }
349  }
350  return $result;
351  }
352 
353  protected function reload( $testInfo ) {
354  global $argv;
355  pcntl_exec( PHP_BINARY, [
356  $argv[0],
357  '--session-data',
358  json_encode( [
359  'startFile' => $testInfo['file'],
360  'startTest' => $testInfo['desc']
361  ] + $this->session ) ] );
362 
363  print "pcntl_exec() failed\n";
364  return false;
365  }
366 
367  protected function findTest( $file, $testInfo ) {
368  $initialPart = '';
369  for ( $i = 1; $i < $testInfo['line']; $i++ ) {
370  $line = fgets( $file );
371  if ( $line === false ) {
372  print "Error reading from file\n";
373  return false;
374  }
375  $initialPart .= $line;
376  }
377 
378  $line = fgets( $file );
379  if ( !preg_match( '/^!!\s*test/', $line ) ) {
380  print "Test has moved, cannot edit\n";
381  return false;
382  }
383 
384  $testPart = $line;
385 
386  $desc = fgets( $file );
387  if ( trim( $desc ) !== $testInfo['desc'] ) {
388  print "Description does not match, cannot edit\n";
389  return false;
390  }
391  $testPart .= $desc;
392  return [ $initialPart, $testPart ];
393  }
394 
395  protected function getOutputFileName( $inputFileName ) {
396  if ( is_writable( $inputFileName ) ) {
397  $outputFileName = $inputFileName;
398  } else {
399  $outputFileName = wfTempDir() . '/' . basename( $inputFileName );
400  print "Cannot write to input file, writing to $outputFileName instead\n";
401  }
402  return $outputFileName;
403  }
404 
405  protected function editTest( $fileName, $deletions, $changes ) {
406  $text = file_get_contents( $fileName );
407  if ( $text === false ) {
408  print "Unable to open test file!";
409  return false;
410  }
411  $result = TestFileEditor::edit( $text, $deletions, $changes,
412  function ( $msg ) {
413  print "$msg\n";
414  }
415  );
416  if ( is_writable( $fileName ) ) {
417  file_put_contents( $fileName, $result );
418  print "Wrote updated file\n";
419  } else {
420  print "Cannot write updated file, here is a patch you can paste:\n\n";
421  print "--- {$fileName}\n" .
422  "+++ {$fileName}~\n" .
423  $this->unifiedDiff( $text, $result ) .
424  "\n";
425  }
426  }
427 
428  protected function update( $testInfo, $result ) {
429  $this->editTest( $testInfo['file'],
430  [], // deletions
431  [ // changes
432  $testInfo['test'] => [
433  $testInfo['resultSection'] => [
434  'op' => 'update',
435  'value' => $result->actual . "\n"
436  ]
437  ]
438  ]
439  );
440  }
441 
442  protected function deleteTest( $testInfo ) {
443  $this->editTest( $testInfo['file'],
444  [ $testInfo['test'] ], // deletions
445  [] // changes
446  );
447  }
448 
449  protected function switchTidy( $testInfo ) {
450  $resultSection = $testInfo['resultSection'];
451  if ( in_array( $resultSection, [ 'html/php', 'html/*', 'html', 'result' ] ) ) {
452  $newSection = 'html+tidy';
453  } elseif ( in_array( $resultSection, [ 'html/php+tidy', 'html+tidy' ] ) ) {
454  $newSection = 'html';
455  } else {
456  print "Unrecognised result section name \"$resultSection\"";
457  return;
458  }
459 
460  $this->editTest( $testInfo['file'],
461  [], // deletions
462  [ // changes
463  $testInfo['test'] => [
464  $resultSection => [
465  'op' => 'rename',
466  'value' => $newSection
467  ]
468  ]
469  ]
470  );
471  }
472 
473  protected function deleteSubtest( $testInfo ) {
474  $this->editTest( $testInfo['file'],
475  [], // deletions
476  [ // changes
477  $testInfo['test'] => [
478  $testInfo['resultSection'] => [
479  'op' => 'delete'
480  ]
481  ]
482  ]
483  );
484  }
485 }
486 
487 $maintClass = 'ParserEditTests';
ParserEditTests\$recorder
$recorder
Definition: editTests.php:14
ParserEditTests\showResults
showResults()
Definition: editTests.php:110
ParserEditTests\__construct
__construct()
Default constructor.
Definition: editTests.php:20
Maintenance\getTermSize
static getTermSize()
Get the terminal size as a two-element array where the first element is the width (number of columns)...
Definition: Maintenance.php:1593
ParserEditTests\$numExecuted
$numExecuted
Definition: editTests.php:16
ParserEditTests\$testFiles
$testFiles
Definition: editTests.php:12
$response
this hook is for auditing only $response
Definition: hooks.txt:783
ParserEditTests\dwdiff
dwdiff( $expected, $actual)
Definition: editTests.php:275
ParserEditTests\showProgress
showProgress()
Definition: editTests.php:101
ParserEditTests\update
update( $testInfo, $result)
Definition: editTests.php:428
ParserEditTests\findTest
findTest( $file, $testInfo)
Definition: editTests.php:367
ParserEditTests\setupFileData
setupFileData()
Definition: editTests.php:64
Maintenance\readconsole
static readconsole( $prompt='> ')
Prompt the console for input.
Definition: Maintenance.php:1524
ParserTestRunner\getParserTestFiles
static getParserTestFiles()
Get list of filenames to extension and core parser tests.
Definition: ParserTestRunner.php:167
RUN_MAINTENANCE_IF_MAIN
require_once RUN_MAINTENANCE_IF_MAIN
Definition: maintenance.txt:50
ParserEditTests\alternatingAligned
alternatingAligned( $expectedStr, $actualStr)
Definition: editTests.php:307
ParserEditTests\runTests
runTests()
Definition: editTests.php:74
Maintenance
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: maintenance.txt:39
$result
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImgAuthModifyHeaders':Executed just before a file is streamed to a user via img_auth.php, allowing headers to be modified beforehand. $title:LinkTarget object & $headers:HTTP headers(name=> value, names are case insensitive). Two headers get special handling:If-Modified-Since(value must be a valid HTTP date) and Range(must be of the form "bytes=(\d*-\d*)") will be honored when streaming the file. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. Return false to stop further processing of the tag $reader:XMLReader object $logInfo:Array of information 'ImportHandlePageXMLTag':When parsing a XML tag in a page. Return false to stop further processing of the tag $reader:XMLReader object & $pageInfo:Array of information 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. Return false to stop further processing of the tag $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. Return false to stop further processing of the tag $reader:XMLReader object 'ImportHandleUnknownUser':When a user doesn 't exist locally, this hook is called to give extensions an opportunity to auto-create it. If the auto-creation is successful, return false. $name:User name 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. Return false to stop further processing of the tag $reader:XMLReader object $revisionInfo:Array of information 'ImportLogInterwikiLink':Hook to change the interwiki link used in log entries and edit summaries for transwiki imports. & $fullInterwikiPrefix:Interwiki prefix, may contain colons. & $pageTitle:String that contains page title. 'ImportSources':Called when reading from the $wgImportSources configuration variable. Can be used to lazy-load the import sources list. & $importSources:The value of $wgImportSources. Modify as necessary. See the comment in DefaultSettings.php for the detail of how to structure this array. 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. & $title:Title object for the current page & $request:WebRequest & $ignoreRedirect:boolean to skip redirect check & $target:Title/string of redirect target & $article:Article object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) & $article:article(object) being checked 'IsTrustedProxy':Override the result of IP::isTrustedProxy() & $ip:IP being check & $result:Change this value to override the result of IP::isTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of Sanitizer::validateEmail(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetMagic':DEPRECATED! Use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language & $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetSpecialPageAliases':DEPRECATED! Use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language & $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code:language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Array with elements of the form "language:title" in the order that they will be output. & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LanguageSelector':Hook to change the language selector available on a page. $out:The output page. $cssClassName:CSS class name of the language selector. 'LinkBegin':DEPRECATED! Use HtmlPageLinkRendererBegin instead. Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition: hooks.txt:1993
ParserEditTests\$termWidth
$termWidth
Definition: editTests.php:11
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:37
ParserEditTests\$runner
$runner
Definition: editTests.php:15
$term
For QUnit the mediawiki tests qunit testrunner dependency will be added to any module whereas SearchGetNearMatch runs after $term
Definition: hooks.txt:2845
MWException
MediaWiki exception.
Definition: MWException.php:26
$argv
global $argv
Definition: autoload.ide.php:24
ParserEditTests\unifiedDiff
unifiedDiff( $left, $right)
Definition: editTests.php:164
ParserEditTests\deleteTest
deleteTest( $testInfo)
Definition: editTests.php:442
TestRecorder
Interface to record parser test results.
Definition: TestRecorder.php:35
Maintenance\addOption
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
Definition: Maintenance.php:219
TestSetup\applyInitialConfig
static applyInitialConfig()
This should be called before Setup.php, e.g.
Definition: TestSetup.php:11
ParserEditTests\$numFailed
$numFailed
Definition: editTests.php:18
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:95
AnsiTermColorer
Terminal that supports ANSI escape sequences.
Definition: MWTerm.php:39
ParserEditTests\editTest
editTest( $fileName, $deletions, $changes)
Definition: editTests.php:405
UnifiedDiffFormatter
A formatter that outputs unified diffs.
Definition: UnifiedDiffFormatter.php:31
$options
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 & $options
Definition: hooks.txt:2001
ParserEditTests\handleFailure
handleFailure( $index, $testInfo, $result)
Definition: editTests.php:171
$line
$line
Definition: cdb.php:59
Maintenance\requireTestsAutoloader
static requireTestsAutoloader()
Call this to set up the autoloader to allow classes to be used from the tests directory.
Definition: Maintenance.php:1620
TestFileEditor\edit
static edit( $text, array $deletions, array $changes, $warningCallback=null)
Definition: TestFileEditor.php:12
$maintClass
$maintClass
Definition: editTests.php:487
ParserEditTests\$testCount
$testCount
Definition: editTests.php:13
ParserEditTests\getOutputFileName
getOutputFileName( $inputFileName)
Definition: editTests.php:395
TestFileReader\read
static read( $file, array $options=[])
Definition: TestFileReader.php:38
DiffFormatter\format
format( $diff)
Format a diff.
Definition: DiffFormatter.php:62
print
print
Definition: opensearch_desc.php:46
wfTempDir
wfTempDir()
Tries to get the system directory for temporary files.
Definition: GlobalFunctions.php:2057
Maintenance\getOption
getOption( $name, $default=null)
Get an option, or return the default.
Definition: Maintenance.php:254
ParserEditTests\reload
reload( $testInfo)
Definition: editTests.php:353
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:22
ParserEditTests\heading
heading( $text)
Definition: editTests.php:156
ParserEditTests\deleteSubtest
deleteSubtest( $testInfo)
Definition: editTests.php:473
ParserEditTests\finalSetup
finalSetup()
Handle some last-minute setup here.
Definition: editTests.php:28
Maintenance\hasOption
hasOption( $name)
Checks to see if a particular param exists.
Definition: Maintenance.php:240
ParserEditTests\switchTidy
switchTidy( $testInfo)
Definition: editTests.php:449
ParserEditTests\execute
execute()
Do the actual work.
Definition: editTests.php:34
ParserEditTests\$numSkipped
$numSkipped
Definition: editTests.php:17
ParserTestRunner
Definition: ParserTestRunner.php:36
ParserEditTests
Interactive parser test runner and test file editor.
Definition: editTests.php:10
Diff
Class representing a 'diff' between two sequences of strings.
Definition: DairikiDiff.php:200