3 * WikiTest is the base class for all the various
4 * individual tests of the installed wiki, which
5 * will be called by WikiSuite.
8 package com
.piclab
.wikitest
;
9 import com
.meterware
.httpunit
.*;
11 import java
.util
.regex
.*;
13 public class WikiTest
{
15 protected WikiSuite m_suite
= null;
16 protected long m_start
, m_stop
;
17 protected boolean m_verboseflag
= false;
19 /* All subclasses of WikiTest should override testName()
20 * to return a useful name and runTest() to perform the actual
21 * tests. runTest() should return true on success. You can
22 * also overrise initTest() if you like; it gets run before
23 * the individual test timer is started.
26 public String
testName() { return "Error"; }
28 protected int initTest() throws Exception
{
32 protected int runTest() throws Exception
{
37 * This is the primary entry point:
40 public void run( WikiSuite ws
) {
48 /* assert( m_suite != null ); */
50 java
.util
.logging
.Level ll
= null;
51 if ( m_verboseflag
) {
52 ll
= WikiSuite
.setLoggingLevel( java
.util
.logging
.Level
.FINE
);
57 } catch ( Exception e
) {
58 WikiSuite
.error( "Exception (" + e
+ ") initializing test \"" +
64 WikiSuite
.error( "Test \"" + testName() +
65 "\" failed to initialize with code " + result
);
68 WikiSuite
.info( "Started test \"" + testName() + "\"" );
69 m_start
= System
.currentTimeMillis();
73 } catch (Exception e
) {
74 WikiSuite
.error( "Exception (" + e
+ ") running test \"" +
79 m_stop
= System
.currentTimeMillis();
80 double time
= (double)(m_stop
- m_start
) / 1000.0;
82 StringBuffer sb
= new StringBuffer(100);
83 sb
.append( "Test \"" ).append( testName() ).append( "\" " )
84 .append( (result
==0) ?
"Succeeded" : "Failed " ).append( " (" )
85 .append( WikiSuite
.threeDecimals( time
) ).append( " secs)" );
86 WikiSuite
.info( sb
.toString() );
88 if ( m_verboseflag
) {
89 WikiSuite
.setLoggingLevel( ll
);
94 * General utility functions
97 public int fail( int code
) {
98 WikiSuite
.error( "Test \"" + testName() + "\" failed with code " + code
);
102 public void clearCookies() { m_suite
.getConv().clearContents(); }
105 * Encapsulate rules for converting a title to URL form; this
106 * should match the equivalent function in the Wiki code.
109 public static String
titleToUrl( String title
) {
110 StringBuffer sb
= new StringBuffer( title
.length() + 20 );
112 if ( "".equals( title
) ) {
113 title
= WikiSuite
.getMainPage();
116 for (int i
=0; i
<title
.length(); ++i
) {
117 char c
= title
.charAt(i
);
118 if ((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z')) {
120 } else if (c
>= '0' && c
<= '9') {
122 } else if (c
== '.' || c
== '-' || c
== '*' || c
== ':' || c
== '/'
123 || c
== '(' || c
== ')' || c
== '_') {
125 } else if (c
== ' ') {
129 String hex
= "00" + Integer
.toHexString((int)c
);
130 sb
.append(hex
.substring(hex
.length() - 2));
133 return sb
.toString();
136 public static String
viewUrl( String title
, String query
) {
137 StringBuffer url
= new StringBuffer(200);
138 String t
= titleToUrl( title
);
140 url
.append( WikiSuite
.getServer() )
141 .append( WikiSuite
.getScript() ).append( "?title=" ).append( t
)
142 .append( "&" ).append( query
);
143 return url
.toString();
146 public static String
viewUrl( String title
) {
147 StringBuffer url
= new StringBuffer(200);
148 String t
= titleToUrl( title
);
149 String ap
= WikiSuite
.getArticlePath();
151 int p
= ap
.indexOf( "$1" );
154 url
.replace( p
, p
+2, t
);
156 url
.append( WikiSuite
.getServer() )
157 .append( WikiSuite
.getScript() ).append( "?title=" ).append( t
);
159 return url
.toString();
162 public WebResponse
getResponse( String url
)
163 throws WikiSuiteFailureException
{
164 WebResponse r
= null;
168 r
= m_suite
.getConv().getResponse( url
);
169 } catch (org
.xml
.sax
.SAXException e
) {
170 msg
= "Error parsing received page \"" + url
+ "\"";
171 WikiSuite
.warning( msg
);
172 } catch (java
.net
.MalformedURLException e
) {
173 msg
= "Badly formed URL \"" + url
+ "\"";
174 WikiSuite
.fatal( msg
);
175 throw new WikiSuiteFailureException( msg
);
176 } catch (java
.io
.IOException e
) {
177 WikiSuite
.warning( "I/O Error receiving page \"" + url
+ "\"" );
182 public WebResponse
getResponse( WebRequest req
) {
183 WebResponse r
= null;
186 r
= m_suite
.getConv().getResponse( req
);
187 } catch (org
.xml
.sax
.SAXException e
) {
188 WikiSuite
.warning( "Error parsing received page." );
189 } catch (java
.io
.IOException e
) {
190 WikiSuite
.warning( "I/O Error receiving page." );
195 public void showResponseTitle( WebResponse wr
)
196 throws WikiSuiteFailureException
{
201 if ( "Error".equals( t
) || "Database error".equals( t
) ) {
202 throw new WikiSuiteFailureException( "Got wiki error page." );
204 WikiSuite
.fine( "Viewing \"" + t
+ "\"" );
205 } catch (org
.xml
.sax
.SAXException e
) {
206 WikiSuite
.error( "Exception (" + e
+ ")" );
207 throw new WikiSuiteFailureException( "Couldn't parse title." );
211 public WebResponse
viewPage( String title
)
212 throws WikiSuiteFailureException
{
213 WebResponse wr
= getResponse( viewUrl( title
) );
214 showResponseTitle( wr
);
218 public WebResponse
viewPage( String title
, String query
)
219 throws WikiSuiteFailureException
{
220 StringBuffer url
= new StringBuffer( 200 );
221 String t
= titleToUrl( title
);
223 url
.append( m_suite
.getServer() )
224 .append( m_suite
.getScript() ).append( "?title=" )
225 .append( t
).append( "&" ).append( query
);
227 WebResponse wr
= getResponse( url
.toString() );
228 showResponseTitle( wr
);
232 public WebResponse
searchFor( String target
, String query
)
233 throws WikiSuiteFailureException
{
234 StringBuffer url
= new StringBuffer( 200 );
238 t
= java
.net
.URLEncoder
.encode( target
, "UTF-8" );
239 } catch ( java
.io
.UnsupportedEncodingException e
) {
240 throw new WikiSuiteFailureException( e
.toString() );
242 url
.append( m_suite
.getServer() )
243 .append( m_suite
.getScript() ).append( "?search=" )
245 if ( ! "".equals( query
) ) {
246 url
.append( "&" ).append( query
);
248 return getResponse( url
.toString() );
251 public WebResponse
searchFor( String target
)
252 throws WikiSuiteFailureException
{
253 return searchFor( target
, null );
256 public WebResponse
editPage( String title
)
257 throws WikiSuiteFailureException
{
258 return viewPage( title
, "action=edit" );
261 public static WebForm
getFormByName( WebResponse resp
, String name
)
262 throws WikiSuiteFailureException
{
264 WebForm
[] forms
= null;
267 forms
= resp
.getForms();
268 } catch ( org
.xml
.sax
.SAXException e
) {
269 msg
= "Couldn't find form \"" + name
+ "\"";
270 WikiSuite
.error( msg
);
273 for (int i
=0; i
< forms
.length
; ++i
) {
274 Node formNode
= forms
[i
].getDOMSubtree();
275 NamedNodeMap nnm
= formNode
.getAttributes();
276 Node nameNode
= nnm
.getNamedItem( "id" );
278 if (nameNode
== null) continue;
279 if (nameNode
.getNodeValue().equalsIgnoreCase( name
)) {
286 public WebResponse
loginAs( String name
, String password
)
287 throws WikiSuiteFailureException
{
288 WebResponse wr
= null;
289 WebRequest req
= null;
291 wr
= viewPage( "Special:Userlogin" );
293 WebForm loginform
= getFormByName( wr
, "userlogin" );
294 req
= loginform
.getRequest( "wpLoginattempt" );
295 req
.setParameter( "wpName", name
);
296 req
.setParameter( "wpPassword", password
);
297 wr
= getResponse( req
);
299 WikiSuite
.fine( "Logged in as " + name
);
303 public WebResponse
logout()
304 throws WikiSuiteFailureException
{
305 WebResponse wr
= viewPage( "Special:Userlogout" );
310 public WebResponse
deletePage( String title
)
311 throws WikiSuiteFailureException
{
312 WebResponse wr
= null;
314 wr
= loginAs( "WikiSysop", m_suite
.getSysopPass() );
315 wr
= viewPage( title
, "action=delete" );
320 } catch ( org
.xml
.sax
.SAXException e
) {
321 WikiSuite
.error( "Could not parse response to delete request." );
326 if ( rt
.equals( "Internal error" ) ) {
329 /* Can't delete because it doesn't exist: no problem */
332 WebForm delform
= getFormByName( wr
, "deleteconfirm" );
333 WebRequest req
= delform
.getRequest( "wpConfirmB" );
335 req
.setParameter( "wpReason", "Deletion for testing" );
336 req
.setParameter( "wpConfirm", "1" );
338 WebResponse ret
= getResponse( req
);
339 WikiSuite
.fine( "Deleted \"" + title
+ "\"" );
345 public WebResponse
replacePage( String page
, String text
)
346 throws WikiSuiteFailureException
{
347 WebResponse wr
= editPage( page
);
349 WebForm editform
= getFormByName( wr
, "editform" );
350 WebRequest req
= editform
.getRequest( "wpSave" );
351 req
.setParameter( "wpTextbox1", text
);
352 return getResponse( req
);
355 public WebResponse
addText( String page
, String text
)
356 throws WikiSuiteFailureException
{
357 WebResponse wr
= editPage( page
);
359 WebForm editform
= getFormByName( wr
, "editform" );
360 WebRequest req
= editform
.getRequest( "wpSave" );
361 String old
= req
.getParameter( "wpTextbox1" );
363 req
.setParameter( "wpTextbox1", old
+ "\n" + text
);
364 req
.setParameter( "wpSummary", "Wikitest addition to " + page
);
366 return getResponse( req
);
369 public WebRequest
openPrefs() throws WikiSuiteFailureException
{
370 WebResponse wr
= viewPage( "Special:Preferences" );
371 WebForm pform
= getFormByName( wr
, "preferences" );
372 return pform
.getRequest( "wpSaveprefs" );
375 private static Pattern m_startdiv
= null, m_enddiv
= null;
377 public String
getArticle( WebResponse wr
)
378 throws WikiSuiteFailureException
{
383 if ( m_startdiv
== null ) {
384 m_startdiv
= Pattern
.compile( "<div\\s[^>]*id\\s*=\\s*.article[^>]*>",
385 Pattern
.CASE_INSENSITIVE
| Pattern
.DOTALL
);
386 m_enddiv
= Pattern
.compile( "</div[^>]*>",
387 Pattern
.CASE_INSENSITIVE
| Pattern
.DOTALL
);
391 } catch ( java
.io
.IOException e
) {
392 msg
= "Error (" + e
+ ") parsing page.";
393 WikiSuite
.error( msg
);
394 throw new WikiSuiteFailureException( msg
);
396 m
= m_startdiv
.matcher( text
);
398 throw new WikiSuiteFailureException( "Can't find article div start." );
401 text
= text
.substring( m
.end() );
402 m
= m_enddiv
.matcher( text
);
404 throw new WikiSuiteFailureException( "Can't find article div end." );
406 text
= text
.substring( 0, m
.start() );
410 public int checkGoodPatterns( String text
, String
[] pats
) {
414 for ( int i
= 0; i
< pats
.length
; ++i
) {
415 p
= Pattern
.compile( pats
[i
], Pattern
.CASE_INSENSITIVE
);
416 m
= p
.matcher( text
);
418 if ( ! m
.find() ) { return 1 + i
; }
423 public int checkBadPatterns( String text
, String
[] badpats
) {
427 for ( int i
= 0; i
< badpats
.length
; ++i
) {
428 p
= Pattern
.compile( badpats
[i
], Pattern
.CASE_INSENSITIVE
);
429 m
= p
.matcher( text
);
431 if ( m
.find() ) { return 1 + i
; }
437 * The main method of a subclass should be able to just create
438 * an instance of itself and call runSingle() to perform a
439 * standalone test, and we'll handle the commandline and
440 * setting up a suite object, etc. They are of course welcome
441 * to set up a more complex main if they want.
444 public void runSingle( String
[] params
) {
446 * Do command line. For now, just verbose flag.
448 for ( int i
= 0; i
< params
.length
; ++i
) {
449 if ( "-v".equals( params
[i
].substring( 0, 2 ) ) ) {
450 m_verboseflag
= true;
453 run( new WikiSuite() );
456 public static void main( String params
) {
457 System
.out
.println( "WikiTest is not a runnable class." );