Index: trunk/phase3/tests/parserTests.php |
— | — | @@ -1,92 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * MediaWiki parser test suite |
5 | | - * |
6 | | - * Copyright © 2004 Brion Vibber <brion@pobox.com> |
7 | | - * http://www.mediawiki.org/ |
8 | | - * |
9 | | - * This program is free software; you can redistribute it and/or modify |
10 | | - * it under the terms of the GNU General Public License as published by |
11 | | - * the Free Software Foundation; either version 2 of the License, or |
12 | | - * (at your option) any later version. |
13 | | - * |
14 | | - * This program is distributed in the hope that it will be useful, |
15 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | - * GNU General Public License for more details. |
18 | | - * |
19 | | - * You should have received a copy of the GNU General Public License along |
20 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
21 | | - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
22 | | - * http://www.gnu.org/copyleft/gpl.html |
23 | | - * |
24 | | - * @file |
25 | | - * @ingroup Testing |
26 | | - */ |
27 | | - |
28 | | -$options = array( 'quick', 'color', 'quiet', 'help', 'show-output', 'record', 'run-disabled' ); |
29 | | -$optionsWithArgs = array( 'regex', 'seed', 'setversion' ); |
30 | | - |
31 | | -require_once( dirname( __FILE__ ) . '/../maintenance/commandLine.inc' ); |
32 | | - |
33 | | -if ( isset( $options['help'] ) ) { |
34 | | - echo <<<ENDS |
35 | | -MediaWiki $wgVersion parser test suite |
36 | | -Usage: php parserTests.php [options...] |
37 | | - |
38 | | -Options: |
39 | | - --quick Suppress diff output of failed tests |
40 | | - --quiet Suppress notification of passed tests (shows only failed tests) |
41 | | - --show-output Show expected and actual output |
42 | | - --color[=yes|no] Override terminal detection and force color output on or off |
43 | | - use wgCommandLineDarkBg = true; if your term is dark |
44 | | - --regex Only run tests whose descriptions which match given regex |
45 | | - --file=<testfile> Run test cases from a custom file instead of parserTests.txt |
46 | | - --record Record tests in database |
47 | | - --compare Compare with recorded results, without updating the database. |
48 | | - --setversion When using --record, set the version string to use (useful |
49 | | - with git-svn so that you can get the exact revision) |
50 | | - --keep-uploads Re-use the same upload directory for each test, don't delete it |
51 | | - --fuzz Do a fuzz test instead of a normal test |
52 | | - --seed <n> Start the fuzz test from the specified seed |
53 | | - --help Show this help message |
54 | | - --run-disabled run disabled tests |
55 | | - --upload Upload test results to remote wiki (per \$wgParserTestRemote) |
56 | | - |
57 | | -ENDS; |
58 | | - exit( 0 ); |
59 | | -} |
60 | | - |
61 | | -# Cases of weird db corruption were encountered when running tests on earlyish |
62 | | -# versions of SQLite |
63 | | -if ( $wgDBtype == 'sqlite' ) { |
64 | | - $db = wfGetDB( DB_MASTER ); |
65 | | - $version = $db->getServerVersion(); |
66 | | - if ( version_compare( $version, '3.6' ) < 0 ) { |
67 | | - die( "Parser tests require SQLite version 3.6 or later, you have $version\n" ); |
68 | | - } |
69 | | -} |
70 | | - |
71 | | -# There is a convention that the parser should never |
72 | | -# refer to $wgTitle directly, but instead use the title |
73 | | -# passed to it. |
74 | | -$wgTitle = Title::newFromText( 'Parser test script do not use' ); |
75 | | -$tester = new ParserTest($options); |
76 | | - |
77 | | -if ( isset( $options['file'] ) ) { |
78 | | - $files = array( $options['file'] ); |
79 | | -} else { |
80 | | - // Default parser tests and any set from extensions or local config |
81 | | - $files = $wgParserTestFiles; |
82 | | -} |
83 | | - |
84 | | -# Print out software version to assist with locating regressions |
85 | | -$version = SpecialVersion::getVersion(); |
86 | | -echo( "This is MediaWiki version {$version}.\n\n" ); |
87 | | - |
88 | | -if ( isset( $options['fuzz'] ) ) { |
89 | | - $tester->fuzzTest( $files ); |
90 | | -} else { |
91 | | - $ok = $tester->runTestsFromFiles( $files ); |
92 | | - exit ( $ok ? 0 : 1 ); |
93 | | -} |
Index: trunk/phase3/tests/testHelpers.inc |
— | — | @@ -1,653 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -/** |
5 | | - * @ingroup Testing |
6 | | - * |
7 | | - * Set of classes to help with test output and such. Right now pretty specific |
8 | | - * to the parser tests but could be more useful one day :) |
9 | | - * |
10 | | - * @todo Fixme: Make this more generic |
11 | | - */ |
12 | | - |
13 | | -class AnsiTermColorer { |
14 | | - function __construct() { |
15 | | - } |
16 | | - |
17 | | - /** |
18 | | - * Return ANSI terminal escape code for changing text attribs/color |
19 | | - * |
20 | | - * @param $color String: semicolon-separated list of attribute/color codes |
21 | | - * @return String |
22 | | - */ |
23 | | - public function color( $color ) { |
24 | | - global $wgCommandLineDarkBg; |
25 | | - |
26 | | - $light = $wgCommandLineDarkBg ? "1;" : "0;"; |
27 | | - |
28 | | - return "\x1b[{$light}{$color}m"; |
29 | | - } |
30 | | - |
31 | | - /** |
32 | | - * Return ANSI terminal escape code for restoring default text attributes |
33 | | - * |
34 | | - * @return String |
35 | | - */ |
36 | | - public function reset() { |
37 | | - return $this->color( 0 ); |
38 | | - } |
39 | | -} |
40 | | - |
41 | | -/* A colour-less terminal */ |
42 | | -class DummyTermColorer { |
43 | | - public function color( $color ) { |
44 | | - return ''; |
45 | | - } |
46 | | - |
47 | | - public function reset() { |
48 | | - return ''; |
49 | | - } |
50 | | -} |
51 | | - |
52 | | -class TestRecorder { |
53 | | - var $parent; |
54 | | - var $term; |
55 | | - |
56 | | - function __construct( $parent ) { |
57 | | - $this->parent = $parent; |
58 | | - $this->term = $parent->term; |
59 | | - } |
60 | | - |
61 | | - function start() { |
62 | | - $this->total = 0; |
63 | | - $this->success = 0; |
64 | | - } |
65 | | - |
66 | | - function record( $test, $result ) { |
67 | | - $this->total++; |
68 | | - $this->success += ( $result ? 1 : 0 ); |
69 | | - } |
70 | | - |
71 | | - function end() { |
72 | | - // dummy |
73 | | - } |
74 | | - |
75 | | - function report() { |
76 | | - if ( $this->total > 0 ) { |
77 | | - $this->reportPercentage( $this->success, $this->total ); |
78 | | - } else { |
79 | | - wfDie( "No tests found.\n" ); |
80 | | - } |
81 | | - } |
82 | | - |
83 | | - function reportPercentage( $success, $total ) { |
84 | | - $ratio = wfPercent( 100 * $success / $total ); |
85 | | - print $this->term->color( 1 ) . "Passed $success of $total tests ($ratio)... "; |
86 | | - |
87 | | - if ( $success == $total ) { |
88 | | - print $this->term->color( 32 ) . "ALL TESTS PASSED!"; |
89 | | - } else { |
90 | | - $failed = $total - $success ; |
91 | | - print $this->term->color( 31 ) . "$failed tests failed!"; |
92 | | - } |
93 | | - |
94 | | - print $this->term->reset() . "\n"; |
95 | | - |
96 | | - return ( $success == $total ); |
97 | | - } |
98 | | -} |
99 | | - |
100 | | -class DbTestPreviewer extends TestRecorder { |
101 | | - protected $lb; // /< Database load balancer |
102 | | - protected $db; // /< Database connection to the main DB |
103 | | - protected $curRun; // /< run ID number for the current run |
104 | | - protected $prevRun; // /< run ID number for the previous run, if any |
105 | | - protected $results; // /< Result array |
106 | | - |
107 | | - /** |
108 | | - * This should be called before the table prefix is changed |
109 | | - */ |
110 | | - function __construct( $parent ) { |
111 | | - parent::__construct( $parent ); |
112 | | - |
113 | | - $this->lb = wfGetLBFactory()->newMainLB(); |
114 | | - // This connection will have the wiki's table prefix, not parsertest_ |
115 | | - $this->db = $this->lb->getConnection( DB_MASTER ); |
116 | | - } |
117 | | - |
118 | | - /** |
119 | | - * Set up result recording; insert a record for the run with the date |
120 | | - * and all that fun stuff |
121 | | - */ |
122 | | - function start() { |
123 | | - parent::start(); |
124 | | - |
125 | | - if ( ! $this->db->tableExists( 'testrun' ) |
126 | | - or ! $this->db->tableExists( 'testitem' ) ) |
127 | | - { |
128 | | - print "WARNING> `testrun` table not found in database.\n"; |
129 | | - $this->prevRun = false; |
130 | | - } else { |
131 | | - // We'll make comparisons against the previous run later... |
132 | | - $this->prevRun = $this->db->selectField( 'testrun', 'MAX(tr_id)' ); |
133 | | - } |
134 | | - |
135 | | - $this->results = array(); |
136 | | - } |
137 | | - |
138 | | - function record( $test, $result ) { |
139 | | - parent::record( $test, $result ); |
140 | | - $this->results[$test] = $result; |
141 | | - } |
142 | | - |
143 | | - function report() { |
144 | | - if ( $this->prevRun ) { |
145 | | - // f = fail, p = pass, n = nonexistent |
146 | | - // codes show before then after |
147 | | - $table = array( |
148 | | - 'fp' => 'previously failing test(s) now PASSING! :)', |
149 | | - 'pn' => 'previously PASSING test(s) removed o_O', |
150 | | - 'np' => 'new PASSING test(s) :)', |
151 | | - |
152 | | - 'pf' => 'previously passing test(s) now FAILING! :(', |
153 | | - 'fn' => 'previously FAILING test(s) removed O_o', |
154 | | - 'nf' => 'new FAILING test(s) :(', |
155 | | - 'ff' => 'still FAILING test(s) :(', |
156 | | - ); |
157 | | - |
158 | | - $prevResults = array(); |
159 | | - |
160 | | - $res = $this->db->select( 'testitem', array( 'ti_name', 'ti_success' ), |
161 | | - array( 'ti_run' => $this->prevRun ), __METHOD__ ); |
162 | | - |
163 | | - foreach ( $res as $row ) { |
164 | | - if ( !$this->parent->regex |
165 | | - || preg_match( "/{$this->parent->regex}/i", $row->ti_name ) ) |
166 | | - { |
167 | | - $prevResults[$row->ti_name] = $row->ti_success; |
168 | | - } |
169 | | - } |
170 | | - |
171 | | - $combined = array_keys( $this->results + $prevResults ); |
172 | | - |
173 | | - # Determine breakdown by change type |
174 | | - $breakdown = array(); |
175 | | - foreach ( $combined as $test ) { |
176 | | - if ( !isset( $prevResults[$test] ) ) { |
177 | | - $before = 'n'; |
178 | | - } elseif ( $prevResults[$test] == 1 ) { |
179 | | - $before = 'p'; |
180 | | - } else /* if ( $prevResults[$test] == 0 )*/ { |
181 | | - $before = 'f'; |
182 | | - } |
183 | | - |
184 | | - if ( !isset( $this->results[$test] ) ) { |
185 | | - $after = 'n'; |
186 | | - } elseif ( $this->results[$test] == 1 ) { |
187 | | - $after = 'p'; |
188 | | - } else /*if ( $this->results[$test] == 0 ) */ { |
189 | | - $after = 'f'; |
190 | | - } |
191 | | - |
192 | | - $code = $before . $after; |
193 | | - |
194 | | - if ( isset( $table[$code] ) ) { |
195 | | - $breakdown[$code][$test] = $this->getTestStatusInfo( $test, $after ); |
196 | | - } |
197 | | - } |
198 | | - |
199 | | - # Write out results |
200 | | - foreach ( $table as $code => $label ) { |
201 | | - if ( !empty( $breakdown[$code] ) ) { |
202 | | - $count = count( $breakdown[$code] ); |
203 | | - printf( "\n%4d %s\n", $count, $label ); |
204 | | - |
205 | | - foreach ( $breakdown[$code] as $differing_test_name => $statusInfo ) { |
206 | | - print " * $differing_test_name [$statusInfo]\n"; |
207 | | - } |
208 | | - } |
209 | | - } |
210 | | - } else { |
211 | | - print "No previous test runs to compare against.\n"; |
212 | | - } |
213 | | - |
214 | | - print "\n"; |
215 | | - parent::report(); |
216 | | - } |
217 | | - |
218 | | - /** |
219 | | - * Returns a string giving information about when a test last had a status change. |
220 | | - * Could help to track down when regressions were introduced, as distinct from tests |
221 | | - * which have never passed (which are more change requests than regressions). |
222 | | - */ |
223 | | - private function getTestStatusInfo( $testname, $after ) { |
224 | | - // If we're looking at a test that has just been removed, then say when it first appeared. |
225 | | - if ( $after == 'n' ) { |
226 | | - $changedRun = $this->db->selectField ( 'testitem', |
227 | | - 'MIN(ti_run)', |
228 | | - array( 'ti_name' => $testname ), |
229 | | - __METHOD__ ); |
230 | | - $appear = $this->db->selectRow ( 'testrun', |
231 | | - array( 'tr_date', 'tr_mw_version' ), |
232 | | - array( 'tr_id' => $changedRun ), |
233 | | - __METHOD__ ); |
234 | | - |
235 | | - return "First recorded appearance: " |
236 | | - . date( "d-M-Y H:i:s", strtotime ( $appear->tr_date ) ) |
237 | | - . ", " . $appear->tr_mw_version; |
238 | | - } |
239 | | - |
240 | | - // Otherwise, this test has previous recorded results. |
241 | | - // See when this test last had a different result to what we're seeing now. |
242 | | - $conds = array( |
243 | | - 'ti_name' => $testname, |
244 | | - 'ti_success' => ( $after == 'f' ? "1" : "0" ) ); |
245 | | - |
246 | | - if ( $this->curRun ) { |
247 | | - $conds[] = "ti_run != " . $this->db->addQuotes ( $this->curRun ); |
248 | | - } |
249 | | - |
250 | | - $changedRun = $this->db->selectField ( 'testitem', 'MAX(ti_run)', $conds, __METHOD__ ); |
251 | | - |
252 | | - // If no record of ever having had a different result. |
253 | | - if ( is_null ( $changedRun ) ) { |
254 | | - if ( $after == "f" ) { |
255 | | - return "Has never passed"; |
256 | | - } else { |
257 | | - return "Has never failed"; |
258 | | - } |
259 | | - } |
260 | | - |
261 | | - // Otherwise, we're looking at a test whose status has changed. |
262 | | - // (i.e. it used to work, but now doesn't; or used to fail, but is now fixed.) |
263 | | - // In this situation, give as much info as we can as to when it changed status. |
264 | | - $pre = $this->db->selectRow ( 'testrun', |
265 | | - array( 'tr_date', 'tr_mw_version' ), |
266 | | - array( 'tr_id' => $changedRun ), |
267 | | - __METHOD__ ); |
268 | | - $post = $this->db->selectRow ( 'testrun', |
269 | | - array( 'tr_date', 'tr_mw_version' ), |
270 | | - array( "tr_id > " . $this->db->addQuotes ( $changedRun ) ), |
271 | | - __METHOD__, |
272 | | - array( "LIMIT" => 1, "ORDER BY" => 'tr_id' ) |
273 | | - ); |
274 | | - |
275 | | - if ( $post ) { |
276 | | - $postDate = date( "d-M-Y H:i:s", strtotime ( $post->tr_date ) ) . ", {$post->tr_mw_version}"; |
277 | | - } else { |
278 | | - $postDate = 'now'; |
279 | | - } |
280 | | - |
281 | | - return ( $after == "f" ? "Introduced" : "Fixed" ) . " between " |
282 | | - . date( "d-M-Y H:i:s", strtotime ( $pre->tr_date ) ) . ", " . $pre->tr_mw_version |
283 | | - . " and $postDate"; |
284 | | - |
285 | | - } |
286 | | - |
287 | | - /** |
288 | | - * Commit transaction and clean up for result recording |
289 | | - */ |
290 | | - function end() { |
291 | | - $this->lb->commitMasterChanges(); |
292 | | - $this->lb->closeAll(); |
293 | | - parent::end(); |
294 | | - } |
295 | | - |
296 | | -} |
297 | | - |
298 | | -class DbTestRecorder extends DbTestPreviewer { |
299 | | - var $version; |
300 | | - |
301 | | - /** |
302 | | - * Set up result recording; insert a record for the run with the date |
303 | | - * and all that fun stuff |
304 | | - */ |
305 | | - function start() { |
306 | | - global $wgDBtype; |
307 | | - $this->db->begin(); |
308 | | - |
309 | | - if ( ! $this->db->tableExists( 'testrun' ) |
310 | | - or ! $this->db->tableExists( 'testitem' ) ) |
311 | | - { |
312 | | - print "WARNING> `testrun` table not found in database. Trying to create table.\n"; |
313 | | - $this->db->sourceFile( $this->db->patchPath( 'patch-testrun.sql' ) ); |
314 | | - echo "OK, resuming.\n"; |
315 | | - } |
316 | | - |
317 | | - parent::start(); |
318 | | - |
319 | | - $this->db->insert( 'testrun', |
320 | | - array( |
321 | | - 'tr_date' => $this->db->timestamp(), |
322 | | - 'tr_mw_version' => $this->version, |
323 | | - 'tr_php_version' => phpversion(), |
324 | | - 'tr_db_version' => $this->db->getServerVersion(), |
325 | | - 'tr_uname' => php_uname() |
326 | | - ), |
327 | | - __METHOD__ ); |
328 | | - if ( $wgDBtype === 'postgres' ) { |
329 | | - $this->curRun = $this->db->currentSequenceValue( 'testrun_id_seq' ); |
330 | | - } else { |
331 | | - $this->curRun = $this->db->insertId(); |
332 | | - } |
333 | | - } |
334 | | - |
335 | | - /** |
336 | | - * Record an individual test item's success or failure to the db |
337 | | - * |
338 | | - * @param $test String |
339 | | - * @param $result Boolean |
340 | | - */ |
341 | | - function record( $test, $result ) { |
342 | | - parent::record( $test, $result ); |
343 | | - |
344 | | - $this->db->insert( 'testitem', |
345 | | - array( |
346 | | - 'ti_run' => $this->curRun, |
347 | | - 'ti_name' => $test, |
348 | | - 'ti_success' => $result ? 1 : 0, |
349 | | - ), |
350 | | - __METHOD__ ); |
351 | | - } |
352 | | -} |
353 | | - |
354 | | -class RemoteTestRecorder extends TestRecorder { |
355 | | - function start() { |
356 | | - parent::start(); |
357 | | - |
358 | | - $this->results = array(); |
359 | | - $this->ping( 'running' ); |
360 | | - } |
361 | | - |
362 | | - function record( $test, $result ) { |
363 | | - parent::record( $test, $result ); |
364 | | - $this->results[$test] = (bool)$result; |
365 | | - } |
366 | | - |
367 | | - function end() { |
368 | | - $this->ping( 'complete', $this->results ); |
369 | | - parent::end(); |
370 | | - } |
371 | | - |
372 | | - /** |
373 | | - * Inform a CodeReview instance that we've started or completed a test run... |
374 | | - * |
375 | | - * @param $status string: "running" - tell it we've started |
376 | | - * "complete" - provide test results array |
377 | | - * "abort" - something went horribly awry |
378 | | - * @param $results array of test name => true/false |
379 | | - */ |
380 | | - function ping( $status, $results = false ) { |
381 | | - global $wgParserTestRemote, $IP; |
382 | | - |
383 | | - $remote = $wgParserTestRemote; |
384 | | - $revId = SpecialVersion::getSvnRevision( $IP ); |
385 | | - $jsonResults = FormatJson::encode( $results ); |
386 | | - |
387 | | - if ( !$remote ) { |
388 | | - print "Can't do remote upload without configuring \$wgParserTestRemote!\n"; |
389 | | - exit( 1 ); |
390 | | - } |
391 | | - |
392 | | - // Generate a hash MAC to validate our credentials |
393 | | - $message = array( |
394 | | - $remote['repo'], |
395 | | - $remote['suite'], |
396 | | - $revId, |
397 | | - $status, |
398 | | - ); |
399 | | - |
400 | | - if ( $status == "complete" ) { |
401 | | - $message[] = $jsonResults; |
402 | | - } |
403 | | - $hmac = hash_hmac( "sha1", implode( "|", $message ), $remote['secret'] ); |
404 | | - |
405 | | - $postData = array( |
406 | | - 'action' => 'codetestupload', |
407 | | - 'format' => 'json', |
408 | | - 'repo' => $remote['repo'], |
409 | | - 'suite' => $remote['suite'], |
410 | | - 'rev' => $revId, |
411 | | - 'status' => $status, |
412 | | - 'hmac' => $hmac, |
413 | | - ); |
414 | | - |
415 | | - if ( $status == "complete" ) { |
416 | | - $postData['results'] = $jsonResults; |
417 | | - } |
418 | | - |
419 | | - $response = $this->post( $remote['api-url'], $postData ); |
420 | | - |
421 | | - if ( $response === false ) { |
422 | | - print "CodeReview info upload failed to reach server.\n"; |
423 | | - exit( 1 ); |
424 | | - } |
425 | | - |
426 | | - $responseData = FormatJson::decode( $response, true ); |
427 | | - |
428 | | - if ( !is_array( $responseData ) ) { |
429 | | - print "CodeReview API response not recognized...\n"; |
430 | | - wfDebug( "Unrecognized CodeReview API response: $response\n" ); |
431 | | - exit( 1 ); |
432 | | - } |
433 | | - |
434 | | - if ( isset( $responseData['error'] ) ) { |
435 | | - $code = $responseData['error']['code']; |
436 | | - $info = $responseData['error']['info']; |
437 | | - print "CodeReview info upload failed: $code $info\n"; |
438 | | - exit( 1 ); |
439 | | - } |
440 | | - } |
441 | | - |
442 | | - function post( $url, $data ) { |
443 | | - return Http::post( $url, array( 'postData' => $data ) ); |
444 | | - } |
445 | | -} |
446 | | - |
447 | | -class TestFileIterator implements Iterator { |
448 | | - private $file; |
449 | | - private $fh; |
450 | | - private $parserTest; /* An instance of ParserTest (parserTests.php) or MediaWikiParserTest (phpunit) */ |
451 | | - private $index = 0; |
452 | | - private $test; |
453 | | - private $lineNum; |
454 | | - private $eof; |
455 | | - |
456 | | - function __construct( $file, $parserTest = null ) { |
457 | | - global $IP; |
458 | | - |
459 | | - $this->file = $file; |
460 | | - $this->fh = fopen( $this->file, "rt" ); |
461 | | - |
462 | | - if ( !$this->fh ) { |
463 | | - wfDie( "Couldn't open file '$file'\n" ); |
464 | | - } |
465 | | - |
466 | | - $this->parserTest = $parserTest; |
467 | | - |
468 | | - if ( $this->parserTest ) { |
469 | | - $this->parserTest->showRunFile( wfRelativePath( $this->file, $IP ) ); |
470 | | - } |
471 | | - |
472 | | - $this->lineNum = $this->index = 0; |
473 | | - } |
474 | | - |
475 | | - function rewind() { |
476 | | - if ( fseek( $this->fh, 0 ) ) { |
477 | | - wfDie( "Couldn't fseek to the start of '$this->file'\n" ); |
478 | | - } |
479 | | - |
480 | | - $this->index = -1; |
481 | | - $this->lineNum = 0; |
482 | | - $this->eof = false; |
483 | | - $this->next(); |
484 | | - |
485 | | - return true; |
486 | | - } |
487 | | - |
488 | | - function current() { |
489 | | - return $this->test; |
490 | | - } |
491 | | - |
492 | | - function key() { |
493 | | - return $this->index; |
494 | | - } |
495 | | - |
496 | | - function next() { |
497 | | - if ( $this->readNextTest() ) { |
498 | | - $this->index++; |
499 | | - return true; |
500 | | - } else { |
501 | | - $this->eof = true; |
502 | | - } |
503 | | - } |
504 | | - |
505 | | - function valid() { |
506 | | - return $this->eof != true; |
507 | | - } |
508 | | - |
509 | | - function readNextTest() { |
510 | | - $data = array(); |
511 | | - $section = null; |
512 | | - |
513 | | - while ( false !== ( $line = fgets( $this->fh ) ) ) { |
514 | | - $this->lineNum++; |
515 | | - $matches = array(); |
516 | | - |
517 | | - if ( preg_match( '/^!!\s*(\w+)/', $line, $matches ) ) { |
518 | | - $section = strtolower( $matches[1] ); |
519 | | - |
520 | | - if ( $section == 'endarticle' ) { |
521 | | - if ( !isset( $data['text'] ) ) { |
522 | | - wfDie( "'endarticle' without 'text' at line {$this->lineNum} of $this->file\n" ); |
523 | | - } |
524 | | - |
525 | | - if ( !isset( $data['article'] ) ) { |
526 | | - wfDie( "'endarticle' without 'article' at line {$this->lineNum} of $this->file\n" ); |
527 | | - } |
528 | | - |
529 | | - if ( $this->parserTest ) { |
530 | | - $this->parserTest->addArticle( ParserTest::chomp( $data['article'] ), $data['text'], $this->lineNum ); |
531 | | - } else { |
532 | | - wfDie("Cannot add an article without a parserTest instance"); |
533 | | - ParserTest::addArticle( $data['article'], $data['text'], $this->lineNum ); |
534 | | - } |
535 | | - $data = array(); |
536 | | - $section = null; |
537 | | - |
538 | | - continue; |
539 | | - } |
540 | | - |
541 | | - if ( $section == 'endhooks' ) { |
542 | | - if ( !isset( $data['hooks'] ) ) { |
543 | | - wfDie( "'endhooks' without 'hooks' at line {$this->lineNum} of $this->file\n" ); |
544 | | - } |
545 | | - |
546 | | - foreach ( explode( "\n", $data['hooks'] ) as $line ) { |
547 | | - $line = trim( $line ); |
548 | | - |
549 | | - if ( $line ) { |
550 | | - if ( $this->parserTest && !$this->parserTest->requireHook( $line ) ) { |
551 | | - return false; |
552 | | - } |
553 | | - } |
554 | | - } |
555 | | - |
556 | | - $data = array(); |
557 | | - $section = null; |
558 | | - |
559 | | - continue; |
560 | | - } |
561 | | - |
562 | | - if ( $section == 'endfunctionhooks' ) { |
563 | | - if ( !isset( $data['functionhooks'] ) ) { |
564 | | - wfDie( "'endfunctionhooks' without 'functionhooks' at line {$this->lineNum} of $this->file\n" ); |
565 | | - } |
566 | | - |
567 | | - foreach ( explode( "\n", $data['functionhooks'] ) as $line ) { |
568 | | - $line = trim( $line ); |
569 | | - |
570 | | - if ( $line ) { |
571 | | - if ( $this->parserTest && !$this->parserTest->requireFunctionHook( $line ) ) { |
572 | | - return false; |
573 | | - } |
574 | | - } |
575 | | - } |
576 | | - |
577 | | - $data = array(); |
578 | | - $section = null; |
579 | | - |
580 | | - continue; |
581 | | - } |
582 | | - |
583 | | - if ( $section == 'end' ) { |
584 | | - if ( !isset( $data['test'] ) ) { |
585 | | - wfDie( "'end' without 'test' at line {$this->lineNum} of $this->file\n" ); |
586 | | - } |
587 | | - |
588 | | - if ( !isset( $data['input'] ) ) { |
589 | | - wfDie( "'end' without 'input' at line {$this->lineNum} of $this->file\n" ); |
590 | | - } |
591 | | - |
592 | | - if ( !isset( $data['result'] ) ) { |
593 | | - wfDie( "'end' without 'result' at line {$this->lineNum} of $this->file\n" ); |
594 | | - } |
595 | | - |
596 | | - if ( !isset( $data['options'] ) ) { |
597 | | - $data['options'] = ''; |
598 | | - } |
599 | | - |
600 | | - if ( !isset( $data['config'] ) ) |
601 | | - $data['config'] = ''; |
602 | | - |
603 | | - if ( $this->parserTest |
604 | | - && ( ( preg_match( '/\\bdisabled\\b/i', $data['options'] ) && !$this->parserTest->runDisabled ) |
605 | | - || !preg_match( "/" . $this->parserTest->regex . "/i", $data['test'] ) ) ) { |
606 | | - # disabled test |
607 | | - $data = array(); |
608 | | - $section = null; |
609 | | - |
610 | | - continue; |
611 | | - } |
612 | | - |
613 | | - global $wgUseTeX; |
614 | | - |
615 | | - if ( $this->parserTest && |
616 | | - preg_match( '/\\bmath\\b/i', $data['options'] ) && !$wgUseTeX ) { |
617 | | - # don't run math tests if $wgUseTeX is set to false in LocalSettings |
618 | | - $data = array(); |
619 | | - $section = null; |
620 | | - |
621 | | - continue; |
622 | | - } |
623 | | - |
624 | | - if ( $this->parserTest ) { |
625 | | - $this->test = array( |
626 | | - 'test' => ParserTest::chomp( $data['test'] ), |
627 | | - 'input' => ParserTest::chomp( $data['input'] ), |
628 | | - 'result' => ParserTest::chomp( $data['result'] ), |
629 | | - 'options' => ParserTest::chomp( $data['options'] ), |
630 | | - 'config' => ParserTest::chomp( $data['config'] ) ); |
631 | | - } else { |
632 | | - $this->test['test'] = $data['test']; |
633 | | - } |
634 | | - |
635 | | - return true; |
636 | | - } |
637 | | - |
638 | | - if ( isset ( $data[$section] ) ) { |
639 | | - wfDie( "duplicate section '$section' at line {$this->lineNum} of $this->file\n" ); |
640 | | - } |
641 | | - |
642 | | - $data[$section] = ''; |
643 | | - |
644 | | - continue; |
645 | | - } |
646 | | - |
647 | | - if ( $section ) { |
648 | | - $data[$section] .= $line; |
649 | | - } |
650 | | - } |
651 | | - |
652 | | - return false; |
653 | | - } |
654 | | -} |