KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > test > xml > XMLTestSuiteRunner


1 /*
2
3    Copyright 2001-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.test.xml;
19
20 import java.io.File JavaDoc;
21 import java.io.StringWriter JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23
24 import java.net.URL JavaDoc;
25 import java.net.MalformedURLException JavaDoc;
26
27 import java.util.HashSet JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.Vector JavaDoc;
30
31 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
32 import javax.xml.parsers.DocumentBuilder JavaDoc;
33
34 import org.apache.batik.test.DefaultTestSuite;
35 import org.apache.batik.test.DefaultTestReport;
36 import org.apache.batik.test.TestReport;
37 import org.apache.batik.test.TestSuite;
38 import org.apache.batik.test.Test;
39 import org.apache.batik.test.TestFilter;
40 import org.apache.batik.test.TestException;
41 import org.apache.batik.test.TestReportProcessor;
42
43
44 import org.w3c.dom.Element JavaDoc;
45 import org.w3c.dom.Document JavaDoc;
46 import org.w3c.dom.Node JavaDoc;
47 import org.w3c.dom.NodeList JavaDoc;
48
49 /**
50  * This class can be used to build and run a <tt>TestSuite</tt> from
51  * an XML description following the "XML Test Run" and "XML Test Suite"
52  * formats, whose constants are defined in the <tt>XTRunConstants</tt>
53  * and <tt>XTSConstants</tt> interfaces.
54  *
55  * This class takes a "Test Run" XML description as an input. That
56  * description contains: <br />
57  * + pointers to a number of "Test Suite" XML descriptions,
58  * which contain the definition of the set of <tt>Tests</tt> to be
59  * run and their configuration.<br />
60  * + a description of the set of <tt>TestReportProcessor</tt> and
61  * their configuration that should be used to process the reports
62  * generated by the various <tt>TestSuites</tt>.<br />
63  *
64  * @author <a HREF="mailto:vhardy@apache.org">Vincent Hardy</a>
65  * @version $Id: XMLTestSuiteRunner.java,v 1.13 2004/08/18 07:17:08 vhardy Exp $
66  */

67 public class XMLTestSuiteRunner implements XTRunConstants, XTSConstants{
68     /**
69      * Displayed when no test or testSuite matching the input id was
70      * found.
71      * {0} : unmatched id set
72      */

73     public static final String JavaDoc MESSAGE_UNMATCHED_TEST_IDS
74         = "XMLTestSuiteRunner.messages.unmatched.test.ids";
75
76     /**
77      * An error happened while processing a <tt>TestreportProcessor</tt>
78      * description.
79      * {0} : the <testReportProcessor> "className" attribute value
80      * {1} : exception's class name
81      * {2} : exception's message
82      * {3} : exception's stack trace
83      */

84     public static final String JavaDoc CANNOT_CREATE_TEST_REPORT_PROCESSOR
85         = "xml.XMLTestSuiteRunner.error.cannot.create.test.report.processor";
86
87     /**
88      * An error happened while running the <tt>TestSuite</tt>
89      * {0} : <tt>TestSuite</tt> name
90      * {1} : <tt>TestSuite</tt> class name.
91      * {1} : exception's class name.
92      * {2} : exception's message
93      * {3} : exception's stack trace.
94      */

95     public static final String JavaDoc TEST_SUITE_EXCEPTION
96         = "xml.XMLTestSuiteRunner.test.suite.exception";
97
98     /**
99      * An error happened while processing the <tt>TestReport</tt>
100      * generated by the <tt>TestSuite</tt>
101      * {0} : <tt>TestReportProcessor</tt> class name.
102      * {1} : exception's class name.
103      * {2} : exception's message
104      * {3} : exception's stack trace.
105      */

106     public static final String JavaDoc TEST_REPORT_PROCESSING_EXCEPTION
107         = "xml.XMLTestSuiteRunner.error.test.report.processing.exception";
108
109     /**
110      * Test filter which accepts all tests
111      */

112     public static class AcceptAllTestsFilter implements TestFilter{
113         public Test filter(Test t){
114             return t;
115         }
116     }
117
118     /**
119      * Test filter which only accepts tests with ids matching
120      * the ones passed to its constructor.
121      */

122     public static class IdBasedTestFilter implements TestFilter {
123         protected String JavaDoc[] ids;
124         protected Set JavaDoc unmatchedIds = new HashSet JavaDoc();
125
126         public IdBasedTestFilter(String JavaDoc[] ids){
127             this.ids = ids;
128             for(int i=0; i<ids.length; i++){
129                 unmatchedIds.add(ids[i]);
130             }
131         }
132
133         public String JavaDoc traceUnusedIds(){
134             Object JavaDoc[] ui = unmatchedIds.toArray();
135             StringBuffer JavaDoc sb = null;
136             if(ui != null && ui.length > 0){
137                 sb = new StringBuffer JavaDoc();
138                 sb.append(ui[0].toString());
139                 for(int i=1; i<ui.length; i++){
140                     sb.append(", ");
141                     sb.append(ui[i].toString());
142                 }
143             }
144             return sb != null ? sb.toString() : null;
145         }
146
147         /**
148          * Remove children <tt>Test</tt> instances from the <tt>TestSuite</tt>
149          * if they are filtered out.
150          */

151         public void filterTestSuite(TestSuite ts){
152             Test[] t = ts.getChildrenTests();
153             int nTests = t != null ? t.length : 0;
154             for(int i=0; i<nTests; i++){
155                 if(filter(t[i]) == null){
156                     ts.removeTest(t[i]);
157                 }
158             }
159         }
160
161         /**
162          * Accept a test if one of the ids is found (i.e., an
163          * exact match or a substring) in the <tt>Test</tt>'s
164          * qualified id.
165          * <tt>TestSuite</tt>s are accepted if they have children and
166          * rejected if they have none.
167          */

168         public Test filter(Test t){
169             String JavaDoc id = t.getQualifiedId();
170             boolean isRequested = isRequestedId(id);
171
172             //
173
// First, handle TestSuite children
174
//
175
if(t instanceof TestSuite){
176                 TestSuite ts = (TestSuite)t;
177                 filterTestSuite(ts);
178                 if(ts.getChildrenCount() > 0){
179                     return t;
180                 }
181                 return null;
182             }
183
184             //
185
// Now, handle leaf Tests
186
//
187
if(isRequested){
188                 return t;
189             }
190
191             return null;
192         }
193
194         protected boolean isRequestedId(String JavaDoc id){
195             for(int i=0; i<ids.length; i++){
196                 //
197
// id substring of ids[i]
198
// ======================
199
// if the test identifier (id) is a substring of one of the requested
200
// then the test is one of the requested test parents and should be accepted.
201
// Example: id = "all.B" with requested ids = "all.A all.B.B3"
202
// "all.B" (id) is a substring of "all.B.B3" (ids[1])
203
// Conclusion: id is accepted because it is a parent test of ids[1]
204
//
205
// ids[i] substring of id
206
// ======================
207
// if one of the requested test identifiers (id[i]) is a substring of the
208
// test id, then one of the test children is requested, so the test should
209
// be accepted.
210
// Example: id = "all.B.B3" with requested ids = "all.B"
211
// "all.B" (ids[0]) is a substring of "all.B.B3" (id)
212
// Conclusion: id is accepted because it is a child test of ids[0]
213
//
214
if(ids[i].lastIndexOf(id) == 0){
215                     // System.out.println("accepting " + id + ". It is (or is the a parent of) " + ids[i]);
216
unmatchedIds.remove(ids[i]);
217                     return true;
218                 }
219                 
220                 if(id.lastIndexOf(ids[i]) != -1){
221                     // System.out.println("accepting " + id + " it is (or is a child of) the requested " + ids[i]);
222
unmatchedIds.remove(ids[i]);
223                     return true;
224                 }
225             }
226             return false;
227         }
228
229     }
230
231     /**
232      * Builds an array of <tt>TestReportProcessor</tt> from the input
233      * element, assuming the input element is a <testSuite> instance,
234      */

235     protected TestReportProcessor[] extractTestReportProcessor(Element JavaDoc element)
236         throws TestException
237     {
238         Vector JavaDoc processors = new Vector JavaDoc();
239         
240         NodeList JavaDoc children = element.getChildNodes();
241         if(children != null && children.getLength() > 0){
242             int n = children.getLength();
243             for(int i=0; i<n; i++){
244                 Node JavaDoc child = children.item(i);
245                 if(child.getNodeType() == Node.ELEMENT_NODE){
246                     Element JavaDoc childElement = (Element JavaDoc)child;
247                     String JavaDoc tagName = childElement.getTagName().intern();
248                     if(tagName == XTRun_TEST_REPORT_PROCESSOR_TAG){
249                         processors.addElement(buildProcessor(childElement));
250                     }
251                 }
252             }
253         }
254         
255         TestReportProcessor[] p = null;
256         if(processors.size() > 0){
257             p = new TestReportProcessor[processors.size()];
258             processors.copyInto(p);
259         }
260
261         return p;
262     }
263
264     /**
265      * Builds a <tt>TestResultProcessor</tt> from an element.
266      */

267     protected TestReportProcessor buildProcessor(Element JavaDoc element)
268         throws TestException {
269         try{
270             return (TestReportProcessor)XMLReflect.buildObject(element);
271         }catch(Exception JavaDoc e){
272             StringWriter JavaDoc sw = new StringWriter JavaDoc();
273             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
274             e.printStackTrace(pw);
275             throw new TestException(CANNOT_CREATE_TEST_REPORT_PROCESSOR,
276                                     new Object JavaDoc[] { element.getAttribute(XR_CLASS_ATTRIBUTE),
277                                                    e.getClass().getName(),
278                                                    e.getMessage(),
279                                                    sw.toString() },
280                                     e);
281         }
282     }
283
284     /**
285      * Builds a <tt>TestSuite</tt> from an input element.
286      * This method assumes that element is a &lt;testRun&gt;
287      * instance. The element is scanned for children
288      * &lt;testSuite&gt; elements which is loaded into
289      * a <tt>Test</tt> and composited into a <tt>TestSuite</tt>
290      */

291     protected DefaultTestSuite buildTestRunTestSuite(Element JavaDoc element)
292         throws TestException {
293         DefaultTestSuite testSuite = new DefaultTestSuite();
294
295         //
296
// Set the testRun name and id on the top level testSuite
297
//
298
String JavaDoc name = element.getAttribute(XTRun_NAME_ATTRIBUTE);
299         testSuite.setName(name);
300         
301         String JavaDoc id = element.getAttribute(XTRun_ID_ATTRIBUTE);
302         testSuite.setId(id);
303
304         Element JavaDoc[] testSuites
305             = getChildrenByTagName(element, XTRun_TEST_SUITE_TAG);
306
307         int n = testSuites != null ? testSuites.length : 0;
308         for(int i=0; i<n; i++){
309             String JavaDoc suiteHref =
310                 testSuites[i].getAttribute(XTRun_HREF_ATTRIBUTE);
311
312             Test test = XMLTestSuiteLoader.loadTestSuite(suiteHref, testSuite);
313             if(test != null){
314                 testSuite.addTest(test);
315             }
316         }
317
318         return testSuite;
319     }
320
321     /**
322      * Gets all the children of a given type.
323      */

324     protected Element JavaDoc[] getChildrenByTagName(Element JavaDoc element,
325                                              String JavaDoc tagName)
326     {
327         tagName = tagName.intern();
328         Vector JavaDoc childrenWithTagName = new Vector JavaDoc();
329         
330         NodeList JavaDoc children = element.getChildNodes();
331         if(children != null && children.getLength() > 0){
332             int n = children.getLength();
333             for(int i=0; i<n; i++){
334                 Node JavaDoc child = children.item(i);
335                 if(child.getNodeType() == Node.ELEMENT_NODE){
336                     Element JavaDoc childElement = (Element JavaDoc)child;
337                     String JavaDoc childTagName = childElement.getTagName().intern();
338                     if(childTagName == tagName){
339                         childrenWithTagName.addElement(childElement);
340                     }
341                 }
342             }
343         }
344         
345         Element JavaDoc[] a = null;
346         if(childrenWithTagName.size() > 0){
347             a = new Element JavaDoc[childrenWithTagName.size()];
348             childrenWithTagName.copyInto(a);
349         }
350
351         return a;
352     }
353
354
355     /**
356      * Runs the test suite described by the input
357      * Document object. If the input ids array
358      * is null or of zero length, then all the tests will be run.
359      * Otherwise, only the tests identified by
360      * the array will be run.
361      */

362     public TestReport run(Document JavaDoc doc, String JavaDoc[] ids)
363         throws TestException {
364         Element JavaDoc root = doc.getDocumentElement();
365
366         return run(root, ids);
367     }
368
369     protected TestReport runTest(Test test)
370         throws TestException {
371         try{
372             return test.run();
373         }catch(Exception JavaDoc e){
374             StringWriter JavaDoc sw = new StringWriter JavaDoc();
375             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
376             e.printStackTrace(pw);
377             throw new TestException(TEST_SUITE_EXCEPTION,
378                                     new Object JavaDoc[] { test.getName(),
379                                                    test.getClass().getName(),
380                                                    e.getClass().getName(),
381                                                    e.getMessage(),
382                                                    sw.toString() },
383                                     e);
384         }
385     }
386
387     protected void processReport(TestReport report,
388                                  TestReportProcessor[] processors)
389         throws TestException {
390         int n = processors.length;
391         int i=0;
392         try{
393             for(; i<n; i++){
394                 processors[i].processReport(report);
395             }
396         }catch(Exception JavaDoc e){
397             StringWriter JavaDoc sw = new StringWriter JavaDoc();
398             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
399             e.printStackTrace(pw);
400             throw new TestException(TEST_REPORT_PROCESSING_EXCEPTION,
401                                     new Object JavaDoc[] { processors[i].getClass().getName(),
402                                                    e.getClass().getName(),
403                                                    e.getMessage(),
404                                                    sw.toString() },
405                                     e);
406         }
407     }
408
409     protected TestReport run(Element JavaDoc testRunElement, String JavaDoc[] ids)
410         throws TestException{
411         //
412
// First, build entire suite of tests
413
//
414
Test testRun
415             = buildTestRunTestSuite(testRunElement);
416
417         //
418
// Filter testSuite if necessary
419
//
420
Test filteredTestRun = testRun;
421         if(ids != null && ids.length > 0){
422             IdBasedTestFilter filter = new IdBasedTestFilter(ids);
423             filteredTestRun = filter.filter(testRun);
424             String JavaDoc unusedIds = filter.traceUnusedIds();
425             if(unusedIds != null){
426                 System.err.println(Messages.formatMessage(MESSAGE_UNMATCHED_TEST_IDS,
427                                                           new Object JavaDoc[]{unusedIds}));
428             }
429         }
430
431         if(filteredTestRun == null){
432             DefaultTestReport report
433                 = new DefaultTestReport(testRun);
434             report.setPassed(true);
435             return report;
436         }
437
438         //
439
// Now, get the set of TestReportProcessors
440
// that can use the data
441
//
442
TestReportProcessor[] processors
443             = extractTestReportProcessor(testRunElement);
444
445         //
446
// Run the test
447
//
448
TestReport report = runTest(testRun);
449         
450         //
451
// Process the report
452
//
453
if(processors != null){
454             processReport(report, processors);
455         }
456
457         return report;
458     }
459
460     /**
461      * Displayed when the user passes no arguments to the command line.
462      */

463     public static final String JavaDoc USAGE
464         = "XMLTestSuiteRunner.messages.error.usage";
465
466     /**
467      * Displayed when the input argument does not represent an existing
468      * file to notify the user that the argument is going to be
469      * interpreted as a URI.
470      */

471     public static final String JavaDoc NOT_A_FILE_TRY_URI
472         = "XMLTestSuiteRunner.messages.error.not.a.file.try.uri";
473
474     /**
475      * Displayed when the input file name cannot be turned into a URL
476      */

477     public static final String JavaDoc COULD_NOT_CONVERT_FILE_NAME_TO_URI
478         = "XMLTestSuiteRunner.messages.error.could.not.convert.file.name.to.uri";
479
480     /**
481      * Displayed when the input argument does not represent a valid
482      * URI
483      */

484     public static final String JavaDoc INVALID_URI
485         = "XMLTestSuiteRunner.messages.error.invalid.uri";
486
487     /**
488      * Displayed when the input document cannot be parsed.
489      * {0} : uri of the invalid document.
490      * {1} : exception generated while parsing
491      * {2} : exception message
492      */

493     public static final String JavaDoc INVALID_DOCUMENT
494         = "XMLTestSuiteRunner.messages.error.invalid.document";
495
496     /**
497      * Error displayed when an error occurs while running the
498      * test suite
499      */

500     public static final String JavaDoc ERROR_RUNNING_TEST_SUITE
501         = "XMLTestSuiteRunner.messages.error.running.test.suite";
502
503     public static void main(String JavaDoc[] args) {
504         if(args.length < 1){
505             System.err.println(Messages.formatMessage(USAGE, null));
506             System.exit(0);
507         }
508         
509         String JavaDoc uriStr = args[0];
510         String JavaDoc[] ids = new String JavaDoc[args.length - 1];
511         System.arraycopy(args, 1, ids, 0, args.length-1);
512
513         File JavaDoc file = new File JavaDoc(uriStr);
514         URL JavaDoc url = null;
515         if(file.exists()){
516             try {
517                 url = file.toURL();
518             }catch(MalformedURLException JavaDoc e){
519                 System.err.println(Messages.formatMessage(COULD_NOT_CONVERT_FILE_NAME_TO_URI,
520                                                             new Object JavaDoc[]{uriStr}));
521                 System.exit(0);
522             }
523         }
524         
525         else {
526             System.err.println(Messages.formatMessage(NOT_A_FILE_TRY_URI,
527                                                         new Object JavaDoc[]{uriStr}));
528             try{
529                 url = new URL JavaDoc(uriStr);
530             }catch(MalformedURLException JavaDoc e){
531                 System.err.println(Messages.formatMessage(INVALID_URI,
532                                                           new Object JavaDoc[]{uriStr}));
533                 System.exit(0);
534             }
535         }
536
537         Document JavaDoc doc = null;
538
539         try{
540             System.err.println("Loading document ...");
541
542             DocumentBuilder JavaDoc docBuilder
543                 = DocumentBuilderFactory.newInstance().newDocumentBuilder();
544
545             doc = docBuilder.parse(url.toString());
546         }catch(Exception JavaDoc e){
547             e.printStackTrace();
548             System.err.println(Messages.formatMessage(INVALID_DOCUMENT,
549                                                       new Object JavaDoc[] { uriStr,
550                                                                      e.getClass().getName(),
551                                                                      e.getMessage() }));
552             System.exit(0);
553         }
554         
555         try{
556             System.err.println("Running test run...");
557             XMLTestSuiteRunner r = new XMLTestSuiteRunner();
558             r.run(doc, ids);
559         }catch(TestException e){
560             System.err.println(Messages.formatMessage(ERROR_RUNNING_TEST_SUITE,
561                                                       new Object JavaDoc[] { e.getMessage() }));
562             System.exit(0);
563         }
564
565         System.exit(1);
566         
567     }
568 }
569
Popular Tags