From: <bo...@us...> - 2010-05-05 15:47:27
|
Revision: 379 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=379&view=rev Author: bodewig Date: 2010-05-05 15:47:17 +0000 (Wed, 05 May 2010) Log Message: ----------- replace old ElementQualifiers with new code that (almost) does the same Modified Paths: -------------- trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameAndAttributeQualifier.java trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameAndTextQualifier.java trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameQualifier.java trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/examples/RecursiveElementNameAndTextQualifier.java trunk/xmlunit/src/tests/java-legacy/org/custommonkey/xmlunit/test_ElementNameAndAttributeQualifier.java Added Paths: ----------- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/ElementSelectors.java trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/Nodes.java trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/ trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/ElementSelectorsTest.java trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/util/NodesTest.java Added: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/ElementSelectors.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/ElementSelectors.java (rev 0) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/ElementSelectors.java 2010-05-05 15:47:17 UTC (rev 379) @@ -0,0 +1,277 @@ +/* + This file is licensed to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package net.sf.xmlunit.diff; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import javax.xml.namespace.QName; +import net.sf.xmlunit.util.Nodes; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Element; +import org.w3c.dom.Text; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Common ElementSelector implementations. + */ +public final class ElementSelectors { + private ElementSelectors() { } + + /** + * Always returns true, i.e. each element can be compared to each + * other element. + * + * <p>Generally this means elements will be compared in document + * order.</p> + */ + public static final ElementSelector Default = new ElementSelector() { + public boolean canBeCompared(Element controlElement, + Element testElement) { + return true; + } + }; + + /** + * Elements with the same local name (and namespace URI - if any) + * can be compared. + */ + public static final ElementSelector byName = new ElementSelector() { + public boolean canBeCompared(Element controlElement, + Element testElement) { + return controlElement != null + && testElement != null + && bothNullOrEqual(Nodes.getQName(controlElement), + Nodes.getQName(testElement)); + } + }; + + /** + * Elements with the same local name (and namespace URI - if any) + * and nested text (if any) can be compared. + */ + public static final ElementSelector byNameAndText = new ElementSelector() { + public boolean canBeCompared(Element controlElement, + Element testElement) { + return byName.canBeCompared(controlElement, testElement) + && bothNullOrEqual(Nodes.getMergedNestedText(controlElement), + Nodes.getMergedNestedText(testElement)); + } + }; + + /** + * Elements with the same local name (and namespace URI - if any) + * and attribute values for the given attribute names can be + * compared. + * + * <p>Attributes are only searched for in the null namespace.</p> + */ + public static ElementSelector byNameAndAttributes(String... attribs) { + if (attribs == null) { + throw new IllegalArgumentException("attributes must not be null"); + } + QName[] qs = new QName[attribs.length]; + for (int i = 0; i < attribs.length; i++) { + qs[i] = new QName(attribs[i]); + } + return byNameAndAttributes(qs); + } + + /** + * Elements with the same local name (and namespace URI - if any) + * and attribute values for the given attribute names can be + * compared. + * + * <p>Namespace URIs of attributes are those of the attributes on + * the control element or the null namespace if the don't + * exist.</p> + */ + public static ElementSelector + byNameAndAttributesControlNS(final String... attribs) { + + if (attribs == null) { + throw new IllegalArgumentException("attributes must not be null"); + } + final HashSet<String> as = new HashSet(Arrays.asList(attribs)); + return new ElementSelector() { + public boolean canBeCompared(Element controlElement, + Element testElement) { + if (!byName.canBeCompared(controlElement, testElement)) { + return false; + } + Map<QName, String> cAttrs = Nodes.getAttributes(controlElement); + Map<String, QName> qNameByLocalName = + new HashMap<String, QName>(); + for (QName q : cAttrs.keySet()) { + String local = q.getLocalPart(); + if (as.contains(local)) { + qNameByLocalName.put(local, q); + } + } + for (String a : attribs) { + QName q = qNameByLocalName.get(a); + if (q == null) { + qNameByLocalName.put(a, new QName(a)); + } + } + return mapsEqualForKeys(cAttrs, + Nodes.getAttributes(testElement), + qNameByLocalName.values()); + } + }; + } + + /** + * Elements with the same local name (and namespace URI - if any) + * and attribute values for the given attribute names can be + * compared. + */ + public static ElementSelector byNameAndAttributes(final QName... attribs) { + if (attribs == null) { + throw new IllegalArgumentException("attributes must not be null"); + } + final Collection<QName> qs = Arrays.asList(attribs); + return new ElementSelector() { + public boolean canBeCompared(Element controlElement, + Element testElement) { + if (!byName.canBeCompared(controlElement, testElement)) { + return false; + } + return mapsEqualForKeys(Nodes.getAttributes(controlElement), + Nodes.getAttributes(testElement), + qs); + } + }; + } + + /** + * Elements with the same local name (and namespace URI - if any) + * and attribute values for all attributes can be compared. + */ + public static final ElementSelector byNameAndAllAttributes = + new ElementSelector() { + public boolean canBeCompared(Element controlElement, + Element testElement) { + if (!byName.canBeCompared(controlElement, testElement)) { + return false; + } + Map<QName, String> cAttrs = Nodes.getAttributes(controlElement); + Map<QName, String> tAttrs = Nodes.getAttributes(testElement); + if (cAttrs.size() != tAttrs.size()) { + return false; + } + return mapsEqualForKeys(cAttrs, tAttrs, cAttrs.keySet()); + } + }; + + /** + * Elements with the same local name (and namespace URI - if any) + * and child elements and nested text at each level (if any) can + * be compared. + */ + public static final ElementSelector + byNameAndTextRec = new ElementSelector() { + public boolean canBeCompared(Element controlElement, + Element testElement) { + if (!byNameAndText.canBeCompared(controlElement, + testElement)) { + return false; + } + NodeList controlChildren = controlElement.getChildNodes(); + NodeList testChildren = testElement.getChildNodes(); + final int controlLen = controlChildren.getLength(); + final int testLen = testChildren.getLength(); + int controlIndex, testIndex; + for (controlIndex = testIndex = 0; + controlIndex < controlLen && testIndex < testLen; + ) { + // find next non-text child nodes + Node c = controlChildren.item(controlIndex); + while (isText(c) && ++controlIndex < controlLen) { + c = controlChildren.item(controlIndex); + } + if (isText(c)) { + break; + } + Node t = testChildren.item(testIndex); + while (isText(t) && ++testIndex < testLen) { + t = testChildren.item(testIndex); + } + if (isText(t)) { + break; + } + + // different types of children make elements + // non-comparable + if (c.getNodeType() != t.getNodeType()) { + return false; + } + // recurse for child elements + if (c instanceof Element + && !byNameAndTextRec.canBeCompared((Element) c, + (Element) t)) { + return false; + } + + controlIndex++; + testIndex++; + } + + // child lists exhausted? + if (controlIndex < controlLen) { + Node n = controlChildren.item(controlIndex); + while (isText(n) && ++controlIndex < controlLen) { + n = controlChildren.item(controlIndex); + } + // some non-Text children remained + if (controlIndex < controlLen) { + return false; + } + } + if (testIndex < testLen) { + Node n = testChildren.item(testIndex); + while (isText(n) && ++testIndex < testLen) { + n = testChildren.item(testIndex); + } + // some non-Text children remained + if (testIndex < testLen) { + return false; + } + } + return true; + } + }; + + private static boolean bothNullOrEqual(Object o1, Object o2) { + return o1 == null ? o2 == null : o1.equals(o2); + } + + private static boolean mapsEqualForKeys(Map<QName, String> control, + Map<QName, String> test, + Iterable<QName> keys) { + for (QName q : keys) { + if (!bothNullOrEqual(control.get(q), test.get(q))) { + return false; + } + } + return true; + } + + private static boolean isText(Node n) { + return n instanceof Text || n instanceof CDATASection; + } +} \ No newline at end of file Property changes on: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/ElementSelectors.java ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/Nodes.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/Nodes.java (rev 0) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/Nodes.java 2010-05-05 15:47:17 UTC (rev 379) @@ -0,0 +1,80 @@ +/* + This file is licensed to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package net.sf.xmlunit.util; + +import java.util.Map; +import java.util.LinkedHashMap; +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import org.w3c.dom.Attr; +import org.w3c.dom.CDATASection; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.Text; + +/** + * Utility algorithms that work on DOM nodes. + */ +public final class Nodes { + private Nodes() { } + + /** + * Extracts a Node's name, namespace URI (if any) and prefix as a + * QName. + */ + public static QName getQName(Node n) { + String s = n.getLocalName(); + String p = n.getPrefix(); + return s != null + ? new QName(n.getNamespaceURI(), s, + p != null ? p: XMLConstants.DEFAULT_NS_PREFIX) + : new QName(n.getNodeName()); + } + + /** + * Tries to merge all direct Text and CDATA children of the given + * Node and concatenates their value. + * + * @return an empty string if the Node has no Text or CDATA + * children. + */ + public static String getMergedNestedText(Node n) { + StringBuilder sb = new StringBuilder(); + for (Node child : new IterableNodeList(n.getChildNodes())) { + if (child instanceof Text || child instanceof CDATASection) { + String s = child.getNodeValue(); + if (s != null) { + sb.append(s); + } + } + } + return sb.toString(); + } + + /** + * Obtains an element's attributes as Map. + */ + public static Map<QName, String> getAttributes(Node n) { + Map<QName, String> map = new LinkedHashMap<QName, String>(); + NamedNodeMap m = n.getAttributes(); + if (m != null) { + final int len = m.getLength(); + for (int i = 0; i < len; i++) { + Attr a = (Attr) m.item(i); + map.put(getQName(a), a.getValue()); + } + } + return map; + } +} Property changes on: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/util/Nodes.java ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameAndAttributeQualifier.java =================================================================== --- trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameAndAttributeQualifier.java 2010-05-03 16:08:17 UTC (rev 378) +++ trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameAndAttributeQualifier.java 2010-05-05 15:47:17 UTC (rev 379) @@ -37,6 +37,8 @@ package org.custommonkey.xmlunit; import java.util.Arrays; +import net.sf.xmlunit.diff.ElementSelector; +import net.sf.xmlunit.diff.ElementSelectors; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; @@ -50,10 +52,11 @@ * @see Diff#overrideElementQualifier(ElementQualifier) */ public class ElementNameAndAttributeQualifier extends ElementNameQualifier { + private final ElementSelector selector; private static final String[] ALL_ATTRIBUTES = {"*"}; - + private final String[] qualifyingAttrNames; - + /** * No-args constructor: use all attributes from all elements to determine * whether elements qualify for comparability @@ -61,7 +64,7 @@ public ElementNameAndAttributeQualifier() { this(ALL_ATTRIBUTES); } - + /** * Simple constructor for a single qualifying attribute name * @param attrName the value to use to qualify whether two elements can be @@ -80,6 +83,9 @@ this.qualifyingAttrNames = new String[attrNames.length]; System.arraycopy(attrNames, 0, qualifyingAttrNames, 0, attrNames.length); + selector = matchesAllAttributes(attrNames) + ? ElementSelectors.byNameAndAllAttributes + : ElementSelectors.byNameAndAttributesControlNS(attrNames); } /** @@ -94,12 +100,9 @@ * false otherwise */ public boolean qualifyForComparison(Element control, Element test) { - if (super.qualifyForComparison(control, test)) { - return areAttributesComparable(control, test); - } - return false; + return selector.canBeCompared(control, test); } - + /** * Determine whether the qualifying attributes are present in both elements * and if so whether their values are the same @@ -123,7 +126,7 @@ qualifyingAttributes[n] = (Attr) namedNodeMap.getNamedItem(qualifyingAttrNames[n]); } } - + String nsURI, name; for (int i=0; i < qualifyingAttributes.length; ++i) { if (qualifyingAttributes[i] != null) { Modified: trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameAndTextQualifier.java =================================================================== --- trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameAndTextQualifier.java 2010-05-03 16:08:17 UTC (rev 378) +++ trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameAndTextQualifier.java 2010-05-05 15:47:17 UTC (rev 379) @@ -36,6 +36,7 @@ package org.custommonkey.xmlunit; +import net.sf.xmlunit.diff.ElementSelectors; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -60,19 +61,16 @@ * elements; false otherwise */ public boolean qualifyForComparison(Element control, Element test) { - if (super.qualifyForComparison(control, test)) { - return similar(extractText(control), extractText(test)); - } - return false; + return ElementSelectors.byNameAndText.canBeCompared(control, test); } - + /** * Determine whether the text nodes contain similar values * @param control * @param test * @return true if text nodes are similar, false otherwise */ - protected boolean similar(Text control, Text test) { + protected boolean similar(Text control, Text test) { if (control == null) { return test == null; } else if (test == null) { @@ -97,6 +95,6 @@ } } return null; - } + } } Modified: trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameQualifier.java =================================================================== --- trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameQualifier.java 2010-05-03 16:08:17 UTC (rev 378) +++ trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/ElementNameQualifier.java 2010-05-05 15:47:17 UTC (rev 379) @@ -36,6 +36,7 @@ package org.custommonkey.xmlunit; +import net.sf.xmlunit.diff.ElementSelectors; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -58,10 +59,9 @@ * false otherwise */ public boolean qualifyForComparison(Element control, Element test) { - return control != null && test !=null - && equalsNamespace(control, test) - && getNonNamespacedNodeName(control).equals(getNonNamespacedNodeName(test)); + return ElementSelectors.byName.canBeCompared(control, test); } + /** * Determine whether two nodes are defined by the same namespace URI * @param control @@ -77,7 +77,7 @@ } return controlNS.equals(testNS); } - + /** * Strip any namespace information off a node name * @param node Modified: trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/examples/RecursiveElementNameAndTextQualifier.java =================================================================== --- trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/examples/RecursiveElementNameAndTextQualifier.java 2010-05-03 16:08:17 UTC (rev 378) +++ trunk/xmlunit/src/main/java-legacy/org/custommonkey/xmlunit/examples/RecursiveElementNameAndTextQualifier.java 2010-05-05 15:47:17 UTC (rev 379) @@ -36,11 +36,8 @@ package org.custommonkey.xmlunit.examples; +import net.sf.xmlunit.diff.ElementSelectors; import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import org.custommonkey.xmlunit.ElementNameQualifier; import org.custommonkey.xmlunit.ElementQualifier; /** @@ -52,9 +49,6 @@ */ public class RecursiveElementNameAndTextQualifier implements ElementQualifier { - private static final ElementNameQualifier NAME_QUALIFIER = - new ElementNameQualifier(); - /** * Uses element names and the text nested an arbitrary level of * child elements deeper into the element to compare @@ -71,128 +65,7 @@ */ public boolean qualifyForComparison(Element currentControl, Element currentTest) { - return compareNodes(currentControl, currentTest); + return ElementSelectors.byNameAndTextRec.canBeCompared(currentControl, + currentTest); } - - private boolean compareNodes(Node currentControl, Node currentTest) { - try { - - // if they are elements, compare names of the two nodes - if (!NAME_QUALIFIER.qualifyForComparison((Element) currentControl, - (Element) currentTest)) { - return false; - } - - // Compare the control and test elements' children - - NodeList controlNodes = null; - NodeList testNodes = null; - - // Check that both nodes have children and, if so, get lists of them - - if (currentControl.hasChildNodes() && currentTest.hasChildNodes()) { - controlNodes = currentControl.getChildNodes(); - testNodes = currentTest.getChildNodes(); - } else if (currentControl.hasChildNodes() - || currentTest.hasChildNodes()) { - return false; - - // if both nodes are empty, they are comparable - } else { - return true; - } - - // check that both node lists have the same length - - if (countNodesWithoutConsecutiveTextNodes(controlNodes) - != countNodesWithoutConsecutiveTextNodes(testNodes)) { - return false; - } - - // Do checks of test and control nodes' children - - final int cNodes = controlNodes.getLength(); - final int tNodes = testNodes.getLength(); - - int i, j; - for (i = j = 0; i < cNodes && j < tNodes; i++, j++) { - Node testNode = testNodes.item(i); - Node controlNode = controlNodes.item(j); - - // check if both node are same type - if (controlNode.getNodeType() != testNode.getNodeType()) { - return false; - } - // compare text nodes - if (controlNode.getNodeType() == Node.TEXT_NODE) { - // compare concatenated, trimmed text nodes - if (!catText(controlNode).equals(catText(testNode))) { - return false; - } - - // swallow adjacent Text nodes - for (; i < cNodes - 1 - && controlNodes.item(i + 1).getNodeType() == Node.TEXT_NODE; - i++); - for (; j < tNodes - 1 - && testNodes.item(j + 1).getNodeType() == Node.TEXT_NODE; - j++); - - // recursive check of current child control and test nodes' - // children - - } else if (!compareNodes((Element) controlNode, - (Element) testNode)) { - return false; - } - } - if (i != cNodes || j != tNodes) { - return false; - } - - // All descendants of current control and test nodes are comparable - return true; - } catch (Exception e) { - return false; - } - } - /** - * Concatenates contiguous Text nodes and removes all leading and - * trailing whitespace. - * @param textNode - * @return - */ - private static String catText(Node textNode) { - StringBuffer text = new StringBuffer(); - Node next = textNode; - - do { - if (next.getNodeValue() != null) { - text.append(next.getNodeValue().trim()); - next = next.getNextSibling(); - } - } while (next != null && next.getNodeType() == Node.TEXT_NODE); - - return text.toString(); - } - - /** - * Calculates the number of Nodes that are either not Text nodes - * or are Text nodes whose previous sibling isn't a Text node as - * well. I.e. consecutive Text nodes are counted as a single - * node. - */ - private static int countNodesWithoutConsecutiveTextNodes(NodeList l) { - int count = 0; - boolean lastNodeWasText = false; - final int length = l.getLength(); - for (int i = 0; i < length; i++) { - Node n = l.item(i); - if (!lastNodeWasText || n.getNodeType() != Node.TEXT_NODE) { - count++; - } - lastNodeWasText = n.getNodeType() == Node.TEXT_NODE; - } - return count; - } } Added: trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/ElementSelectorsTest.java =================================================================== --- trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/ElementSelectorsTest.java (rev 0) +++ trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/ElementSelectorsTest.java 2010-05-05 15:47:17 UTC (rev 379) @@ -0,0 +1,278 @@ +/* + This file is licensed to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package net.sf.xmlunit.diff; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.junit.Before; +import org.junit.Test; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.Text; + +import static org.junit.Assert.*; + +public class ElementSelectorsTest { + private static final String FOO = "foo"; + private static final String BAR = "bar"; + private static final String SOME_URI = "urn:some:uri"; + + private Document doc; + + @Before public void createDoc() throws Exception { + doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() + .newDocument(); + } + + private void pureElementNameComparisons(ElementSelector s) { + Element control = doc.createElement(FOO); + Element equal = doc.createElement(FOO); + Element different = doc.createElement(BAR); + Element controlNS = doc.createElementNS(SOME_URI, FOO); + controlNS.setPrefix(BAR); + + assertFalse(s.canBeCompared(null, null)); + assertFalse(s.canBeCompared(null, control)); + assertFalse(s.canBeCompared(control, null)); + assertTrue(s.canBeCompared(control, equal)); + assertFalse(s.canBeCompared(control, different)); + assertFalse(s.canBeCompared(control, controlNS)); + assertTrue(s.canBeCompared(doc.createElementNS(SOME_URI, FOO), + controlNS)); + } + + @Test public void byName() { + pureElementNameComparisons(ElementSelectors.byName); + } + + @Test public void byNameAndText_NamePart() { + pureElementNameComparisons(ElementSelectors.byNameAndText); + } + + private void byNameAndText_SingleLevel(ElementSelector s) { + Element control = doc.createElement(FOO); + control.appendChild(doc.createTextNode(BAR)); + Element equal = doc.createElement(FOO); + equal.appendChild(doc.createTextNode(BAR)); + Element equalC = doc.createElement(FOO); + equalC.appendChild(doc.createCDATASection(BAR)); + Element noText = doc.createElement(FOO); + Element differentText = doc.createElement(FOO); + differentText.appendChild(doc.createTextNode(BAR)); + differentText.appendChild(doc.createTextNode(BAR)); + + assertTrue(s.canBeCompared(control, equal)); + assertTrue(s.canBeCompared(control, equalC)); + assertFalse(s.canBeCompared(control, noText)); + assertFalse(s.canBeCompared(control, differentText)); + } + + @Test public void byNameAndText() { + byNameAndText_SingleLevel(ElementSelectors.byNameAndText); + } + + @Test public void byNameAndTextRec_NamePart() { + pureElementNameComparisons(ElementSelectors.byNameAndTextRec); + } + + @Test public void byNameAndTextRec_Single() { + byNameAndText_SingleLevel(ElementSelectors.byNameAndTextRec); + } + + private void byNameAndTextRec() { + Element control = doc.createElement(FOO); + Element child = doc.createElement(BAR); + control.appendChild(child); + child.appendChild(doc.createTextNode(BAR)); + Element equal = doc.createElement(FOO); + Element child2 = doc.createElement(BAR); + equal.appendChild(child2); + child2.appendChild(doc.createTextNode(BAR)); + Element equalC = doc.createElement(FOO); + Element child3 = doc.createElement(BAR); + equalC.appendChild(child3); + child3.appendChild(doc.createCDATASection(BAR)); + Element noText = doc.createElement(FOO); + Element differentLevel = doc.createElement(FOO); + differentLevel.appendChild(doc.createTextNode(BAR)); + Element differentElement = doc.createElement(FOO); + Element child4 = doc.createElement(FOO); + differentElement.appendChild(child4); + child4.appendChild(doc.createTextNode(BAR)); + Element differentText = doc.createElement(FOO); + Element child5 = doc.createElement(BAR); + differentText.appendChild(child5); + child5.appendChild(doc.createTextNode(FOO)); + + ElementSelector s = ElementSelectors.byNameAndTextRec; + assertTrue(s.canBeCompared(control, equal)); + assertTrue(s.canBeCompared(control, equalC)); + assertFalse(s.canBeCompared(control, noText)); + assertFalse(s.canBeCompared(control, differentLevel)); + assertFalse(s.canBeCompared(control, differentElement)); + assertFalse(s.canBeCompared(control, differentText)); + } + + @Test public void byNameAndAllAttributes_NamePart() { + pureElementNameComparisons(ElementSelectors.byNameAndAllAttributes); + } + + @Test public void byNameAndAllAttributes() { + Element control = doc.createElement(FOO); + control.setAttribute(BAR, BAR); + Element equal = doc.createElement(FOO); + equal.setAttribute(BAR, BAR); + Element noAttributes = doc.createElement(FOO); + Element differentValue = doc.createElement(FOO); + differentValue.setAttribute(BAR, FOO); + Element differentName = doc.createElement(FOO); + differentName.setAttribute(FOO, FOO); + Element differentNS = doc.createElement(FOO); + differentNS.setAttributeNS(SOME_URI, BAR, BAR); + + assertTrue(ElementSelectors.byNameAndAllAttributes + .canBeCompared(control, equal)); + assertFalse(ElementSelectors.byNameAndAllAttributes + .canBeCompared(control, noAttributes)); + assertFalse(ElementSelectors.byNameAndAllAttributes + .canBeCompared(noAttributes, control)); + assertFalse(ElementSelectors.byNameAndAllAttributes + .canBeCompared(control, differentValue)); + assertFalse(ElementSelectors.byNameAndAllAttributes + .canBeCompared(control, differentName)); + assertFalse(ElementSelectors.byNameAndAllAttributes + .canBeCompared(control, differentNS)); + } + + @Test public void byNameAndAttributes_NamePart() { + pureElementNameComparisons(ElementSelectors + .byNameAndAttributes(new String[] {})); + pureElementNameComparisons(ElementSelectors + .byNameAndAttributes(new QName[] {})); + pureElementNameComparisons(ElementSelectors.byNameAndAttributes(BAR)); + pureElementNameComparisons(ElementSelectors + .byNameAndAttributes(new QName(SOME_URI, + BAR))); + } + + @Test public void byNameAndAttributes_String() { + Element control = doc.createElement(FOO); + control.setAttribute(BAR, BAR); + Element equal = doc.createElement(FOO); + equal.setAttribute(BAR, BAR); + Element noAttributes = doc.createElement(FOO); + Element differentValue = doc.createElement(FOO); + differentValue.setAttribute(BAR, FOO); + Element differentName = doc.createElement(FOO); + differentName.setAttribute(FOO, FOO); + Element differentNS = doc.createElement(FOO); + differentNS.setAttributeNS(SOME_URI, BAR, BAR); + + assertTrue(ElementSelectors.byNameAndAttributes(BAR) + .canBeCompared(control, equal)); + assertFalse(ElementSelectors.byNameAndAttributes(BAR) + .canBeCompared(control, noAttributes)); + assertTrue(ElementSelectors.byNameAndAttributes(FOO) + .canBeCompared(control, noAttributes)); + assertTrue(ElementSelectors.byNameAndAttributes(new String[] {}) + .canBeCompared(control, noAttributes)); + assertFalse(ElementSelectors.byNameAndAttributes(BAR) + .canBeCompared(noAttributes, control)); + assertFalse(ElementSelectors.byNameAndAttributes(BAR) + .canBeCompared(control, differentValue)); + assertFalse(ElementSelectors.byNameAndAttributes(BAR) + .canBeCompared(control, differentName)); + assertFalse(ElementSelectors.byNameAndAttributes(BAR) + .canBeCompared(control, differentNS)); + } + + @Test public void byNameAndAttributes_QName() { + Element control = doc.createElement(FOO); + control.setAttribute(BAR, BAR); + Element equal = doc.createElement(FOO); + equal.setAttribute(BAR, BAR); + Element noAttributes = doc.createElement(FOO); + Element differentValue = doc.createElement(FOO); + differentValue.setAttribute(BAR, FOO); + Element differentName = doc.createElement(FOO); + differentName.setAttribute(FOO, FOO); + Element differentNS = doc.createElement(FOO); + differentNS.setAttributeNS(SOME_URI, BAR, BAR); + + assertTrue(ElementSelectors.byNameAndAttributes(new QName(BAR)) + .canBeCompared(control, equal)); + assertFalse(ElementSelectors.byNameAndAttributes(new QName(BAR)) + .canBeCompared(control, noAttributes)); + assertTrue(ElementSelectors.byNameAndAttributes(new QName(FOO)) + .canBeCompared(control, noAttributes)); + assertTrue(ElementSelectors.byNameAndAttributes(new QName[] {}) + .canBeCompared(control, noAttributes)); + assertFalse(ElementSelectors.byNameAndAttributes(new QName(BAR)) + .canBeCompared(noAttributes, control)); + assertFalse(ElementSelectors.byNameAndAttributes(new QName(BAR)) + .canBeCompared(control, differentValue)); + assertFalse(ElementSelectors.byNameAndAttributes(new QName(BAR)) + .canBeCompared(control, differentName)); + assertFalse(ElementSelectors.byNameAndAttributes(new QName(BAR)) + .canBeCompared(control, differentNS)); + } + + @Test public void byNameAndAttributesControlNS_NamePart() { + pureElementNameComparisons(ElementSelectors + .byNameAndAttributesControlNS()); + pureElementNameComparisons(ElementSelectors + .byNameAndAttributesControlNS(BAR)); + } + + @Test public void byNameAndAttributesControlNS() { + Element control = doc.createElement(FOO); + control.setAttributeNS(SOME_URI, BAR, BAR); + Element equal = doc.createElement(FOO); + equal.setAttributeNS(SOME_URI, BAR, BAR); + Element noAttributes = doc.createElement(FOO); + Element differentValue = doc.createElement(FOO); + differentValue.setAttributeNS(SOME_URI, BAR, FOO); + Element differentName = doc.createElement(FOO); + differentName.setAttributeNS(SOME_URI, FOO, FOO); + Element differentNS = doc.createElement(FOO); + differentNS.setAttributeNS(SOME_URI + "2", BAR, BAR); + Element noNS = doc.createElement(FOO); + noNS.setAttribute(BAR, BAR); + + assertTrue(ElementSelectors.byNameAndAttributesControlNS(BAR) + .canBeCompared(control, equal)); + assertFalse(ElementSelectors.byNameAndAttributesControlNS(BAR) + .canBeCompared(control, noAttributes)); + assertTrue(ElementSelectors.byNameAndAttributesControlNS(FOO) + .canBeCompared(control, noAttributes)); + assertTrue(ElementSelectors.byNameAndAttributesControlNS(new String[] {}) + .canBeCompared(control, noAttributes)); + assertTrue(ElementSelectors.byNameAndAttributesControlNS(BAR) + .canBeCompared(noAttributes, control)); + assertFalse(ElementSelectors.byNameAndAttributesControlNS(BAR) + .canBeCompared(noAttributes, noNS)); + assertFalse(ElementSelectors.byNameAndAttributesControlNS(BAR) + .canBeCompared(control, differentValue)); + assertFalse(ElementSelectors.byNameAndAttributesControlNS(BAR) + .canBeCompared(control, differentName)); + assertFalse(ElementSelectors.byNameAndAttributesControlNS(BAR) + .canBeCompared(control, differentNS)); + assertFalse(ElementSelectors.byNameAndAttributesControlNS(BAR) + .canBeCompared(control, noNS)); + } + +} Property changes on: trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/ElementSelectorsTest.java ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/util/NodesTest.java =================================================================== --- trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/util/NodesTest.java (rev 0) +++ trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/util/NodesTest.java 2010-05-05 15:47:17 UTC (rev 379) @@ -0,0 +1,141 @@ +/* + This file is licensed to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +package net.sf.xmlunit.util; + +import java.util.Map; +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.junit.Before; +import org.junit.Test; +import org.w3c.dom.CDATASection; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.Text; + +import static org.junit.Assert.*; + +public class NodesTest { + + private static final String FOO = "foo"; + private static final String BAR = "bar"; + private static final String SOME_URI = "urn:some:uri"; + + private Document doc; + + @Before public void createDoc() throws Exception { + doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() + .newDocument(); + } + + @Test public void qNameOfElementWithNoNs() { + Element e = doc.createElement(FOO); + QName q = Nodes.getQName(e); + assertEquals(FOO, q.getLocalPart()); + assertEquals(XMLConstants.NULL_NS_URI, q.getNamespaceURI()); + assertEquals(XMLConstants.DEFAULT_NS_PREFIX, q.getPrefix()); + assertEquals(new QName(FOO), q); + } + + @Test public void qNameOfElementWithNsNoPrefix() { + Element e = doc.createElementNS(SOME_URI, FOO); + QName q = Nodes.getQName(e); + assertEquals(FOO, q.getLocalPart()); + assertEquals(SOME_URI, q.getNamespaceURI()); + assertEquals(XMLConstants.DEFAULT_NS_PREFIX, q.getPrefix()); + assertEquals(new QName(SOME_URI, FOO), q); + } + + @Test public void qNameOfElementWithNsAndPrefix() { + Element e = doc.createElementNS(SOME_URI, FOO); + e.setPrefix(BAR); + QName q = Nodes.getQName(e); + assertEquals(FOO, q.getLocalPart()); + assertEquals(SOME_URI, q.getNamespaceURI()); + assertEquals(BAR, q.getPrefix()); + assertEquals(new QName(SOME_URI, FOO), q); + assertEquals(new QName(SOME_URI, FOO, BAR), q); + } + + @Test public void mergeNoTexts() { + Element e = doc.createElement(FOO); + assertEquals("", Nodes.getMergedNestedText(e)); + } + + @Test public void mergeSingleTextNode() { + Element e = doc.createElement(FOO); + Text t = doc.createTextNode(BAR); + e.appendChild(t); + assertEquals(BAR, Nodes.getMergedNestedText(e)); + } + + @Test public void mergeSingleCDATASection() { + Element e = doc.createElement(FOO); + CDATASection t = doc.createCDATASection(BAR); + e.appendChild(t); + assertEquals(BAR, Nodes.getMergedNestedText(e)); + } + + @Test public void mergeIgnoresTextOfChildren() { + Element e = doc.createElement(FOO); + Element c = doc.createElement("child"); + Text t = doc.createTextNode(BAR); + e.appendChild(c); + c.appendChild(t); + assertEquals("", Nodes.getMergedNestedText(e)); + } + + @Test public void mergeIgnoresComments() { + Element e = doc.createElement(FOO); + Comment c = doc.createComment(BAR); + e.appendChild(c); + assertEquals("", Nodes.getMergedNestedText(e)); + } + + @Test public void mergeMultipleChildren() { + Element e = doc.createElement(FOO); + CDATASection c = doc.createCDATASection(BAR); + e.appendChild(c); + e.appendChild(doc.createElement("child")); + Text t = doc.createTextNode(BAR); + e.appendChild(t); + assertEquals(BAR + BAR, Nodes.getMergedNestedText(e)); + } + + @Test public void attributeMapNoAttributes() { + Element e = doc.createElement(FOO); + Map<QName, String> m = Nodes.getAttributes(e); + assertEquals(0, m.size()); + } + + @Test public void attributeMapNoNS() { + Element e = doc.createElement(FOO); + e.setAttribute(FOO, BAR); + Map<QName, String> m = Nodes.getAttributes(e); + assertEquals(1, m.size()); + assertEquals(BAR, m.get(new QName(FOO))); + } + + @Test public void attributeMapwithNS() { + Element e = doc.createElement(FOO); + e.setAttributeNS(SOME_URI, FOO, BAR); + Map<QName, String> m = Nodes.getAttributes(e); + assertEquals(1, m.size()); + assertEquals(BAR, m.get(new QName(SOME_URI, FOO))); + assertEquals(BAR, m.get(new QName(SOME_URI, FOO, BAR))); + } +} Property changes on: trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/util/NodesTest.java ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/xmlunit/src/tests/java-legacy/org/custommonkey/xmlunit/test_ElementNameAndAttributeQualifier.java =================================================================== --- trunk/xmlunit/src/tests/java-legacy/org/custommonkey/xmlunit/test_ElementNameAndAttributeQualifier.java 2010-05-03 16:08:17 UTC (rev 378) +++ trunk/xmlunit/src/tests/java-legacy/org/custommonkey/xmlunit/test_ElementNameAndAttributeQualifier.java 2010-05-05 15:47:17 UTC (rev 379) @@ -142,13 +142,15 @@ final String nsURI = "http://xmlunit.sourceforge.net/tests"; elementNameAndAttributeQualifier = new ElementNameAndAttributeQualifier(); - testAssertionsFor(attrName, nsURI, new boolean[] {false, false}); + testAssertionsFor(attrName, nsURI, new boolean[] {false, false}, true); elementNameAndAttributeQualifier = new ElementNameAndAttributeQualifier(attrName); - testAssertionsFor(attrName, nsURI, new boolean[] {true, true}); + testAssertionsFor(attrName, nsURI, new boolean[] {true, true}, false); } - private void testAssertionsFor(String attrName, String nsURI, boolean[] expectedValues) + private void testAssertionsFor(String attrName, String nsURI, + boolean[] expectedValues, + boolean matchesAllAttributes) throws Exception { Element control = document.createElement(TAG_NAME); control.setAttributeNS(nsURI, attrName, "1"); @@ -161,10 +163,12 @@ assertTrue("qwerty id 1 comparable to qwerty id 1", elementNameAndAttributeQualifier.qualifyForComparison(control, test)); - String otherNsURI = nsURI + "/2"; - test.setAttributeNS(otherNsURI, attrName, "2"); - assertTrue("qwerty id 1 comparable to qwerty id 1 and other-NS id 2", - elementNameAndAttributeQualifier.qualifyForComparison(control, test)); + if (!matchesAllAttributes) { + String otherNsURI = nsURI + "/2"; + test.setAttributeNS(otherNsURI, attrName, "2"); + assertTrue("qwerty id 1 comparable to qwerty id 1 and other-NS id 2", + elementNameAndAttributeQualifier.qualifyForComparison(control, test)); + } control.setAttributeNS(nsURI, "uiop","true"); assertEquals("qwerty id 1 && uiop comparable to qwerty id 1", expectedValues[0], This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |