From: Tomas Cere Date: Mon, 11 May 2015 08:03:18 +0000 (+0200) Subject: Add NetconfXmlUnitRecursiveQualifier to netconf-util. X-Git-Tag: release/beryllium~600 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=7049800718ec3d481a04f56550ccce5404a0300b;hp=feaf6ccc9fdd1451697d135ea4b54dd4629fc345 Add NetconfXmlUnitRecursiveQualifier to netconf-util. XmlUnit's RecursiveElementNameAndTextQualifier has trouble with non-trivial xml's and element order in bigger depths. This adds our own qualifier based on XmlUnit's implementation. Change-Id: Ie89e84813e11cb2af7c9d3c0c6d80377816f79a7 Signed-off-by: Tomas Cere --- diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/NetconfXmlUnitRecursiveQualifier.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/NetconfXmlUnitRecursiveQualifier.java new file mode 100644 index 0000000000..fb416009c5 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/NetconfXmlUnitRecursiveQualifier.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.netconf.util.test; + +import org.custommonkey.xmlunit.ElementNameAndTextQualifier; +import org.custommonkey.xmlunit.ElementQualifier; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * Custom xmlunit qualifier that doesn't care about order when deeper in the recursion + * defaults to comparing element name and text content + */ +public class NetconfXmlUnitRecursiveQualifier implements ElementQualifier { + + private final ElementQualifier qualifier; + + public NetconfXmlUnitRecursiveQualifier() { + this.qualifier = new ElementNameAndTextQualifier(); + } + + public NetconfXmlUnitRecursiveQualifier(final ElementQualifier qualifier) { + this.qualifier = qualifier; + } + + @Override + public boolean qualifyForComparison(Element currentControl, + Element currentTest) { + return compareNodes(currentControl, currentTest); + } + + private boolean compareNodes(Node currentControl, Node currentTest) { + try { + + if (!qualifier.qualifyForComparison((Element) currentControl, + (Element) currentTest)) { + return false; + } + + NodeList controlNodes; + NodeList testNodes; + + if (currentControl.hasChildNodes() && currentTest.hasChildNodes()) { + controlNodes = currentControl.getChildNodes(); + testNodes = currentTest.getChildNodes(); + } else { + return !(currentControl.hasChildNodes() || currentTest.hasChildNodes()); + } + + return (countNodesWithoutConsecutiveTextNodes(controlNodes) == countNodesWithoutConsecutiveTextNodes(testNodes)) + && checkChildren(controlNodes, testNodes); + + } catch (Exception e) { + return false; + } + } + + private boolean checkChildren(NodeList controlNodes, NodeList testNodes) { + for (int i = 0; i < controlNodes.getLength(); i++) { + boolean matchFound = false; + for (int j = 0; j < testNodes.getLength(); j++) { + Node controlNode = controlNodes.item(i); + Node testNode = testNodes.item(j); + + if (controlNode.getNodeType() != testNode.getNodeType()) { + continue; + } + + if (controlNode.getNodeType() == Node.TEXT_NODE) { + if (concatenateText(controlNode).equals(concatenateText(testNode))) { + matchFound = true; + break; + } + + } else if (compareNodes(controlNode, testNode)) { + matchFound = true; + break; + } + } + if (!matchFound) { + return false; + } + } + + return true; + } + + private static String concatenateText(Node textNode) { + StringBuilder builder = new StringBuilder(); + Node next = textNode; + + do { + if (next.getNodeValue() != null) { + builder.append(next.getNodeValue().trim()); + next = next.getNextSibling(); + } + } while (next != null && next.getNodeType() == Node.TEXT_NODE); + + return builder.toString(); + } + + 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; + } +}