r17534 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r17533‎ | r17534 | r17535 >
Date:14:36, 11 November 2006
Author:brion
Status:old
Tags:
Comment:
* Make the set of default parser test input files extensible via
$wgParserTestFiles. This can now be appended to by extensions or local
configuration files so that extension or custom tests can be automatically
run along with the main batch.
* Cite.php now adds its parser tests to the default set when enabled
Modified paths:
  • /trunk/extensions/Cite/Cite.php (modified) (history)
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/maintenance/parserTests.inc (modified) (history)
  • /trunk/phase3/maintenance/parserTests.php (modified) (history)

Diff [purge]

Index: trunk/phase3/maintenance/parserTests.inc
@@ -85,6 +85,9 @@
8686 break;
8787 }
8888 }
 89+ $this->term = $this->color
 90+ ? new AnsiTermColorer( $this->lightcolor )
 91+ : new DummyTermColorer();
8992
9093 $this->showDiffs = !isset( $options['quick'] );
9194 $this->quiet = isset( $options['quiet'] );
@@ -99,9 +102,9 @@
100103 }
101104
102105 if( isset( $options['record'] ) ) {
103 - $this->recorder = new TestRecorder();
 106+ $this->recorder = new DbTestRecorder( $this->term );
104107 } else {
105 - $this->recorder = new DummyTestRecorder();
 108+ $this->recorder = new TestRecorder( $this->term );
106109 }
107110
108111 $this->hooks = array();
@@ -122,39 +125,53 @@
123126 }
124127
125128 /**
126 - * Run a series of tests listed in the given text file.
 129+ * Run a series of tests listed in the given text files.
127130 * Each test consists of a brief description, wikitext input,
128131 * and the expected HTML output.
129132 *
130133 * Prints status updates on stdout and counts up the total
131134 * number and percentage of passed tests.
132135 *
133 - * @param string $filename
 136+ * @param array of strings $filenames
134137 * @return bool True if passed all tests, false if any tests failed.
135138 * @public
136139 */
137 - function runTestsFromFile( $filename ) {
 140+ function runTestsFromFiles( $filenames ) {
 141+ $this->recorder->start();
 142+ $ok = true;
 143+ foreach( $filenames as $filename ) {
 144+ $ok = $this->runFile( $filename ) && $ok;
 145+ }
 146+ $this->recorder->end();
 147+ $this->recorder->report();
 148+ return $ok;
 149+ }
 150+
 151+ private function runFile( $filename ) {
138152 $infile = fopen( $filename, 'rt' );
139153 if( !$infile ) {
140154 wfDie( "Couldn't open $filename\n" );
 155+ } else {
 156+ print $this->term->color( 1 ) .
 157+ "Reading tests from \"$filename\"..." .
 158+ $this->term->reset() .
 159+ "\n";
141160 }
142161
143162 $data = array();
144163 $section = null;
145 - $success = 0;
146 - $total = 0;
147164 $n = 0;
148 - $this->recorder->start();
 165+ $ok = true;
149166 while( false !== ($line = fgets( $infile ) ) ) {
150167 $n++;
151168 if( preg_match( '/^!!\s*(\w+)/', $line, $matches ) ) {
152169 $section = strtolower( $matches[1] );
153170 if( $section == 'endarticle') {
154171 if( !isset( $data['text'] ) ) {
155 - wfDie( "'endarticle' without 'text' at line $n\n" );
 172+ wfDie( "'endarticle' without 'text' at line $n of $filename\n" );
156173 }
157174 if( !isset( $data['article'] ) ) {
158 - wfDie( "'endarticle' without 'article' at line $n\n" );
 175+ wfDie( "'endarticle' without 'article' at line $n of $filename\n" );
159176 }
160177 $this->addArticle($this->chomp($data['article']), $this->chomp($data['text']), $n);
161178 $data = array();
@@ -163,7 +180,7 @@
164181 }
165182 if( $section == 'endhooks' ) {
166183 if( !isset( $data['hooks'] ) ) {
167 - wfDie( "'endhooks' without 'hooks' at line $n\n" );
 184+ wfDie( "'endhooks' without 'hooks' at line $n of $filename\n" );
168185 }
169186 foreach( explode( "\n", $data['hooks'] ) as $line ) {
170187 $line = trim( $line );
@@ -177,7 +194,7 @@
178195 }
179196 if( $section == 'endfunctionhooks' ) {
180197 if( !isset( $data['functionhooks'] ) ) {
181 - wfDie( "'endfunctionhooks' without 'functionhooks' at line $n\n" );
 198+ wfDie( "'endfunctionhooks' without 'functionhooks' at line $n of $filename\n" );
182199 }
183200 foreach( explode( "\n", $data['functionhooks'] ) as $line ) {
184201 $line = trim( $line );
@@ -191,13 +208,13 @@
192209 }
193210 if( $section == 'end' ) {
194211 if( !isset( $data['test'] ) ) {
195 - wfDie( "'end' without 'test' at line $n\n" );
 212+ wfDie( "'end' without 'test' at line $n of $filename\n" );
196213 }
197214 if( !isset( $data['input'] ) ) {
198 - wfDie( "'end' without 'input' at line $n\n" );
 215+ wfDie( "'end' without 'input' at line $n of $filename\n" );
199216 }
200217 if( !isset( $data['result'] ) ) {
201 - wfDie( "'end' without 'result' at line $n\n" );
 218+ wfDie( "'end' without 'result' at line $n of $filename\n" );
202219 }
203220 if( !isset( $data['options'] ) ) {
204221 $data['options'] = '';
@@ -217,17 +234,14 @@
218235 $this->chomp( $data['input'] ),
219236 $this->chomp( $data['result'] ),
220237 $this->chomp( $data['options'] ) );
221 - if( $result ) {
222 - $success++;
223 - }
224 - $total++;
 238+ $ok = $ok && $result;
225239 $this->recorder->record( $this->chomp( $data['test'] ), $result );
226240 $data = array();
227241 $section = null;
228242 continue;
229243 }
230244 if ( isset ($data[$section] ) ) {
231 - wfDie( "duplicate section '$section' at line $n\n" );
 245+ wfDie( "duplicate section '$section' at line $n of $filename\n" );
232246 }
233247 $data[$section] = '';
234248 continue;
@@ -236,23 +250,8 @@
237251 $data[$section] .= $line;
238252 }
239253 }
240 - $this->recorder->end();
241 -
242254 print "\n";
243 - $this->recorder->report();
244 - if( $total > 0 ) {
245 - $ratio = wfPercent( 100 * $success / $total );
246 - print $this->termColor( 1 ) . "Passed $success of $total tests ($ratio) ";
247 - if( $success == $total ) {
248 - print $this->termColor( 32 ) . "PASSED!";
249 - } else {
250 - print $this->termColor( 31 ) . "FAILED!";
251 - }
252 - print $this->termReset() . "\n";
253 - return ($success == $total);
254 - } else {
255 - wfDie( "No tests found.\n" );
256 - }
 255+ return $ok;
257256 }
258257
259258 /**
@@ -604,7 +603,7 @@
605604 */
606605 function showSuccess( $desc ) {
607606 if( !$this->quiet ) {
608 - print $this->termColor( '1;32' ) . 'PASSED' . $this->termReset() . "\n";
 607+ print $this->term->color( '1;32' ) . 'PASSED' . $this->term->reset() . "\n";
609608 }
610609 return true;
611610 }
@@ -625,7 +624,7 @@
626625 # test, in case it succeeded. Show it now:
627626 $this->showTesting( $desc );
628627 }
629 - print $this->termColor( '1;31' ) . 'FAILED!' . $this->termReset() . "\n";
 628+ print $this->term->color( '1;31' ) . 'FAILED!' . $this->term->reset() . "\n";
630629 if ( $this->showOutput ) {
631630 print "--- Expected ---\n$result\n--- Actual ---\n$html\n";
632631 }
@@ -679,33 +678,6 @@
680679 }
681680
682681 /**
683 - * Return ANSI terminal escape code for changing text attribs/color,
684 - * or empty string if color output is disabled.
685 - *
686 - * @param string $color Semicolon-separated list of attribute/color codes
687 - * @return string
688 - * @private
689 - */
690 - function termColor( $color ) {
691 - if($this->lightcolor) {
692 - return $this->color ? "\x1b[1;{$color}m" : '';
693 - } else {
694 - return $this->color ? "\x1b[{$color}m" : '';
695 - }
696 - }
697 -
698 - /**
699 - * Return ANSI terminal escape code for restoring default text attributes,
700 - * or empty string if color output is disabled.
701 - *
702 - * @return string
703 - * @private
704 - */
705 - function termReset() {
706 - return $this->color ? "\x1b[0m" : '';
707 - }
708 -
709 - /**
710682 * Colorize unified diff output if set for ANSI color output.
711683 * Subtractions are colored blue, additions red.
712684 *
@@ -716,8 +688,8 @@
717689 function colorDiff( $text ) {
718690 return preg_replace(
719691 array( '/^(-.*)$/m', '/^(\+.*)$/m' ),
720 - array( $this->termColor( 34 ) . '$1' . $this->termReset(),
721 - $this->termColor( 31 ) . '$1' . $this->termReset() ),
 692+ array( $this->term->color( 34 ) . '$1' . $this->term->reset(),
 693+ $this->term->color( 31 ) . '$1' . $this->term->reset() ),
722694 $text );
723695 }
724696
@@ -821,35 +793,79 @@
822794 $start = max( 0, $position - 10 );
823795 $before = $position - $start;
824796 $fragment = '...' .
825 - $this->termColor( 34 ) .
 797+ $this->term->color( 34 ) .
826798 substr( $text, $start, $before ) .
827 - $this->termColor( 0 ) .
828 - $this->termColor( 31 ) .
829 - $this->termColor( 1 ) .
 799+ $this->term->color( 0 ) .
 800+ $this->term->color( 31 ) .
 801+ $this->term->color( 1 ) .
830802 substr( $text, $position, 1 ) .
831 - $this->termColor( 0 ) .
832 - $this->termColor( 34 ) .
 803+ $this->term->color( 0 ) .
 804+ $this->term->color( 34 ) .
833805 substr( $text, $position + 1, 9 ) .
834 - $this->termColor( 0 ) .
 806+ $this->term->color( 0 ) .
835807 '...';
836808 $display = str_replace( "\n", ' ', $fragment );
837809 $caret = ' ' .
838810 str_repeat( ' ', $before ) .
839 - $this->termColor( 31 ) .
 811+ $this->term->color( 31 ) .
840812 '^' .
841 - $this->termColor( 0 );
 813+ $this->term->color( 0 );
842814 return "$display\n$caret";
843815 }
844816
845817 }
846818
847 -class DummyTestRecorder {
 819+class AnsiTermColorer {
 820+ function __construct( $light ) {
 821+ $this->light = $light;
 822+ }
 823+
 824+ /**
 825+ * Return ANSI terminal escape code for changing text attribs/color
 826+ *
 827+ * @param string $color Semicolon-separated list of attribute/color codes
 828+ * @return string
 829+ * @private
 830+ */
 831+ function color( $color ) {
 832+ $light = $this->light ? "1;" : "";
 833+ return "\x1b[{$light}{$color}m";
 834+ }
 835+
 836+ /**
 837+ * Return ANSI terminal escape code for restoring default text attributes
 838+ *
 839+ * @return string
 840+ * @private
 841+ */
 842+ function reset() {
 843+ return "\x1b[0m";
 844+ }
 845+}
 846+
 847+class DummyTermColorer {
 848+ function color( $color ) {
 849+ return '';
 850+ }
 851+
 852+ function reset() {
 853+ return '';
 854+ }
 855+}
 856+
 857+class TestRecorder {
 858+ function __construct( $term ) {
 859+ $this->term = $term;
 860+ }
 861+
848862 function start() {
849 - // dummy
 863+ $this->total = 0;
 864+ $this->success = 0;
850865 }
851866
852867 function record( $test, $result ) {
853 - // dummy
 868+ $this->total++;
 869+ $this->success += ($result ? 1 : 0);
854870 }
855871
856872 function end() {
@@ -857,16 +873,33 @@
858874 }
859875
860876 function report() {
861 - // dummy
 877+ if( $this->total > 0 ) {
 878+ $this->reportPercentage( $this->success, $this->total );
 879+ } else {
 880+ wfDie( "No tests found.\n" );
 881+ }
862882 }
 883+
 884+ function reportPercentage( $success, $total ) {
 885+ $ratio = wfPercent( 100 * $success / $total );
 886+ print $this->term->color( 1 ) . "Passed $success of $total tests ($ratio) ";
 887+ if( $success == $total ) {
 888+ print $this->term->color( 32 ) . "PASSED!";
 889+ } else {
 890+ print $this->term->color( 31 ) . "FAILED!";
 891+ }
 892+ print $this->term->reset() . "\n";
 893+ return ($success == $total);
 894+ }
863895 }
864896
865 -class TestRecorder {
 897+class DbTestRecorder extends TestRecorder {
866898 var $db; ///< Database connection to the main DB
867899 var $curRun; ///< run ID number for the current run
868900 var $prevRun; ///< run ID number for the previous run, if any
869901
870 - function __construct() {
 902+ function __construct( $term ) {
 903+ parent::__construct( $term );
871904 $this->db = wfGetDB( DB_MASTER );
872905 }
873906
@@ -875,6 +908,8 @@
876909 * and all that fun stuff
877910 */
878911 function start() {
 912+ parent::start();
 913+
879914 $this->db->begin();
880915
881916 // We'll make comparisons against the previous run later...
@@ -898,6 +933,7 @@
899934 * @param bool $result
900935 */
901936 function record( $test, $result ) {
 937+ parent::record( $test, $result );
902938 $this->db->insert( 'testitem',
903939 array(
904940 'ti_run' => $this->curRun,
@@ -912,6 +948,7 @@
913949 */
914950 function end() {
915951 $this->db->commit();
 952+ parent::end();
916953 }
917954
918955 function report() {
@@ -935,6 +972,7 @@
936973 } else {
937974 print "No previous test runs to compare against.\n";
938975 }
 976+ parent::report();
939977 }
940978
941979 /**
Index: trunk/phase3/maintenance/parserTests.php
@@ -54,13 +54,12 @@
5555 $tester = new ParserTest();
5656
5757 if( isset( $options['file'] ) ) {
58 - $file = $options['file'];
 58+ $files = array( $options['file'] );
5959 } else {
60 - # Note: the command line setup changes the current working directory
61 - # to the parent, which is why we have to put the subdir here:
62 - $file = $IP.'/maintenance/parserTests.txt';
 60+ // Default parser tests and any set from extensions or local config
 61+ $files = $wgParserTestFiles;
6362 }
64 -$ok = $tester->runTestsFromFile( $file );
 63+$ok = $tester->runTestsFromFiles( $files );
6564
6665 exit ($ok ? 0 : -1);
6766 ?>
Index: trunk/phase3/includes/DefaultSettings.php
@@ -2308,4 +2308,17 @@
23092309 $wgEnableAPI = true;
23102310 $wgEnableWriteAPI = false;
23112311
 2312+/**
 2313+ * Parser test suite files to be run by parserTests.php when no specific
 2314+ * filename is passed to it.
 2315+ *
 2316+ * Extensions may add their own tests to this array, or site-local tests
 2317+ * may be added via LocalSettings.php
 2318+ *
 2319+ * Use full paths.
 2320+ */
 2321+$wgParserTestFiles = array(
 2322+ "$IP/maintenance/parserTests.txt",
 2323+);
 2324+
23122325 ?>
Index: trunk/phase3/RELEASE-NOTES
@@ -167,8 +167,11 @@
168168 compare changes against the previous run.
169169 Additional tables 'testrun' and 'testitem' are in maintenance/testRunner.sql,
170170 source this and pass --record option to parserTests.php
 171+* Make the set of default parser test input files extensible via
 172+ $wgParserTestFiles. This can now be appended to by extensions or local
 173+ configuration files so that extension or custom tests can be automatically
 174+ run along with the main batch.
171175
172 -
173176 == Languages updated ==
174177
175178 * Bishnupriya Manipuri (bpy)
Index: trunk/extensions/Cite/Cite.php
@@ -26,6 +26,7 @@
2727 'description' => 'adds <nowiki><ref[ name=id]></nowiki> and <nowiki><references/></nowiki> tags, for citations',
2828 'url' => 'http://meta.wikimedia.org/wiki/Cite/Cite.php'
2929 );
 30+$wgParserTestFiles[] = dirname( __FILE__ ) . "/citeParserTests.txt";
3031
3132 /**
3233 * Error codes, first array = internal errors; second array = user errors