0001: /*
0002: ******************************************************************
0003: Copyright (c) 2001-2007, Jeff Martin, Tim Bacon
0004: All rights reserved.
0005:
0006: Redistribution and use in source and binary forms, with or without
0007: modification, are permitted provided that the following conditions
0008: are met:
0009:
0010: * Redistributions of source code must retain the above copyright
0011: notice, this list of conditions and the following disclaimer.
0012: * Redistributions in binary form must reproduce the above
0013: copyright notice, this list of conditions and the following
0014: disclaimer in the documentation and/or other materials provided
0015: with the distribution.
0016: * Neither the name of the xmlunit.sourceforge.net nor the names
0017: of its contributors may be used to endorse or promote products
0018: derived from this software without specific prior written
0019: permission.
0020:
0021: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0022: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0023: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
0024: FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
0025: COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
0026: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
0027: BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0028: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
0029: CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0030: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
0031: ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0032: POSSIBILITY OF SUCH DAMAGE.
0033:
0034: ******************************************************************
0035: */
0036:
0037: package org.custommonkey.xmlunit;
0038:
0039: import java.io.File;
0040: import java.io.FileWriter;
0041: import java.io.IOException;
0042: import java.util.ArrayList;
0043: import java.util.Iterator;
0044:
0045: import javax.xml.parsers.DocumentBuilder;
0046: import junit.framework.TestCase;
0047: import junit.framework.TestSuite;
0048:
0049: import org.w3c.dom.Attr;
0050: import org.w3c.dom.CDATASection;
0051: import org.w3c.dom.Comment;
0052: import org.w3c.dom.Document;
0053: import org.w3c.dom.DocumentType;
0054: import org.w3c.dom.Element;
0055: import org.w3c.dom.NamedNodeMap;
0056: import org.w3c.dom.Node;
0057: import org.w3c.dom.ProcessingInstruction;
0058: import org.w3c.dom.Text;
0059: import org.xml.sax.SAXException;
0060:
0061: /**
0062: * JUnit test for DifferenceEngine
0063: */
0064: public class test_DifferenceEngine extends TestCase implements
0065: DifferenceConstants {
0066: private CollectingDifferenceListener listener;
0067: private DifferenceEngine engine;
0068: private Document document;
0069:
0070: private final ComparisonController PSEUDO_DIFF = new SimpleComparisonController();
0071: private final ComparisonController PSEUDO_DETAILED_DIFF = new NeverHaltingComparisonController();
0072:
0073: private final static ElementQualifier DEFAULT_ELEMENT_QUALIFIER = new ElementNameQualifier();
0074: private final static String TEXT_A = "the pack on my back is aching";
0075: private final static String TEXT_B = "the straps seem to cut me like a knife";
0076: private final static String COMMENT_A = "Im no clown I wont back down";
0077: private final static String COMMENT_B = "dont need you to tell me whats going down";
0078: private final static String[] PROC_A = { "down", "down down" };
0079: private final static String[] PROC_B = { "dadada", "down" };
0080: private final static String CDATA_A = "I'm standing alone, you're weighing the gold";
0081: private final static String CDATA_B = "I'm watching you sinking... Fools Gold";
0082: private final static String ATTR_A = "These boots were made for walking";
0083: private final static String ATTR_B = "The marquis de sade never wore no boots like these";
0084:
0085: private void assertDifferentText(Text control, Text test,
0086: Difference difference) {
0087: try {
0088: engine.compareText(control, test, listener);
0089: } catch (DifferenceEngine.DifferenceFoundException e) {
0090: }
0091: assertEquals(difference.getId(), listener.comparingWhat);
0092: assertEquals(true, listener.different);
0093: resetListener();
0094: }
0095:
0096: public void testCompareText() throws Exception {
0097: String expected = TEXT_A;
0098: String actual = TEXT_B;
0099: Text control = document.createTextNode(expected);
0100: Text test = document.createTextNode(actual);
0101:
0102: assertDifferentText(control, test, TEXT_VALUE);
0103: }
0104:
0105: private void assertDifferentProcessingInstructions(
0106: ProcessingInstruction control, ProcessingInstruction test,
0107: Difference difference) {
0108: try {
0109: engine
0110: .compareProcessingInstruction(control, test,
0111: listener);
0112: } catch (DifferenceEngine.DifferenceFoundException e) {
0113: }
0114: assertEquals(difference.getId(), listener.comparingWhat);
0115: assertEquals(true, listener.different);
0116: resetListener();
0117: }
0118:
0119: public void testCompareProcessingInstruction() throws Exception {
0120: String[] expected = PROC_A;
0121: String[] actual = PROC_B;
0122: ProcessingInstruction control = document
0123: .createProcessingInstruction(expected[0], expected[1]);
0124: ProcessingInstruction test = document
0125: .createProcessingInstruction(actual[0], actual[1]);
0126:
0127: assertDifferentProcessingInstructions(control, test,
0128: PROCESSING_INSTRUCTION_TARGET);
0129:
0130: ProcessingInstruction control2 = document
0131: .createProcessingInstruction(expected[0], expected[1]);
0132: ProcessingInstruction test2 = document
0133: .createProcessingInstruction(expected[0], actual[1]);
0134: assertDifferentProcessingInstructions(control2, test2,
0135: PROCESSING_INSTRUCTION_DATA);
0136: }
0137:
0138: private void assertDifferentComments(Comment control, Comment test,
0139: Difference difference) {
0140: try {
0141: engine.compareComment(control, test, listener);
0142: } catch (DifferenceEngine.DifferenceFoundException e) {
0143: }
0144: assertEquals(difference.getId(), listener.comparingWhat);
0145: assertEquals(true, listener.different);
0146: resetListener();
0147: }
0148:
0149: public void testCompareComment() throws Exception {
0150: String expected = COMMENT_A;
0151: String actual = COMMENT_B;
0152: Comment control = document.createComment(expected);
0153: Comment test = document.createComment(actual);
0154:
0155: assertDifferentComments(control, test, COMMENT_VALUE);
0156: }
0157:
0158: private void assertDifferentCDATA(CDATASection control,
0159: CDATASection test, Difference difference) {
0160: try {
0161: engine.compareCDataSection(control, test, listener);
0162: } catch (DifferenceEngine.DifferenceFoundException e) {
0163: }
0164: assertEquals(difference.getId(), listener.comparingWhat);
0165: assertEquals(true, listener.different);
0166: resetListener();
0167: }
0168:
0169: public void testCompareCDATA() throws Exception {
0170: String expected = CDATA_A;
0171: String actual = CDATA_B;
0172: CDATASection control = document.createCDATASection(expected);
0173: CDATASection test = document.createCDATASection(actual);
0174:
0175: assertDifferentCDATA(control, test, CDATA_VALUE);
0176: }
0177:
0178: private void assertDifferentDocumentTypes(DocumentType control,
0179: DocumentType test, Difference difference, boolean fatal) {
0180: try {
0181: engine.compareDocumentType(control, test, listener);
0182: if (fatal) {
0183: fail("Expected fatal difference!");
0184: }
0185: } catch (DifferenceEngine.DifferenceFoundException e) {
0186: if (!fatal) {
0187: fail("Expected similarity not fatal difference!");
0188: }
0189: }
0190: assertEquals(difference.getId(), listener.comparingWhat);
0191: assertEquals(fatal, listener.different);
0192: resetListener();
0193: }
0194:
0195: public void testCompareDocumentType() throws Exception {
0196: File tmpFile = File.createTempFile("Roses", "dtd");
0197: tmpFile.deleteOnExit();
0198: String tmpDTD = "<!ELEMENT leaf (#PCDATA)><!ELEMENT root (leaf)>";
0199: new FileWriter(tmpFile).write(tmpDTD);
0200: String rosesDTD = tmpFile.toURL().toExternalForm();
0201:
0202: File altTmpFile = File.createTempFile("TheCrows", "dtd");
0203: altTmpFile.deleteOnExit();
0204: new FileWriter(altTmpFile).write(tmpDTD);
0205: String theCrowsDTD = altTmpFile.toURL().toExternalForm();
0206:
0207: Document controlDoc = XMLUnit
0208: .buildControlDocument("<!DOCTYPE root PUBLIC 'Stone' '"
0209: + rosesDTD + "'>" + "<root><leaf/></root>");
0210: Document testDoc = XMLUnit
0211: .buildTestDocument("<!DOCTYPE tree PUBLIC 'Stone' '"
0212: + rosesDTD + "'>" + "<tree><leaf/></tree>");
0213:
0214: DocumentType control = controlDoc.getDoctype();
0215: DocumentType test = testDoc.getDoctype();
0216:
0217: assertDifferentDocumentTypes(control, test, DOCTYPE_NAME, true);
0218:
0219: test = XMLUnit.buildTestDocument(
0220: "<!DOCTYPE root PUBLIC 'id' '" + rosesDTD + "'>"
0221: + "<root><leaf/></root>").getDoctype();
0222: assertDifferentDocumentTypes(control, test, DOCTYPE_PUBLIC_ID,
0223: true);
0224:
0225: test = XMLUnit.buildTestDocument(
0226: "<!DOCTYPE root SYSTEM '" + rosesDTD + "'>"
0227: + "<root><leaf/></root>").getDoctype();
0228: assertDifferentDocumentTypes(control, test, DOCTYPE_PUBLIC_ID,
0229: true);
0230:
0231: test = XMLUnit.buildTestDocument(
0232: "<!DOCTYPE root PUBLIC 'Stone' '" + theCrowsDTD + "'>"
0233: + "<root><leaf/></root>").getDoctype();
0234: assertDifferentDocumentTypes(control, test, DOCTYPE_SYSTEM_ID,
0235: false);
0236:
0237: test = XMLUnit.buildTestDocument(
0238: "<!DOCTYPE root SYSTEM '" + theCrowsDTD + "'>"
0239: + "<root><leaf/></root>").getDoctype();
0240: assertDifferentDocumentTypes(control, test, DOCTYPE_PUBLIC_ID,
0241: true);
0242:
0243: control = XMLUnit.buildTestDocument(
0244: "<!DOCTYPE root SYSTEM '" + rosesDTD + "'>"
0245: + "<root><leaf/></root>").getDoctype();
0246: assertDifferentDocumentTypes(control, test, DOCTYPE_SYSTEM_ID,
0247: false);
0248: }
0249:
0250: private void assertDifferentAttributes(Attr control, Attr test,
0251: Difference difference, boolean fatal) {
0252: try {
0253: engine.compareAttribute(control, test, listener);
0254: if (fatal) {
0255: fail("Expecting fatal difference!");
0256: }
0257: } catch (DifferenceEngine.DifferenceFoundException e) {
0258: if (!fatal) {
0259: fail("Expecting similarity not fatal difference!");
0260: }
0261: }
0262: assertEquals(difference.getId(), listener.comparingWhat);
0263: assertEquals(fatal, listener.different);
0264: resetListener();
0265: }
0266:
0267: public void testCompareAttribute() throws Exception {
0268: String expected = ATTR_A;
0269: String actual = ATTR_B;
0270: Attr control = document.createAttribute(getName());
0271: control.setValue(expected);
0272: Attr test = document.createAttribute(getName());
0273: test.setValue(actual);
0274:
0275: assertDifferentAttributes(control, test, ATTR_VALUE, true);
0276:
0277: String doctypeDeclaration = "<!DOCTYPE manchester ["
0278: + "<!ELEMENT sound EMPTY><!ATTLIST sound sorted (true|false) \"true\">"
0279: + "<!ELEMENT manchester (sound)>]>";
0280: Document controlDoc = XMLUnit
0281: .buildControlDocument(doctypeDeclaration
0282: + "<manchester><sound sorted=\"true\"/></manchester>");
0283: control = (Attr) controlDoc.getDocumentElement()
0284: .getFirstChild().getAttributes().getNamedItem("sorted");
0285:
0286: Document testDoc = XMLUnit.buildTestDocument(doctypeDeclaration
0287: + "<manchester><sound/></manchester>");
0288: test = (Attr) testDoc.getDocumentElement().getFirstChild()
0289: .getAttributes().getNamedItem("sorted");
0290:
0291: assertDifferentAttributes(control, test,
0292: ATTR_VALUE_EXPLICITLY_SPECIFIED, false);
0293: }
0294:
0295: private void assertDifferentElements(Element control, Element test,
0296: Difference difference) {
0297: try {
0298: engine.compareElement(control, test, listener);
0299: } catch (DifferenceEngine.DifferenceFoundException e) {
0300: }
0301: assertEquals(difference.getId(), listener.comparingWhat);
0302: assertEquals(true, listener.different);
0303: resetListener();
0304: }
0305:
0306: public void testCompareElements() throws Exception {
0307: Document document = XMLUnit
0308: .buildControlDocument("<down><im standing=\"alone\"/><im watching=\"you\" all=\"\"/>"
0309: + "<im watching=\"you all\"/><im watching=\"you sinking\"/></down>");
0310: Element control = (Element) document.getDocumentElement();
0311: Element test = (Element) control.getFirstChild();
0312:
0313: assertDifferentElements(control, test, ELEMENT_TAG_NAME);
0314:
0315: // compare im#1 to im#2
0316: control = test;
0317: test = (Element) control.getNextSibling();
0318: assertDifferentElements(control, test, ELEMENT_NUM_ATTRIBUTES);
0319:
0320: // compare im#1 to im#3
0321: test = (Element) test.getNextSibling();
0322: assertDifferentElements(control, test, ATTR_NAME_NOT_FOUND);
0323:
0324: // compare im#3 to im#4
0325: control = test;
0326: test = (Element) control.getNextSibling();
0327: assertDifferentElements(control, test, ATTR_VALUE);
0328: }
0329:
0330: public void testCompareNode() throws Exception {
0331: Document controlDocument = XMLUnit
0332: .buildControlDocument("<root>" + "<!-- " + COMMENT_A
0333: + " -->" + "<?" + PROC_A[0] + " " + PROC_A[1]
0334: + " ?>" + "<elem attr=\"" + ATTR_A + "\">"
0335: + TEXT_A + "</elem></root>");
0336: Document testDocument = XMLUnit.buildTestDocument("<root>"
0337: + "<!-- " + COMMENT_B + " -->" + "<?" + PROC_B[0] + " "
0338: + PROC_B[1] + " ?>" + "<elem attr=\"" + ATTR_B + "\">"
0339: + TEXT_B + "</elem></root>");
0340:
0341: engine.compare(controlDocument, testDocument, listener, null);
0342:
0343: Node control = controlDocument.getDocumentElement()
0344: .getFirstChild();
0345: Node test = testDocument.getDocumentElement().getFirstChild();
0346:
0347: do {
0348: resetListener();
0349: engine.compare(control, test, listener, null);
0350: assertEquals(true, -1 != listener.comparingWhat);
0351: assertEquals(false, listener.nodesSkipped);
0352:
0353: resetListener();
0354: engine.compare(control, control, listener, null);
0355: assertEquals(-1, listener.comparingWhat);
0356:
0357: control = control.getNextSibling();
0358: test = test.getNextSibling();
0359: } while (control != null);
0360: }
0361:
0362: private void assertDifferentNamespaceDetails(Node control,
0363: Node test, Difference expectedDifference, boolean fatal) {
0364: try {
0365: engine.compareNodeBasics(control, test, listener);
0366: if (fatal) {
0367: fail("Expected fatal difference");
0368: }
0369: } catch (DifferenceEngine.DifferenceFoundException e) {
0370: if (!fatal) {
0371: fail("Not expecting fatal difference!");
0372: }
0373: }
0374: assertEquals(expectedDifference.getId(), listener.comparingWhat);
0375: assertEquals(fatal, listener.different);
0376: resetListener();
0377: }
0378:
0379: public void testCompareNodeBasics() throws Exception {
0380: String namespaceA = "http://example.org/StoneRoses";
0381: String namespaceB = "http://example.org/Stone/Roses";
0382: String prefixA = "music";
0383: String prefixB = "cd";
0384: String elemName = "nowPlaying";
0385: Element control = document.createElementNS(namespaceA, prefixA
0386: + ':' + elemName);
0387: engine.compareNodeBasics(control, control, listener);
0388:
0389: Element test = document.createElementNS(namespaceB, prefixA
0390: + ':' + elemName);
0391: assertDifferentNamespaceDetails(control, test, NAMESPACE_URI,
0392: true);
0393:
0394: test = document.createElementNS(namespaceA, prefixB + ':'
0395: + elemName);
0396: assertDifferentNamespaceDetails(control, test,
0397: NAMESPACE_PREFIX, false);
0398: }
0399:
0400: private void assertDifferentChildren(Node control, Node test,
0401: Difference expectedDifference, boolean fatal) {
0402: try {
0403: engine.compareHasChildNodes(control, test, listener);
0404: engine.compareNodeChildren(control, test, listener,
0405: DEFAULT_ELEMENT_QUALIFIER);
0406: if (fatal) {
0407: fail("Expected fatal difference");
0408: }
0409: } catch (DifferenceEngine.DifferenceFoundException e) {
0410: if (!fatal) {
0411: fail("Not expecting fatal difference "
0412: + listener.comparingWhat + ": expected "
0413: + listener.expected + " but was "
0414: + listener.actual);
0415: }
0416: }
0417: assertEquals(expectedDifference == null ? -1
0418: : expectedDifference.getId(), listener.comparingWhat);
0419: assertEquals(fatal, listener.different);
0420: resetListener();
0421: }
0422:
0423: public void testCompareNodeChildren() throws Exception {
0424: document = XMLUnit
0425: .buildControlDocument("<down><im standing=\"alone\"/><im><watching/>you all</im>"
0426: + "<im watching=\"you\">sinking</im></down>");
0427: // compare im #1 to itself
0428: Node control = document.getDocumentElement().getFirstChild();
0429: Node test = control;
0430: assertDifferentChildren(control, control, null, false);
0431:
0432: // compare im #1 to im #2
0433: test = control.getNextSibling();
0434: assertDifferentChildren(control, test, HAS_CHILD_NODES, true);
0435:
0436: // compare im #2 to im #3
0437: control = test;
0438: test = control.getNextSibling();
0439: assertDifferentChildren(control, test, CHILD_NODELIST_LENGTH,
0440: true);
0441: }
0442:
0443: private void assertDifferentNodeLists(Node control, Node test,
0444: Difference expectedDifference, boolean fatal) {
0445: try {
0446: engine.compareNodeList(control.getChildNodes(), test
0447: .getChildNodes(), control.getChildNodes()
0448: .getLength(), listener, DEFAULT_ELEMENT_QUALIFIER);
0449: if (fatal) {
0450: fail("Expected fatal difference");
0451: }
0452: } catch (DifferenceEngine.DifferenceFoundException e) {
0453: if (!fatal) {
0454: fail("Not expecting fatal difference!");
0455: }
0456: }
0457: assertEquals(expectedDifference == null ? -1
0458: : expectedDifference.getId(), listener.comparingWhat);
0459: assertEquals(fatal, listener.different);
0460: resetListener();
0461: }
0462:
0463: public void testCompareNodeList() throws Exception {
0464: document = XMLUnit
0465: .buildControlDocument("<down><im><standing/>alone</im><im><watching/>you all</im>"
0466: + "<im><watching/>you sinking</im></down>");
0467: // compare im #1 to itself
0468: Node control = document.getDocumentElement().getFirstChild();
0469: Node test = control;
0470: assertDifferentNodeLists(control, test, null, false);
0471:
0472: // compare im #1 to im #2
0473: test = control.getNextSibling();
0474: assertDifferentChildren(control, test, ELEMENT_TAG_NAME, true);
0475:
0476: // compare im #2 to im #3
0477: control = test;
0478: test = control.getNextSibling();
0479: assertDifferentChildren(control, test, TEXT_VALUE, true);
0480: }
0481:
0482: public void testCompareNodeListElements() throws Exception {
0483: Element control = document.createElement("root");
0484: control.appendChild(document.createElement("leafElemA"));
0485: control.appendChild(document.createElement("leafElemB"));
0486:
0487: Element test = document.createElement("root");
0488: test.appendChild(document.createElement("leafElemB"));
0489: test.appendChild(document.createElement("leafElemA"));
0490:
0491: assertDifferentChildren(control, test, CHILD_NODELIST_SEQUENCE,
0492: false);
0493: assertDifferentChildren(test, control, CHILD_NODELIST_SEQUENCE,
0494: false);
0495: }
0496:
0497: public void testCompareNodeListMixedContent() throws Exception {
0498: Element control = document.createElement("root");
0499: control.appendChild(document.createTextNode("text leaf"));
0500: control.appendChild(document.createElement("leafElem"));
0501:
0502: Element test = document.createElement("root");
0503: test.appendChild(document.createElement("leafElem"));
0504: test.appendChild(document.createTextNode("text leaf"));
0505:
0506: assertDifferentChildren(control, test, CHILD_NODELIST_SEQUENCE,
0507: false);
0508: assertDifferentChildren(test, control, CHILD_NODELIST_SEQUENCE,
0509: false);
0510: }
0511:
0512: public void testBasicCompare() throws Exception {
0513: try {
0514: engine.compare("black", "white", null, null, listener,
0515: ATTR_NAME_NOT_FOUND);
0516: fail("Expected difference found exception");
0517: } catch (DifferenceEngine.DifferenceFoundException e) {
0518: assertEquals(true, listener.different);
0519: assertEquals(ATTR_NAME_NOT_FOUND.getId(),
0520: listener.comparingWhat);
0521: }
0522: resetListener();
0523:
0524: try {
0525: engine.compare("black", "white", null, null, listener,
0526: NAMESPACE_PREFIX);
0527: assertEquals(false, listener.different);
0528: assertEquals(NAMESPACE_PREFIX.getId(),
0529: listener.comparingWhat);
0530: } catch (Exception e) {
0531: fail("Not expecting difference found exception");
0532: }
0533: }
0534:
0535: public void testXpathLocation1() throws Exception {
0536: String control = "<dvorak><keyboard/><composer/></dvorak>";
0537: String test = "<qwerty><keyboard/></qwerty>";
0538: listenToDifferences(control, test);
0539: assertEquals("1st control xpath", "/dvorak[1]",
0540: listener.controlXpath);
0541: assertEquals("1st test xpath", "/qwerty[1]", listener.testXpath);
0542: }
0543:
0544: public void testXpathLocation2() throws Exception {
0545: String control = "<dvorak><keyboard/><composer/></dvorak>";
0546: String test = "<qwerty><keyboard/></qwerty>";
0547: String start = "<a>", end = "</a>";
0548: listenToDifferences(start + control + end, start + test + end);
0549: assertEquals("2nd control xpath", "/a[1]/dvorak[1]",
0550: listener.controlXpath);
0551: assertEquals("2nd test xpath", "/a[1]/qwerty[1]",
0552: listener.testXpath);
0553: }
0554:
0555: public void testXpathLocation3() throws Exception {
0556: String control = "<stuff><wood type=\"rough\"/></stuff>";
0557: String test = "<stuff><wood type=\"smooth\"/></stuff>";
0558: listenToDifferences(control, test);
0559: assertEquals("3rd control xpath", "/stuff[1]/wood[1]/@type",
0560: listener.controlXpath);
0561: assertEquals("3rd test xpath", "/stuff[1]/wood[1]/@type",
0562: listener.testXpath);
0563: }
0564:
0565: public void testXpathLocation4() throws Exception {
0566: String control = "<stuff><glass colour=\"clear\"/><glass colour=\"green\"/></stuff>";
0567: String test = "<stuff><glass colour=\"clear\"/><glass colour=\"blue\"/></stuff>";
0568: ;
0569: listenToDifferences(control, test);
0570: assertEquals("4th control xpath", "/stuff[1]/glass[2]/@colour",
0571: listener.controlXpath);
0572: assertEquals("4th test xpath", "/stuff[1]/glass[2]/@colour",
0573: listener.testXpath);
0574: }
0575:
0576: public void testXpathLocation5() throws Exception {
0577: String control = "<stuff><wood>maple</wood><wood>oak</wood></stuff>";
0578: String test = "<stuff><wood>maple</wood><wood>ash</wood></stuff>";
0579: listenToDifferences(control, test);
0580: assertEquals("5th control xpath",
0581: "/stuff[1]/wood[2]/text()[1]", listener.controlXpath);
0582: assertEquals("5th test xpath", "/stuff[1]/wood[2]/text()[1]",
0583: listener.testXpath);
0584: }
0585:
0586: public void testXpathLocation6() throws Exception {
0587: String control = "<stuff><list><wood/><glass/></list><item/></stuff>";
0588: String test = "<stuff><list><wood/><glass/></list><item>description</item></stuff>";
0589: listenToDifferences(control, test);
0590: assertEquals("6th control xpath", "/stuff[1]/item[1]",
0591: listener.controlXpath);
0592: assertEquals("6th test xpath", "/stuff[1]/item[1]",
0593: listener.testXpath);
0594: }
0595:
0596: public void testXpathLocation7() throws Exception {
0597: String control = "<stuff><list><wood/></list></stuff>";
0598: String test = "<stuff><list><glass/></list></stuff>";
0599: listenToDifferences(control, test);
0600: assertEquals("7th control xpath", "/stuff[1]/list[1]/wood[1]",
0601: listener.controlXpath);
0602: assertEquals("7th test xpath", "/stuff[1]/list[1]/glass[1]",
0603: listener.testXpath);
0604: }
0605:
0606: public void testXpathLocation8() throws Exception {
0607: String control = "<stuff><list><!--wood--></list></stuff>";
0608: String test = "<stuff><list><!--glass--></list></stuff>";
0609: listenToDifferences(control, test);
0610: assertEquals("8th control xpath",
0611: "/stuff[1]/list[1]/comment()[1]", listener.controlXpath);
0612: assertEquals("8th test xpath",
0613: "/stuff[1]/list[1]/comment()[1]", listener.testXpath);
0614: }
0615:
0616: public void testXpathLocation9() throws Exception {
0617: String control = "<stuff><list/><?wood rough?><list/></stuff>";
0618: String test = "<stuff><list/><?glass clear?><list/></stuff>";
0619: listenToDifferences(control, test);
0620: assertEquals("9th control xpath",
0621: "/stuff[1]/processing-instruction()[1]",
0622: listener.controlXpath);
0623: assertEquals("9th test xpath",
0624: "/stuff[1]/processing-instruction()[1]",
0625: listener.testXpath);
0626: }
0627:
0628: public void testXpathLocation10() throws Exception {
0629: String control = "<stuff><list/>list<![CDATA[wood]]></stuff>";
0630: String test = "<stuff><list/>list<![CDATA[glass]]></stuff>";
0631: listenToDifferences(control, test);
0632: assertEquals("10th control xpath", "/stuff[1]/text()[2]",
0633: listener.controlXpath);
0634: assertEquals("10th test xpath", "/stuff[1]/text()[2]",
0635: listener.testXpath);
0636: }
0637:
0638: public void testXpathLocation11() throws Exception {
0639: String control = "<stuff><list><item/></list></stuff>";
0640: String test = "<stuff><list>item text</list></stuff>";
0641: listenToDifferences(control, test);
0642: assertEquals("11th control xpath", "/stuff[1]/list[1]/item[1]",
0643: listener.controlXpath);
0644: assertEquals("11th test xpath", "/stuff[1]/list[1]/text()[1]",
0645: listener.testXpath);
0646: }
0647:
0648: public void testXpathLocation12() throws Exception {
0649: engine = new DifferenceEngine(PSEUDO_DETAILED_DIFF);
0650: String control = "<stuff><item id=\"1\"/><item id=\"2\"/></stuff>";
0651: String test = "<stuff><item id=\"1\"/></stuff>";
0652: listenToDifferences(control, test);
0653: assertEquals("12th control xpath", "/stuff[1]/item[2]",
0654: listener.controlXpath);
0655: assertEquals("12th test xpath", "/stuff[1]/item[1]",
0656: listener.testXpath);
0657: }
0658:
0659: public void testXpathLocation13() throws Exception {
0660: engine = new DifferenceEngine(PSEUDO_DETAILED_DIFF);
0661: String control = "<stuff><item id=\"1\"/><item id=\"2\"/></stuff>";
0662: String test = "<stuff><?item data?></stuff>";
0663: listenToDifferences(control, test);
0664: assertEquals("13th control xpath", "/stuff[1]/item[1]",
0665: listener.controlXpath);
0666: assertEquals("13th test xpath",
0667: "/stuff[1]/processing-instruction()[1]",
0668: listener.testXpath);
0669: }
0670:
0671: public void testXpathLocation14() throws Exception {
0672: engine = new DifferenceEngine(PSEUDO_DETAILED_DIFF);
0673: String control = "<stuff><thing id=\"1\"/><item id=\"2\"/></stuff>";
0674: String test = "<stuff><item id=\"2\"/><item id=\"1\"/></stuff>";
0675: listenToDifferences(control, test);
0676: assertEquals("14th control xpath", "/stuff[1]/item[1]/@id",
0677: listener.controlXpath);
0678: assertEquals("14th test xpath", "/stuff[1]/item[2]/@id",
0679: listener.testXpath);
0680: }
0681:
0682: public void testIssue1027863() throws Exception {
0683: engine = new DifferenceEngine(PSEUDO_DETAILED_DIFF);
0684: String control = "<stuff><item id=\"1\"><thing/></item></stuff>";
0685: String test = "<stuff><item id=\"2\"/></stuff>";
0686: listenToDifferences(control, test);
0687: assertEquals("15th difference type",
0688: DifferenceEngine.HAS_CHILD_NODES_ID,
0689: listener.comparingWhat);
0690: assertEquals("15th difference control value", "true",
0691: listener.expected);
0692: assertEquals("15th difference test value", "false",
0693: listener.actual);
0694: assertEquals("15th control xpath", "/stuff[1]/item[1]",
0695: listener.controlXpath);
0696: assertEquals("15th test xpath", "/stuff[1]/item[1]",
0697: listener.testXpath);
0698: }
0699:
0700: public void testNormalizeWhitespace() {
0701: assertEquals("a b", DifferenceEngine
0702: .normalizeWhitespace("a\rb"));
0703: assertEquals("a b", DifferenceEngine
0704: .normalizeWhitespace("a b"));
0705: assertEquals("a b c d e f", DifferenceEngine
0706: .normalizeWhitespace("a\rb c\nd\te\r\n \tf"));
0707: }
0708:
0709: public void testAttributeSequence() throws Exception {
0710: testAttributeSequence(ATTR_SEQUENCE_ID);
0711: resetListener();
0712: XMLUnit.setIgnoreAttributeOrder(true);
0713: try {
0714: testAttributeSequence(-1);
0715: } finally {
0716: XMLUnit.setIgnoreAttributeOrder(false);
0717: }
0718: }
0719:
0720: private void testAttributeSequence(int expected) throws Exception {
0721: Element control = document.createElement("foo");
0722: Element test = document.createElement("foo");
0723: OrderPreservingNamedNodeMap controlMap = new OrderPreservingNamedNodeMap();
0724: OrderPreservingNamedNodeMap testMap = new OrderPreservingNamedNodeMap();
0725: for (int i = 0; i < 2; i++) {
0726: int j = 1 - i;
0727: Attr attrI = document.createAttribute("attr" + i);
0728: attrI.setValue(String.valueOf(i));
0729: Attr attrJ = document.createAttribute("attr" + j);
0730: attrJ.setValue(String.valueOf(j));
0731:
0732: control.setAttributeNode(attrI);
0733: controlMap.add(attrI);
0734: test.setAttributeNode(attrJ);
0735: testMap.add(attrJ);
0736: }
0737: engine.compareElementAttributes(control, test, controlMap,
0738: testMap, listener);
0739: assertEquals(expected, listener.comparingWhat);
0740: }
0741:
0742: public void testAttributeSequenceNS() throws Exception {
0743: testAttributeSequenceNS(ATTR_SEQUENCE_ID);
0744: resetListener();
0745: XMLUnit.setIgnoreAttributeOrder(true);
0746: try {
0747: testAttributeSequenceNS(-1);
0748: } finally {
0749: XMLUnit.setIgnoreAttributeOrder(false);
0750: }
0751: }
0752:
0753: private void testAttributeSequenceNS(int expected) throws Exception {
0754: Element control = document.createElementNS("ns", "foo");
0755: Element test = document.createElementNS("ns", "foo");
0756: OrderPreservingNamedNodeMap controlMap = new OrderPreservingNamedNodeMap();
0757: OrderPreservingNamedNodeMap testMap = new OrderPreservingNamedNodeMap();
0758: for (int i = 0; i < 2; i++) {
0759: int j = 1 - i;
0760: Attr attrI = document.createAttributeNS("ns", "attr" + i);
0761: attrI.setValue(String.valueOf(i));
0762: Attr attrJ = document.createAttributeNS("ns", "attr" + j);
0763: attrJ.setValue(String.valueOf(j));
0764:
0765: control.setAttributeNode(attrI);
0766: controlMap.add(attrI);
0767: test.setAttributeNode(attrJ);
0768: testMap.add(attrJ);
0769: }
0770: engine.compareElementAttributes(control, test, controlMap,
0771: testMap, listener);
0772: assertEquals(expected, listener.comparingWhat);
0773: }
0774:
0775: public void testExtraComment() {
0776: testExtraComment(true);
0777: resetListener();
0778: XMLUnit.setIgnoreComments(true);
0779: try {
0780: testExtraComment(false);
0781: } finally {
0782: XMLUnit.setIgnoreComments(false);
0783: }
0784: }
0785:
0786: private void testExtraComment(boolean expectDifference) {
0787: Element control = document.createElement("foo");
0788: Element test = document.createElement("foo");
0789: Comment c = document.createComment("bar");
0790: control.appendChild(c);
0791: Element cChild = document.createElement("baz");
0792: control.appendChild(cChild);
0793: Element tChild = document.createElement("baz");
0794: test.appendChild(tChild);
0795: engine.compare(control, test, listener, null);
0796: assertEquals(expectDifference, listener.different);
0797: resetListener();
0798: engine.compare(test, control, listener, null);
0799: assertEquals(expectDifference, listener.different);
0800: }
0801:
0802: public void testCommentContent() {
0803: testCommentContent(true);
0804: resetListener();
0805: XMLUnit.setIgnoreComments(true);
0806: try {
0807: testCommentContent(false);
0808: } finally {
0809: XMLUnit.setIgnoreComments(false);
0810: }
0811: }
0812:
0813: private void testCommentContent(boolean expectDifference) {
0814: Element control = document.createElement("foo");
0815: Element test = document.createElement("foo");
0816: Comment c = document.createComment("bar");
0817: control.appendChild(c);
0818: Comment c2 = document.createComment("baz");
0819: test.appendChild(c2);
0820: engine.compare(control, test, listener, null);
0821: assertEquals(expectDifference, listener.different);
0822: }
0823:
0824: public void testMissingSchemaLocation() throws Exception {
0825: testMissingXSIAttribute(
0826: XMLConstants.W3C_XML_SCHEMA_INSTANCE_SCHEMA_LOCATION_ATTR,
0827: DifferenceConstants.SCHEMA_LOCATION_ID);
0828: }
0829:
0830: public void testMissingNoNamespaceSchemaLocation() throws Exception {
0831: testMissingXSIAttribute(
0832: XMLConstants.W3C_XML_SCHEMA_INSTANCE_NO_NAMESPACE_SCHEMA_LOCATION_ATTR,
0833: DifferenceConstants.NO_NAMESPACE_SCHEMA_LOCATION_ID);
0834: }
0835:
0836: private void testMissingXSIAttribute(String attrName,
0837: int expectedDifference) throws Exception {
0838: Element control = document.createElement("foo");
0839: control.setAttributeNS(
0840: XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, attrName,
0841: "bar");
0842: Element test = document.createElement("foo");
0843: engine.compare(control, test, listener, null);
0844: assertEquals(expectedDifference, listener.comparingWhat);
0845: resetListener();
0846: engine.compare(test, control, listener, null);
0847: assertEquals(expectedDifference, listener.comparingWhat);
0848: }
0849:
0850: public void testDifferentSchemaLocation() throws Exception {
0851: testDifferentXSIAttribute(
0852: XMLConstants.W3C_XML_SCHEMA_INSTANCE_SCHEMA_LOCATION_ATTR,
0853: DifferenceConstants.SCHEMA_LOCATION_ID);
0854: }
0855:
0856: public void testDifferentNoNamespaceSchemaLocation()
0857: throws Exception {
0858: testDifferentXSIAttribute(
0859: XMLConstants.W3C_XML_SCHEMA_INSTANCE_NO_NAMESPACE_SCHEMA_LOCATION_ATTR,
0860: DifferenceConstants.NO_NAMESPACE_SCHEMA_LOCATION_ID);
0861: }
0862:
0863: private void testDifferentXSIAttribute(String attrName,
0864: int expectedDifference) throws Exception {
0865: Element control = document.createElement("foo");
0866: control.setAttributeNS(
0867: XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, attrName,
0868: "bar");
0869: Element test = document.createElement("foo");
0870: test.setAttributeNS(
0871: XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, attrName,
0872: "baz");
0873: engine.compare(control, test, listener, null);
0874: assertEquals(expectedDifference, listener.comparingWhat);
0875: }
0876:
0877: public void testMissingAttribute() throws Exception {
0878: Element control = document.createElement("foo");
0879: control.setAttribute("bar", "baz");
0880: Element test = document.createElement("foo");
0881: test.setAttribute("baz", "bar");
0882: engine.compare(control, test, listener, null);
0883: assertEquals(ATTR_NAME_NOT_FOUND_ID, listener.comparingWhat);
0884: }
0885:
0886: private void listenToDifferences(String control, String test)
0887: throws SAXException, IOException {
0888: Document controlDoc = XMLUnit.buildControlDocument(control);
0889: Document testDoc = XMLUnit.buildTestDocument(test);
0890: engine.compare(controlDoc, testDoc, listener,
0891: DEFAULT_ELEMENT_QUALIFIER);
0892: }
0893:
0894: private void resetListener() {
0895: listener = new CollectingDifferenceListener();
0896: }
0897:
0898: public void setUp() throws Exception {
0899: resetListener();
0900: engine = new DifferenceEngine(PSEUDO_DIFF);
0901: DocumentBuilder documentBuilder = XMLUnit.newControlParser();
0902: document = documentBuilder.newDocument();
0903: }
0904:
0905: private class SimpleComparisonController implements
0906: ComparisonController {
0907: public boolean haltComparison(Difference afterDifference) {
0908: return !afterDifference.isRecoverable();
0909: }
0910: }
0911:
0912: private class NeverHaltingComparisonController implements
0913: ComparisonController {
0914: public boolean haltComparison(Difference afterDifference) {
0915: return false;
0916: }
0917: }
0918:
0919: private class CollectingDifferenceListener implements
0920: DifferenceListener {
0921: public String expected;
0922: public String actual;
0923: public Node control;
0924: public Node test;
0925: public int comparingWhat = -1;
0926: public boolean different = false;
0927: public boolean nodesSkipped = false;
0928: public String controlXpath;
0929: public String testXpath;
0930: private boolean tracing = false;
0931:
0932: public int differenceFound(Difference difference) {
0933: if (tracing) {
0934: System.out.println(difference.toString());
0935: }
0936: assertNotNull("difference not null", difference);
0937: assertNotNull("control node detail not null", difference
0938: .getControlNodeDetail());
0939: assertNotNull("test node detail not null", difference
0940: .getTestNodeDetail());
0941: this .expected = difference.getControlNodeDetail()
0942: .getValue();
0943: this .actual = difference.getTestNodeDetail().getValue();
0944: this .control = difference.getControlNodeDetail().getNode();
0945: this .test = difference.getTestNodeDetail().getNode();
0946: this .comparingWhat = difference.getId();
0947: this .different = !difference.isRecoverable();
0948: this .controlXpath = difference.getControlNodeDetail()
0949: .getXpathLocation();
0950: this .testXpath = difference.getTestNodeDetail()
0951: .getXpathLocation();
0952: return RETURN_ACCEPT_DIFFERENCE;
0953: }
0954:
0955: public void skippedComparison(Node control, Node test) {
0956: nodesSkipped = true;
0957: }
0958:
0959: public void setTrace(boolean active) {
0960: tracing = active;
0961: }
0962: }
0963:
0964: private class OrderPreservingNamedNodeMap implements NamedNodeMap {
0965: private ArrayList/* Attr */nodes = new ArrayList();
0966:
0967: void add(Attr attr) {
0968: nodes.add(attr);
0969: }
0970:
0971: public int getLength() {
0972: return nodes.size();
0973: }
0974:
0975: public Node item(int index) {
0976: return (Node) nodes.get(index);
0977: }
0978:
0979: public Node getNamedItem(String name) {
0980: for (Iterator iter = nodes.iterator(); iter.hasNext();) {
0981: Attr a = (Attr) iter.next();
0982: if (a.getName().equals(name)) {
0983: return a;
0984: }
0985: }
0986: return null;
0987: }
0988:
0989: public Node getNamedItemNS(String ns, String localName) {
0990: for (Iterator iter = nodes.iterator(); iter.hasNext();) {
0991: Attr a = (Attr) iter.next();
0992: if (a.getLocalName().equals(localName)
0993: && a.getNamespaceURI().equals(ns)) {
0994: return a;
0995: }
0996: }
0997: return null;
0998: }
0999:
1000: // not implemented, not needed in our case
1001: public Node removeNamedItem(String n) {
1002: return fail();
1003: }
1004:
1005: public Node removeNamedItemNS(String n1, String n2) {
1006: return fail();
1007: }
1008:
1009: public Node setNamedItem(Node n) {
1010: return fail();
1011: }
1012:
1013: public Node setNamedItemNS(Node n) {
1014: return fail();
1015: }
1016:
1017: private Node fail() {
1018: throw new RuntimeException("not implemented");
1019: }
1020: }
1021: }
|