Parser test improvements:
[lhc/web/wiklou.git] / maintenance / parserTests.php
1 <?php
2 # Copyright (C) 2004 Brion Vibber <brion@pobox.com>
3 # http://www.mediawiki.org/
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 # http://www.gnu.org/copyleft/gpl.html
19
20 /**
21 * @todo Make this more independent of the configuration (and if possible the database)
22 * @todo document
23 * @package MediaWiki
24 * @subpackage Maintenance
25 */
26
27 /** */
28 require_once( 'commandLine.inc' );
29 include_once( 'InitialiseMessages.inc' );
30
31 $wgTitle = Title::newFromText( 'Parser test script' );
32
33 class ParserTest {
34 function runTestsFromFile( $filename ) {
35 $infile = fopen( $filename, 'rt' );
36 if( !$infile ) {
37 die( "Couldn't open parserTests.txt\n" );
38 }
39
40 $data = array();
41 $section = null;
42 $success = 0;
43 $total = 0;
44 $n = 0;
45 while( false !== ($line = fgets( $infile ) ) ) {
46 $n++;
47 if( preg_match( '/^!!\s*(\w+)/', $line, $matches ) ) {
48 $section = strtolower( $matches[1] );
49 if( $section == 'end' ) {
50 if (isset ($data['disabled'])) {
51 # disabled test
52 $data = array();
53 $section = null;
54 continue;
55 }
56 if( !isset( $data['test'] ) ) {
57 die( "'end' without 'test' at line $n\n" );
58 }
59 if( !isset( $data['input'] ) ) {
60 die( "'end' without 'input' at line $n\n" );
61 }
62 if( !isset( $data['result'] ) ) {
63 die( "'end' without 'result' at line $n\n" );
64 }
65 if( $this->runTest(
66 rtrim( $data['test'] ),
67 rtrim( $data['input'] ),
68 $this->resultTransform(rtrim( $data['result'] ) ) ) ) {
69 $success++;
70 }
71 $total++;
72 $data = array();
73 $section = null;
74 continue;
75 }
76 $data[$section] = '';
77 continue;
78 }
79 if( $section ) {
80 $data[$section] .= $line;
81 }
82 }
83 if( $total > 0 ) {
84 $ratio = IntVal( 100.0 * $success / $total );
85 print "\nPassed $success of $total tests ($ratio%)\n";
86 return ($success == $total);
87 } else {
88 die( "No tests found.\n" );
89 }
90 }
91
92 /**
93 * Substitute simple variables to allow for slightly more
94 * sophisticated tests.
95 * @access private
96 */
97 function resultTransform($text) {
98 $rep = array (
99 '__SCRIPT__' => $GLOBALS['wgScript']
100 );
101 $text = str_replace(array_keys($rep), array_values($rep), $text);
102 return $text;
103 }
104
105 /**
106 * @param string $input Wikitext to try rendering
107 * @param string $result Result to output
108 * @return bool
109 */
110 function runTest( $desc, $input, $result ) {
111 print "Running test $desc...";
112
113 $this->setupGlobals();
114
115 $user =& new User();
116 $options =& ParserOptions::newFromUser( $user );
117 $parser =& new Parser();
118 $title =& Title::makeTitle( NS_MAIN, 'Parser_test' );
119
120 $output =& $parser->parse( $input, $title, $options );
121
122 $html = $output->getText();
123 # $languageLinks = $output->getLanguageLinks();
124 # $categoryLinks = $output->getCategoryLinks();
125
126 $op = new OutputPage();
127 $op->replaceLinkHolders($html);
128
129 global $wgUseTidy;
130 if ($wgUseTidy) {
131 # Using Parser here is probably theoretically
132 # wrong, because we shouldn't use Parser to
133 # validate itself, but this should be safe
134 # in practice.
135 $result = Parser::tidy($result);
136 }
137
138 $this->teardownGlobals();
139
140 if( rtrim($result) === rtrim($html) ) {
141 return $this->showSuccess( $desc );
142 } else {
143 return $this->showFailure( $desc, $result, $html );
144 }
145 }
146
147 function setupGlobals() {
148 static $settings = array(
149 'wgServer' => 'http://localhost',
150 'wgScript' => '/index.php',
151 'wgScriptPath' => '/',
152 'wgArticlePath' => '/wiki/$1',
153 );
154 $this->savedGlobals = array();
155 foreach( $settings as $var => $val ) {
156 $this->savedGlobals[$var] = $GLOBALS[$var];
157 $GLOBALS[$var] = $val;
158 }
159 }
160
161 function teardownGlobals() {
162 foreach( $this->savedGlobals as $var => $val ) {
163 $GLOBALS[$var] = $val;
164 }
165 }
166
167 function showSuccess( $desc ) {
168 print "ok\n";
169 return true;
170 }
171
172 function showFailure( $desc, $result, $html ) {
173 print "FAILED\n";
174 #print "!! Expected:\n$result\n";
175 #print "!! Received:\n$html\n!!\n";
176 print $this->quickDiff( $result, $html );
177 return false;
178 }
179
180 function quickDiff( $input, $output ) {
181 $prefix = "/tmp/mwParser-" . mt_rand();
182
183 $infile = "$prefix-in";
184 $this->dumpToFile( $input, $infile );
185
186 $outfile = "$prefix-out";
187 $this->dumpToFile( $output, $outfile );
188
189 $diff = `diff -u $infile $outfile`;
190 unlink( $infile );
191 unlink( $outfile );
192
193 return $diff;
194 }
195
196 function dumpToFile( $data, $filename ) {
197 $file = fopen( $filename, "wt" );
198 fwrite( $file, $data );
199 fclose( $file );
200 }
201 }
202
203 $tester =& new ParserTest();
204
205 # Note: the command line setup changes the current working directory
206 # to the parent, which is why we have to put the subdir here:
207 $ok = $tester->runTestsFromFile( 'maintenance/parserTests.txt' );
208
209 exit ($ok ? 0 : -1);
210
211 ?>