Fix bgpcep testtool deploy when running with snapshots.
[integration/test.git] / csit / libraries / XmlComparator.py
index b8adc3e0a96cbf2c3b9bd418fc43232990369a40..6d05e7e9e21aae8272815de4dc090c0dab5b3cea 100644 (file)
@@ -1,4 +1,4 @@
-'''
+"""
 Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
 
 This program and the accompanying materials are made available under the
@@ -8,17 +8,16 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
 Created on May 21, 2014
 
 @author: <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
-'''
+"""
 from xml.dom.minidom import Element
 import ipaddr
 import xml.dom.minidom as md
 import copy
 
-KEY_NOT_FOUND = '<KEY_NOT_FOUND>'  # KeyNotFound for dictDiff
+KEY_NOT_FOUND = "<KEY_NOT_FOUND>"  # KeyNotFound for dictDiff
 
 
-class XMLtoDictParserTools():
-
+class XMLtoDictParserTools:
     @staticmethod
     def parseTreeToDict(node, returnedDict=None, ignoreList=[]):
         """
@@ -32,7 +31,7 @@ class XMLtoDictParserTools():
         @return: dict representation for the input DOM Element
         """
         returnedDict = {} if returnedDict is None else returnedDict
-        if (node.nodeType == Element.ELEMENT_NODE):
+        if node.nodeType == Element.ELEMENT_NODE:
             nodeKey = node.localName
             if nodeKey not in ignoreList:
                 if node.childNodes is not None:
@@ -40,12 +39,16 @@ class XMLtoDictParserTools():
                     for child in node.childNodes:
                         if child.nodeType == Element.TEXT_NODE:
                             nodeValue = child.nodeValue
-                            if (len(nodeValue.strip(' \t\n\r'))) > 0:
-                                XMLtoDictParserTools.addDictValue(returnedDict, nodeKey, nodeValue)
+                            if (len(nodeValue.strip(" \t\n\r"))) > 0:
+                                XMLtoDictParserTools.addDictValue(
+                                    returnedDict, nodeKey, nodeValue
+                                )
                                 nodeKey = None
                                 break
                         elif child.nodeType == Element.ELEMENT_NODE:
-                            childDict = XMLtoDictParserTools.parseTreeToDict(child, childDict, ignoreList)
+                            childDict = XMLtoDictParserTools.parseTreeToDict(
+                                child, childDict, ignoreList
+                            )
 
                     XMLtoDictParserTools.addDictValue(returnedDict, nodeKey, childDict)
 
@@ -53,11 +56,10 @@ class XMLtoDictParserTools():
 
     @staticmethod
     def addDictValue(m_dict, key, value):
-
         def _allign_address(value):
             """unifies output"""
             n = ipaddr.IPNetwork(value)
-            return '{0}/{1}'.format(n.network.exploded, n.prefixlen)
+            return "{0}/{1}".format(n.network.exploded, n.prefixlen)
 
         def _convert_numbers(value):
             if value.startswith("0x"):
@@ -65,29 +67,41 @@ class XMLtoDictParserTools():
             return str(int(value))
 
         if key is not None:
-            if (isinstance(value, str)):
+            if isinstance(value, str):
                 # we need to predict possible differences
                 # for same value in upper or lower case
                 value = value.lower()
             if key not in m_dict:
                 # lets add mask for ips withot mask
-                if key in ['ipv4-destination', 'ipv4-source', 'ipv6-destination', 'ipv6-source', 'ipv6-nd-target']:
+                if key in [
+                    "ipv4-destination",
+                    "ipv4-source",
+                    "ipv6-destination",
+                    "ipv6-source",
+                    "ipv6-nd-target",
+                ]:
                     nvalue = _allign_address(value)
                     m_dict[key] = nvalue
-                elif key in ['tunnel-mask', 'type', 'metadata-mask', 'out_port', 'out_group']:
+                elif key in [
+                    "tunnel-mask",
+                    "type",
+                    "metadata-mask",
+                    "out_port",
+                    "out_group",
+                ]:
                     nvalue = _convert_numbers(value)
                     m_dict[key] = nvalue
                 else:
                     m_dict[key] = value
             else:
                 exist_value = m_dict.get(key)
-                if (type(exist_value) is dict):
+                if type(exist_value) is dict:
                     list_values = [exist_value, value]
                     key_for_sort = XMLtoDictParserTools.searchKey(exist_value)
                     if key_for_sort is not None:
                         list_values = sorted(list_values, key=lambda k: k[key_for_sort])
                     m_dict[key] = list_values
-                elif (isinstance(exist_value, list)):
+                elif isinstance(exist_value, list):
                     exist_value.append(value)
                     list_values = exist_value
                     key_for_sort = XMLtoDictParserTools.searchKey(value)
@@ -106,7 +120,7 @@ class XMLtoDictParserTools():
         @param dictionary: dictionary with data
         @return: the array order key
         """
-        subKeyStr = ['-id', 'order']
+        subKeyStr = ["-id", "order"]
         for substr in subKeyStr:
             for key in dictionary:
                 if key == substr:
@@ -133,7 +147,7 @@ class XMLtoDictParserTools():
                 # missing key in responded dict
                 diff[key] = (key, KEY_NOT_FOUND)
             # check values of the dictionaries
-            elif (original_dict[key] != responded_dict[key]):
+            elif original_dict[key] != responded_dict[key]:
                 # values are not the same #
 
                 orig_dict_val = original_dict[key]
@@ -141,26 +155,33 @@ class XMLtoDictParserTools():
 
                 # check value is instance of dictionary
                 if isinstance(orig_dict_val, dict) and isinstance(resp_dict_val, dict):
-                    sub_dif = XMLtoDictParserTools.getDifferenceDict(orig_dict_val, resp_dict_val)
+                    sub_dif = XMLtoDictParserTools.getDifferenceDict(
+                        orig_dict_val, resp_dict_val
+                    )
                     if sub_dif:
                         diff[key] = sub_dif
 
                 # check value is instance of list
                 # TODO - > change a basic comparator to compare by id or order
-                elif isinstance(orig_dict_val, list) and isinstance(resp_dict_val, list):
+                elif isinstance(orig_dict_val, list) and isinstance(
+                    resp_dict_val, list
+                ):
                     sub_list_diff = {}
                     # the list lengths
                     orig_i, resp_i = len(orig_dict_val), len(resp_dict_val)
                     # define a max iteration length (less from both)
                     min_index = orig_i if orig_i < resp_i else resp_i
                     for index in range(0, min_index, 1):
-                        if (orig_dict_val[index] != resp_dict_val[index]):
-                            sub_list_diff[index] = (orig_dict_val[index], resp_dict_val[index])
-                    if (orig_i > min_index):
+                        if orig_dict_val[index] != resp_dict_val[index]:
+                            sub_list_diff[index] = (
+                                orig_dict_val[index],
+                                resp_dict_val[index],
+                            )
+                    if orig_i > min_index:
                         # original is longer as responded dict
                         for index in range(min_index, orig_i, 1):
                             sub_list_diff[index] = (orig_dict_val[index], None)
-                    elif (resp_i > min_index):
+                    elif resp_i > min_index:
                         # responded dict is longer as original
                         for index in range(min_index, resp_i, 1):
                             sub_list_diff[index] = (None, resp_dict_val[index])
@@ -177,40 +198,117 @@ class XMLtoDictParserTools():
         return diff
 
 
-IGNORED_TAGS_FOR_OPERATIONAL_COMPARISON = ['id', 'flow-name', 'barrier', 'cookie_mask', 'installHw', 'flags',
-                                           'strict', 'byte-count', 'duration', 'packet-count', 'in-port',
-                                           'vlan-id-present', 'out_group', 'out_port', 'hard-timeout', 'idle-timeout',
-                                           'flow-statistics', 'cookie', 'clear-actions',
-                                           'ipv4-source-address-no-mask', 'ipv4-source-arbitrary-bitmask',
-                                           'ipv4-destination-address-no-mask', 'ipv4-destination-arbitrary-bitmask',
-                                           'ipv6-source-address-no-mask', 'ipv6-source-arbitrary-bitmask',
-                                           'ipv6-destination-address-no-mask', 'ipv6-destination-arbitrary-bitmask']  # noqa
-
-IGNORED_PATHS_FOR_OC = [(['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'controller-action'], True),  # noqa
-                        (['flow', 'instructions', 'instruction', 'clear-actions', 'action'], False),
-                        (['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'push-vlan-action', 'vlan-id'], False),  # noqa
-                        (['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'drop-action'], True),
-                        (['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'flood-action'], True),
-                        ]
-
-TAGS_TO_ADD_FOR_OC = [(['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'output-action'], 'max-length', '0'),  # noqa
-                      ]
-
-
-TAGS_TO_MODIFY_FOR_OC = [(['flow', 'match', 'metadata'], 'metadata', 'metadata-mask'),
-                         (['flow', 'match', 'tunnel'], 'tunnel-id', 'tunnel-mask'),
-                         ]
+IGNORED_TAGS_FOR_OPERATIONAL_COMPARISON = [
+    "id",
+    "flow-name",
+    "barrier",
+    "cookie_mask",
+    "installHw",
+    "flags",
+    "strict",
+    "byte-count",
+    "duration",
+    "packet-count",
+    "in-port",
+    "vlan-id-present",
+    "out_group",
+    "out_port",
+    "hard-timeout",
+    "idle-timeout",
+    "flow-statistics",
+    "cookie",
+    "clear-actions",
+    "ipv4-source-address-no-mask",
+    "ipv4-source-arbitrary-bitmask",
+    "ipv4-destination-address-no-mask",
+    "ipv4-destination-arbitrary-bitmask",
+    "ipv6-source-address-no-mask",
+    "ipv6-source-arbitrary-bitmask",
+    "ipv6-destination-address-no-mask",
+    "ipv6-destination-arbitrary-bitmask",
+]  # noqa
+
+IGNORED_PATHS_FOR_OC = [
+    (
+        [
+            "flow",
+            "instructions",
+            "instruction",
+            "apply-actions",
+            "action",
+            "controller-action",
+        ],
+        True,
+    ),  # noqa
+    (["flow", "instructions", "instruction", "clear-actions", "action"], False),
+    (
+        [
+            "flow",
+            "instructions",
+            "instruction",
+            "apply-actions",
+            "action",
+            "push-vlan-action",
+            "vlan-id",
+        ],
+        False,
+    ),  # noqa
+    (
+        [
+            "flow",
+            "instructions",
+            "instruction",
+            "apply-actions",
+            "action",
+            "drop-action",
+        ],
+        True,
+    ),
+    (
+        [
+            "flow",
+            "instructions",
+            "instruction",
+            "apply-actions",
+            "action",
+            "flood-action",
+        ],
+        True,
+    ),
+]
+
+TAGS_TO_ADD_FOR_OC = [
+    (
+        [
+            "flow",
+            "instructions",
+            "instruction",
+            "apply-actions",
+            "action",
+            "output-action",
+        ],
+        "max-length",
+        "0",
+    )  # noqa
+]
+
+
+TAGS_TO_MODIFY_FOR_OC = [
+    (["flow", "match", "metadata"], "metadata", "metadata-mask"),
+    (["flow", "match", "tunnel"], "tunnel-id", "tunnel-mask"),
+]
 
 
 class XmlComparator:
-
     def is_flow_configured(self, requested_flow, configured_flows):
 
         orig_tree = md.parseString(requested_flow)
         xml_resp_stream = configured_flows
         xml_resp_tree = md.parseString(xml_resp_stream)
-        nodeListOperFlows = xml_resp_tree.getElementsByTagNameNS("*", 'flow')
-        origDict = XMLtoDictParserTools.parseTreeToDict(orig_tree._get_documentElement())
+        nodeListOperFlows = xml_resp_tree.getElementsByTagNameNS("*", "flow")
+        origDict = XMLtoDictParserTools.parseTreeToDict(
+            orig_tree._get_documentElement()
+        )
 
         reportDict = {}
         index = 0
@@ -219,11 +317,15 @@ class XmlComparator:
             XMLtoDictParserTools.addDictValue(reportDict, index, nodeDict)
             index += 1
             if nodeDict == origDict:
-                return True, ''
-            if nodeDict['flow']['priority'] == origDict['flow']['priority']:
-                return False, 'Flow found with diferences {0}'.format(
-                    XMLtoDictParserTools.getDifferenceDict(nodeDict, origDict))
-        return False, ''
+                return True, ""
+            if nodeDict["flow"]["priority"] == origDict["flow"]["priority"]:
+                return (
+                    False,
+                    "Flow found with diferences {0}".format(
+                        XMLtoDictParserTools.getDifferenceDict(nodeDict, origDict)
+                    ),
+                )
+        return False, ""
 
     def is_flow_operational2(self, requested_flow, oper_resp, check_id=False):
         def _rem_unimplemented_tags(tagpath, recurs, tdict):
@@ -239,20 +341,25 @@ class XmlComparator:
             # when to delete
             if len(tagpath) == 1 and tagpath[0] in tdict:
                 del tdict[tagpath[0]]
-            if len(tagpath) > 1 and recurs is True and tagpath[0] in tdict and tdict[tagpath[0]] == {}:
+            if (
+                len(tagpath) > 1
+                and recurs is True
+                and tagpath[0] in tdict
+                and tdict[tagpath[0]] == {}
+            ):
                 del tdict[tagpath[0]]
-            if list(tdict.keys()) == ['order']:
-                del tdict['order']
+            if list(tdict.keys()) == ["order"]:
+                del tdict["order"]
 
         def _add_tags(tagpath, newtag, value, tdict):
-            '''if whole tagpath exists and the tag is not present, it is added with given value'''
+            """if whole tagpath exists and the tag is not present, it is added with given value"""
             if len(tagpath) > 0 and tagpath[0] in tdict:
                 _add_tags(tagpath[1:], newtag, value, tdict[tagpath[0]])
             elif len(tagpath) == 0 and newtag not in tdict:
                 tdict[newtag] = value
 
         def _to_be_modified_tags(tagpath, tag, related_tag, tdict):
-            '''if whole tagpath exists and the tag is not present, it is added with given value'''
+            """if whole tagpath exists and the tag is not present, it is added with given value"""
             if len(tagpath) > 0 and tagpath[0] in tdict:
                 _to_be_modified_tags(tagpath[1:], tag, related_tag, tdict[tagpath[0]])
             elif len(tagpath) == 0 and tag in tdict and related_tag in tdict:
@@ -260,27 +367,27 @@ class XmlComparator:
 
         IGNORED_TAGS_LIST = list(IGNORED_TAGS_FOR_OPERATIONAL_COMPARISON)
         if check_id:
-            IGNORED_TAGS_LIST.remove('id')
+            IGNORED_TAGS_LIST.remove("id")
         orig_tree = md.parseString(requested_flow)
         xml_resp_stream = oper_resp
         xml_resp_tree = md.parseString(xml_resp_stream)
-        nodeListOperFlows = xml_resp_tree.getElementsByTagNameNS("*", 'flow')
+        nodeListOperFlows = xml_resp_tree.getElementsByTagNameNS("*", "flow")
         origDict = XMLtoDictParserTools.parseTreeToDict(
-            orig_tree._get_documentElement(),
-            ignoreList=IGNORED_TAGS_LIST)
+            orig_tree._get_documentElement(), ignoreList=IGNORED_TAGS_LIST
+        )
 
         # origDict['flow-statistics'] = origDict.pop( 'flow' )
         reportDict = {}
         index = 0
         for node in nodeListOperFlows:
             nodeDict = XMLtoDictParserTools.parseTreeToDict(
-                node,
-                ignoreList=IGNORED_TAGS_LIST)
+                node, ignoreList=IGNORED_TAGS_LIST
+            )
             XMLtoDictParserTools.addDictValue(reportDict, index, nodeDict)
             index += 1
             if nodeDict == origDict:
-                return True, ''
-            if nodeDict['flow']['priority'] == origDict['flow']['priority']:
+                return True, ""
+            if nodeDict["flow"]["priority"] == origDict["flow"]["priority"]:
                 for p in IGNORED_PATHS_FOR_OC:
                     td = copy.copy(origDict)
                     _rem_unimplemented_tags(p[0], p[1], td)
@@ -290,37 +397,43 @@ class XmlComparator:
                         _to_be_modified_tags(p, t, rt, td)
 
                     if nodeDict == td:
-                        return True, ''
+                        return True, ""
                 if nodeDict == origDict:
-                    return True, ''
-                return False, 'Flow found with diferences {0}'.format(
-                    XMLtoDictParserTools.getDifferenceDict(nodeDict, origDict))
-        return False, ''
+                    return True, ""
+                return (
+                    False,
+                    "Flow found with diferences {0}".format(
+                        XMLtoDictParserTools.getDifferenceDict(nodeDict, origDict)
+                    ),
+                )
+        return False, ""
 
     def get_data_for_flow_put_update(self, xml):
         # action only for yet
         xml_dom_input = md.parseString(xml)
-        actionList = xml_dom_input.getElementsByTagName('action')
+        actionList = xml_dom_input.getElementsByTagName("action")
         if actionList is not None and len(actionList) > 0:
             action = actionList[0]
             for child in action.childNodes:
                 if child.nodeType == Element.ELEMENT_NODE:
-                    nodeKey = (child.localName)
-                    if nodeKey != 'order':
-                        if nodeKey != 'drop-action':
-                            new_act = child.ownerDocument.createElement('drop-action')
+                    nodeKey = child.localName
+                    if nodeKey != "order":
+                        if nodeKey != "drop-action":
+                            new_act = child.ownerDocument.createElement("drop-action")
                         else:
-                            new_act = child.ownerDocument.createElement('output-action')
-                            onc = child.ownerDocument.createElement('output-node-connector')
-                            onc_content = child.ownerDocument.createTextNode('TABLE')
+                            new_act = child.ownerDocument.createElement("output-action")
+                            onc = child.ownerDocument.createElement(
+                                "output-node-connector"
+                            )
+                            onc_content = child.ownerDocument.createTextNode("TABLE")
                             onc.appendChild(onc_content)
                             new_act.appendChild(onc)
-                            ml = child.ownerDocument.createElement('max-length')
-                            ml_content = child.ownerDocument.createTextNode('60')
+                            ml = child.ownerDocument.createElement("max-length")
+                            ml_content = child.ownerDocument.createTextNode("60")
                             ml.appendChild(ml_content)
                             new_act.appendChild(ml)
                         child.parentNode.replaceChild(new_act, child)
-        return xml_dom_input.toxml(encoding='utf-8')
+        return xml_dom_input.toxml(encoding="utf-8")
 
     def get_flow_content(self, tid=1, fid=1, priority=1):
         """Returns an xml flow content identified by given details.
@@ -331,7 +444,7 @@ class XmlComparator:
             :param priority: flow priority
         """
 
-        flow_template = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+        flow_template = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <flow xmlns="urn:opendaylight:flow:inventory">
     <strict>false</strict>
     <instructions>
@@ -361,7 +474,13 @@ class XmlComparator:
     <flow-name>%s</flow-name>
     <priority>%s</priority>
     <barrier>false</barrier>
-</flow>'''
-
-        flow_data = flow_template % (tid, fid, fid, 'TestFlow-{0}'.format(fid), priority)
+</flow>"""
+
+        flow_data = flow_template % (
+            tid,
+            fid,
+            fid,
+            "TestFlow-{0}".format(fid),
+            priority,
+        )
         return flow_data