KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > betwixt > xmlunit > XmlTestCase


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

16  
17 package org.apache.commons.betwixt.xmlunit;
18
19 import java.io.File JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.StringReader JavaDoc;
22 import java.io.StringWriter JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.Comparator JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.List JavaDoc;
28
29 import javax.xml.parsers.DocumentBuilder JavaDoc;
30 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
31 import javax.xml.parsers.ParserConfigurationException JavaDoc;
32
33 import junit.framework.AssertionFailedError;
34 import junit.framework.TestCase;
35
36 import org.apache.xerces.parsers.SAXParser;
37 import org.w3c.dom.Attr JavaDoc;
38 import org.w3c.dom.DOMException JavaDoc;
39 import org.w3c.dom.Document JavaDoc;
40 import org.w3c.dom.NamedNodeMap JavaDoc;
41 import org.w3c.dom.Node JavaDoc;
42 import org.w3c.dom.NodeList JavaDoc;
43 import org.xml.sax.InputSource JavaDoc;
44 import org.xml.sax.SAXException JavaDoc;
45 import org.xml.sax.SAXParseException JavaDoc;
46 import org.xml.sax.helpers.DefaultHandler JavaDoc;
47
48 /**
49   * Provides xml test utilities.
50   * Hopefully, these might be moved into [xmlunit] sometime.
51   *
52   * @author Robert Burrell Donkin
53   * @author Khaled Noaman, IBM (some portions derived from test code originally contributed to the Apache Xerces project)
54   */

55 public class XmlTestCase extends TestCase {
56
57     private static final String JavaDoc NAMESPACES_FEATURE_ID
58                             = "http://xml.org/sax/features/namespaces";
59
60     private static final String JavaDoc NAMESPACE_PREFIXES_FEATURE_ID
61                             = "http://xml.org/sax/features/namespace-prefixes";
62
63     private static final String JavaDoc VALIDATION_FEATURE_ID
64                             = "http://xml.org/sax/features/validation";
65
66     private static final String JavaDoc SCHEMA_VALIDATION_FEATURE_ID
67                             = "http://apache.org/xml/features/validation/schema";
68
69     private static final String JavaDoc SCHEMA_FULL_CHECKING_FEATURE_ID
70                             = "http://apache.org/xml/features/validation/schema-full-checking";
71
72     private static final String JavaDoc DYNAMIC_VALIDATION_FEATURE_ID
73                             = "http://apache.org/xml/features/validation/dynamic";
74
75     private static final String JavaDoc NONAMESPACE_SCHEMA_LOCATION_PROPERTY_ID
76         = "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation";
77
78
79     protected static boolean debug = false;
80
81     DocumentBuilderFactory JavaDoc domFactory;
82
83          
84     public XmlTestCase(String JavaDoc testName) {
85         super(testName);
86     }
87
88     
89     public void xmlAssertIsomorphicContent(
90                                 org.w3c.dom.Document JavaDoc documentOne,
91                                 org.w3c.dom.Document JavaDoc documentTwo)
92                                     throws
93                                         AssertionFailedError {
94         log("Testing documents:" + documentOne.getDocumentElement().getNodeName()
95             + " and " + documentTwo.getDocumentElement().getNodeName());
96         xmlAssertIsomorphicContent(documentOne, documentTwo, false);
97     }
98
99     public void xmlAssertIsomorphicContent(
100                                 org.w3c.dom.Document JavaDoc documentOne,
101                                 org.w3c.dom.Document JavaDoc documentTwo,
102                                 boolean orderIndependent)
103                                     throws
104                                         AssertionFailedError {
105         xmlAssertIsomorphicContent(null, documentOne, documentTwo, orderIndependent);
106     }
107     
108     public void xmlAssertIsomorphicContent(
109                                 String JavaDoc message,
110                                 org.w3c.dom.Document JavaDoc documentOne,
111                                 org.w3c.dom.Document JavaDoc documentTwo)
112                                     throws
113                                         AssertionFailedError {
114         
115         xmlAssertIsomorphicContent(message, documentOne, documentTwo, false);
116     }
117     
118     public void xmlAssertIsomorphicContent(
119                                 String JavaDoc message,
120                                 org.w3c.dom.Document JavaDoc documentOne,
121                                 org.w3c.dom.Document JavaDoc documentTwo,
122                                 boolean orderIndependent)
123                                     throws
124                                         AssertionFailedError
125     {
126         // two documents have isomorphic content iff their root elements
127
// are isomophic
128
xmlAssertIsomorphic(
129                             message,
130                             documentOne.getDocumentElement(),
131                             documentTwo.getDocumentElement(),
132                             orderIndependent);
133     }
134  
135     
136     public void xmlAssertIsomorphic(
137                                 org.w3c.dom.Node JavaDoc rootOne,
138                                 org.w3c.dom.Node JavaDoc rootTwo)
139                                     throws
140                                         AssertionFailedError {
141         xmlAssertIsomorphic(rootOne, rootTwo, false);
142     }
143     
144     public void xmlAssertIsomorphic(
145                                 org.w3c.dom.Node JavaDoc rootOne,
146                                 org.w3c.dom.Node JavaDoc rootTwo,
147                                 boolean orderIndependent)
148                                     throws
149                                         AssertionFailedError
150     {
151         xmlAssertIsomorphic(null, rootOne, rootTwo, orderIndependent);
152     }
153     
154     public void xmlAssertIsomorphic(
155                                 String JavaDoc message,
156                                 org.w3c.dom.Node JavaDoc rootOne,
157                                 org.w3c.dom.Node JavaDoc rootTwo) {
158                                 
159         xmlAssertIsomorphic(message, rootOne, rootTwo, false);
160     
161     }
162     
163     public void xmlAssertIsomorphic(
164                                 String JavaDoc message,
165                                 org.w3c.dom.Node JavaDoc rootOne,
166                                 org.w3c.dom.Node JavaDoc rootTwo,
167                                 boolean orderIndependent)
168                                     throws
169                                         AssertionFailedError
170     {
171         // first normalize the xml
172
rootOne.normalize();
173         rootTwo.normalize();
174         // going to use recursion so avoid normalizing each time
175
testIsomorphic(message, rootOne, rootTwo, orderIndependent);
176     }
177  
178     
179     private void testIsomorphic(
180                                 String JavaDoc message,
181                                 org.w3c.dom.Node JavaDoc nodeOne,
182                                 org.w3c.dom.Node JavaDoc nodeTwo)
183                                     throws
184                                         AssertionFailedError {
185                                         
186         testIsomorphic(message, nodeOne, nodeTwo, false);
187     }
188                                     
189     
190     private void testIsomorphic(
191                                 String JavaDoc message,
192                                 org.w3c.dom.Node JavaDoc nodeOne,
193                                 org.w3c.dom.Node JavaDoc nodeTwo,
194                                 boolean orderIndependent)
195                                     throws
196                                         AssertionFailedError
197     {
198         try {
199             if (debug) {
200                 log(
201                     "node 1 name=" + nodeOne.getNodeName()
202                     + " qname=" + nodeOne.getLocalName());
203                 log(
204                     "node 2 name=" + nodeTwo.getNodeName()
205                     + " qname=" + nodeTwo.getLocalName());
206             }
207             
208             // compare node properties
209
log("Comparing node properties");
210             assertEquals(
211                         (null == message ? "(Unequal node types)" : message + "(Unequal node types)"),
212                         nodeOne.getNodeType(),
213                         nodeTwo.getNodeType());
214             assertEquals(
215                         (null == message ? "(Unequal node names)" : message + "(Unequal node names)"),
216                         nodeOne.getNodeName(),
217                         nodeTwo.getNodeName());
218             assertEquals(
219                         (null == message ? "(Unequal node values)" : message + "(Unequal node values)"),
220                         trim(nodeOne.getNodeValue()),
221                         trim(nodeTwo.getNodeValue()));
222             assertEquals(
223                         (null == message ? "(Unequal local names)" : message + "(Unequal local names)"),
224                         nodeOne.getLocalName(),
225                         nodeTwo.getLocalName());
226             assertEquals(
227                         (null == message ? "(Unequal namespace)" : message + "(Unequal namespace)"),
228                         nodeOne.getNamespaceURI(),
229                         nodeTwo.getNamespaceURI());
230             
231                                                   
232             // compare attributes
233
log("Comparing attributes");
234             // make sure both have them first
235
assertEquals(
236                         (null == message ? "(Unequal attributes)" : message + "(Unequal attributes)"),
237                         nodeOne.hasAttributes(),
238                         nodeTwo.hasAttributes());
239             if (nodeOne.hasAttributes()) {
240                 // do the actual comparison
241
// first we check the number of attributes are equal
242
// we then check that for every attribute of node one,
243
// a corresponding attribute exists in node two
244
// (this should be sufficient to prove equality)
245
NamedNodeMap JavaDoc attributesOne = nodeOne.getAttributes();
246                 NamedNodeMap JavaDoc attributesTwo = nodeTwo.getAttributes();
247                 
248                 assertEquals(
249                         (null == message ? "(Unequal attributes)" : message + "(Unequal attributes)"),
250                         attributesOne.getLength(),
251                         attributesTwo.getLength());
252                 
253                 for (int i=0, size=attributesOne.getLength(); i<size; i++) {
254                     Attr JavaDoc attributeOne = (Attr JavaDoc) attributesOne.item(i);
255                     Attr JavaDoc attributeTwo = (Attr JavaDoc) attributesTwo.getNamedItemNS(
256                                                     attributeOne.getNamespaceURI(),
257                                                     attributeOne.getLocalName());
258                     if (attributeTwo == null) {
259                         attributeTwo = (Attr JavaDoc) attributesTwo.getNamedItem(attributeOne.getName());
260                     }
261                     
262                     // check attribute two exists
263
if (attributeTwo == null) {
264                         String JavaDoc diagnosis = "[Missing attribute (" + attributeOne.getName() + ")]";
265                         fail((null == message ? diagnosis : message + diagnosis));
266                     }
267                     
268                     // now check attribute values
269
assertEquals(
270                         (null == message ? "(Unequal attribute values)" : message + "(Unequal attribute values)"),
271                         attributeOne.getValue(),
272                         attributeTwo.getValue());
273                 }
274             }
275             
276             
277             // compare children
278
log("Comparing children");
279             // this time order is important
280
// so we can just go down the list and compare node-wise using recursion
281
List JavaDoc listOne = sanitize(nodeOne.getChildNodes());
282             List JavaDoc listTwo = sanitize(nodeTwo.getChildNodes());
283
284             if (orderIndependent) {
285                 log("[Order Independent]");
286                 Comparator JavaDoc nodeByName = new NodeByNameComparator();
287                 Collections.sort(listOne, nodeByName);
288                 Collections.sort(listTwo, nodeByName);
289             }
290             
291             Iterator JavaDoc it = listOne.iterator();
292             Iterator JavaDoc iter2 = listTwo.iterator();
293             while (it.hasNext() & iter2.hasNext()) {
294                 Node JavaDoc nextOne = ((Node JavaDoc)it.next());
295                 Node JavaDoc nextTwo = ((Node JavaDoc)iter2.next());
296                 log(nextOne.getNodeName() + ":" + nextOne.getNodeValue());
297                 log(nextTwo.getNodeName() + ":" + nextTwo.getNodeValue());
298             }
299
300             assertEquals(
301                         (null == message ? "(Unequal child nodes@" + nodeOne.getNodeName() +")":
302                                 message + "(Unequal child nodes @" + nodeOne.getNodeName() +")"),
303                         listOne.size(),
304                         listTwo.size());
305                         
306             it = listOne.iterator();
307             iter2 = listTwo.iterator();
308             while (it.hasNext() & iter2.hasNext()) {
309                 Node JavaDoc nextOne = ((Node JavaDoc)it.next());
310                 Node JavaDoc nextTwo = ((Node JavaDoc)iter2.next());
311                 log(nextOne.getNodeName() + " vs " + nextTwo.getNodeName());
312                 testIsomorphic(message, nextOne, nextTwo, orderIndependent);
313             
314             }
315         
316         } catch (DOMException JavaDoc ex) {
317             fail((null == message ? "" : message + " ") + "DOM exception" + ex.toString());
318         }
319     }
320     
321     
322     protected DocumentBuilder JavaDoc createDocumentBuilder() {
323         try {
324
325             return getDomFactory().newDocumentBuilder();
326         
327         } catch (ParserConfigurationException JavaDoc e) {
328             fail("Cannot create DOM builder: " + e.toString());
329         
330         }
331         // just to keep the compiler happy
332
return null;
333     }
334     
335     protected DocumentBuilderFactory JavaDoc getDomFactory() {
336         // lazy creation
337
if (domFactory == null) {
338             domFactory = DocumentBuilderFactory.newInstance();
339         }
340         
341         return domFactory;
342     }
343     
344     protected Document JavaDoc parseString(StringWriter JavaDoc writer) {
345         try {
346         
347             return createDocumentBuilder().parse(new InputSource JavaDoc(new StringReader JavaDoc(writer.getBuffer().toString())));
348         
349         } catch (SAXException JavaDoc e) {
350             fail("Cannot create parse string: " + e.toString());
351         
352         } catch (IOException JavaDoc e) {
353             fail("Cannot create parse string: " + e.toString());
354         
355         }
356         // just to keep the compiler happy
357
return null;
358     }
359     
360     protected Document JavaDoc parseString(String JavaDoc string) {
361         try {
362         
363             return createDocumentBuilder().parse(new InputSource JavaDoc(new StringReader JavaDoc(string)));
364         
365         } catch (SAXException JavaDoc e) {
366             fail("Cannot create parse string: " + e.toString());
367         
368         } catch (IOException JavaDoc e) {
369             fail("Cannot create parse string: " + e.toString());
370         
371         }
372         // just to keep the compiler happy
373
return null;
374     }
375
376     
377     protected Document JavaDoc parseFile(String JavaDoc path) {
378         try {
379         
380             return createDocumentBuilder().parse(new File JavaDoc(path));
381         
382         } catch (SAXException JavaDoc e) {
383             fail("Cannot create parse file: " + e.toString());
384         
385         } catch (IOException JavaDoc e) {
386             fail("Cannot create parse file: " + e.toString());
387         
388         }
389         // just to keep the compiler happy
390
return null;
391     }
392     
393     private void log(String JavaDoc message)
394     {
395         if (debug) {
396             System.out.println("[XmlTestCase]" + message);
397         }
398     }
399
400     
401     private void log(String JavaDoc message, Exception JavaDoc e)
402     {
403         if (debug) {
404             System.out.println("[XmlTestCase]" + message);
405             e.printStackTrace();
406         }
407     }
408     
409     private String JavaDoc trim(String JavaDoc trimThis)
410     {
411         if (trimThis == null) {
412             return trimThis;
413         }
414         
415         return trimThis.trim();
416     }
417     
418     private List JavaDoc sanitize(NodeList JavaDoc nodes) {
419         ArrayList JavaDoc list = new ArrayList JavaDoc();
420         
421         for (int i=0, size=nodes.getLength(); i<size; i++) {
422             if ( nodes.item(i).getNodeType() == Node.TEXT_NODE ) {
423                 if ( !( nodes.item(i).getNodeValue() == null ||
424                         nodes.item(i).getNodeValue().trim().length() == 0 )) {
425                     list.add(nodes.item(i));
426                 } else {
427                     log("Ignoring text node:" + nodes.item(i).getNodeValue());
428                 }
429             } else {
430                 list.add(nodes.item(i));
431             }
432         }
433         return list;
434     }
435     
436     private class NodeByNameComparator implements Comparator JavaDoc {
437         public int compare(Object JavaDoc objOne, Object JavaDoc objTwo) {
438             String JavaDoc nameOne = ((Node JavaDoc) objOne).getNodeName();
439             String JavaDoc nameTwo = ((Node JavaDoc) objTwo).getNodeName();
440             
441             if (nameOne == null) {
442                 if (nameTwo == null) {
443                     return 0;
444                 }
445                 return -1;
446             }
447             
448             if (nameTwo == null) {
449                 return 1;
450             }
451             
452             return nameOne.compareTo(nameTwo);
453         }
454     }
455     
456     
457     public void validateWithSchema(InputSource JavaDoc documentSource, final InputSource JavaDoc schemaSource)
458             throws ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
459     {
460         class XMLUnitHandler extends DefaultHandler JavaDoc {
461             ArrayList JavaDoc errors = new ArrayList JavaDoc();
462             ArrayList JavaDoc warnings = new ArrayList JavaDoc();
463             InputSource JavaDoc schemaSource;
464     
465             XMLUnitHandler(InputSource JavaDoc schemaSource) {
466                 this.schemaSource = schemaSource;
467                 schemaSource.setSystemId("schema.xsd");
468             }
469     
470             public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId) {
471                 return schemaSource;
472             }
473     
474             public void error(SAXParseException JavaDoc ex) {
475                 errors.add(ex);
476             }
477     
478             public void warning(SAXParseException JavaDoc ex) {
479                 warnings.add(ex);
480             }
481     
482             void reportErrors() throws SAXException JavaDoc {
483                 if (errors.size() > 0) {
484                     throw (SAXException JavaDoc) errors.get(0);
485                 }
486             }
487     
488         }
489
490         // it's not all that good to have a concrete dependency on Xerces
491
// and a particular version, at that.
492
// but schema support in the Xerces series of parsers is variable
493
// and some of the configuration details differ.
494
// At least this way seems reliable
495
SAXParser parser = new SAXParser();
496     
497         // Set features
498
parser.setFeature(NAMESPACES_FEATURE_ID, true);
499         parser.setFeature(NAMESPACE_PREFIXES_FEATURE_ID, false);
500         parser.setFeature(VALIDATION_FEATURE_ID, true);
501         parser.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true);
502         parser.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, false);
503         parser.setFeature(DYNAMIC_VALIDATION_FEATURE_ID, false);
504     
505         // Set properties
506
parser.setProperty(NONAMESPACE_SCHEMA_LOCATION_PROPERTY_ID, "schema.xsd");
507     
508         XMLUnitHandler handler = new XMLUnitHandler(schemaSource);
509     
510         // Set handlers
511
parser.setContentHandler(handler);
512         parser.setErrorHandler(handler);
513         parser.setEntityResolver(handler);
514     
515         // parse document
516
parser.parse(documentSource);
517         handler.reportErrors();
518     }
519     
520     public boolean isValid(InputSource JavaDoc documentSource, InputSource JavaDoc schemaSource)
521             throws ParserConfigurationException JavaDoc, IOException JavaDoc
522     {
523         boolean result = false;
524         try
525         {
526             validateWithSchema(documentSource, schemaSource);
527             result = true;
528         }
529         catch (SAXException JavaDoc se)
530         {
531             log("Validation failed.", se);
532         }
533         
534         return result;
535     }
536     
537     public void xmlAssertIsValid(InputSource JavaDoc documentSource, InputSource JavaDoc schemaSource)
538         throws ParserConfigurationException JavaDoc, IOException JavaDoc
539     {
540         try
541         {
542             validateWithSchema(documentSource, schemaSource);
543         }
544         catch (SAXException JavaDoc se)
545         {
546             se.printStackTrace();
547             fail("Validation failure: " + se.getMessage());
548         }
549     }
550 }
551
552
Popular Tags