Bug 5560: Fix bits ordering issue in BGP flowspec tests 96/37196/6
authorVratko Polak <vrpolak@cisco.com>
Fri, 8 Apr 2016 12:20:44 +0000 (14:20 +0200)
committerJamo Luhrsen <jluhrsen@redhat.com>
Mon, 11 Apr 2016 17:27:37 +0000 (17:27 +0000)
This includes change to norm.json.py Library to optionally
perform sorting withing string values if key is present in given list.

Also, ordering and syntax inside Verify Flowspec Data is improved.

Change-Id: I12d2493233d557772f8beec6e11743a4d6941c97
Signed-off-by: Vratko Polak <vrpolak@cisco.com>
csit/libraries/norm_json.py
csit/suites/bgpcep/bgpflowspec/010_bgp_flowspec.robot

index 7dde004504513020b8b1c284ffdbea499dfcaaa5..8a84fc27d3df5ca99d12a635c700c6f64f12f988 100644 (file)
@@ -114,13 +114,51 @@ def dumps_indented(obj, indent=1):
     return pretty_json + '\n'  # to avoid diff "no newline" warning line
 
 
-def normalize_json_text(text, strict=False, indent=1):  # pylint likes lowercase
+def sort_bits(obj, keys_with_bits=[]):
+    """
+    Rearrange string values of list bits names in alphabetical order.
+
+    This function looks at dict items with known keys.
+    If the value is string, space-separated names are sorted.
+    This function is recursive over dicts and lists.
+    Current implementation performs re-arranging in-place (to save memory),
+    so it is not required to store the return value.
+
+    The intended usage is for composite objects which contain
+    OrderedDict elements. The implementation makes sure that ordering
+    (dictated by keys) is preserved. Support for generic dicts is an added value.
+
+    Sadly, dict (at least in Python 2.7) does not have __updatevalue__(key) method
+    which would guarantee iteritems() is not affected when value is updated.
+    Current "obj[key] = value" implementation is safe for dict and OrderedDict,
+    but it may be not safe for other subclasses of dict.
+
+    TODO: Should this docstring include links to support dict and OrderedDict safety?
+    """
+    if isinstance(obj, dict):
+        for key, value in obj.iteritems():
+            # Unicode is not str and vice versa, isinstance has to check for both.
+            # Luckily, "in" recognizes equivalent strings in different encodings.
+            # Type "bytes" is added for Python 3 compatibility.
+            if key in keys_with_bits and isinstance(value, (unicode, str, bytes)):
+                obj[key] = " ".join(sorted(value.split(" ")))
+            else:
+                sort_bits(value, keys_with_bits)
+    # A string is not a list, so there is no risk of recursion over characters.
+    elif isinstance(obj, list):
+        for item in obj:
+            sort_bits(item, keys_with_bits)
+    return obj
+
+
+def normalize_json_text(text, strict=False, indent=1, keys_with_bits=[]):
     """
     Attempt to return sorted indented JSON string.
 
     If parse error happens:
     If strict is true, raise the exception.
     If strict is not true, return original text with error message.
+    If keys_with_bits is non-empty, run sort_bits on intermediate Python object.
     """
     try:
         object_decoded = loads_sorted(text)
@@ -129,5 +167,7 @@ def normalize_json_text(text, strict=False, indent=1):  # pylint likes lowercase
             raise err
         else:
             return str(err) + '\n' + text
+    if keys_with_bits:
+        sort_bits(object_decoded, keys_with_bits)
     pretty_json = dumps_indented(object_decoded, indent=indent)
     return pretty_json
index 6e9507d8ae23469139e3e8c93672a7dfbd714539..36c3c910b519d3aee8480d5436dee205d5cbf4ef 100644 (file)
@@ -115,11 +115,12 @@ Verify Empty Flowspec Data
 Verify Flowspec Data
     [Arguments]    ${exprspfile}
     [Documentation]    Verify expected response
-    ${rsp}=    RequestsLibrary.Get Request    session    ${FLOWSPEC_URL}
-    Log    ${rsp.content}
-    ${received_json}=    Normalize Json Text    ${rsp.content}
+    ${keys_with_bits}=    BuiltIn.Create_List    op
     ${expected_rsp}=    OperatingSystem.Get File    ${CURDIR}/../../../variables/bgpflowspec/${exprspfile}
-    ${expected_json}=    Normalize Json Text    ${expected_rsp}
-    Log    ${received_json}
-    Log    ${expected_json}
-    Should Be Equal    ${received_json}    ${expected_json}
+    ${expected_json}=    norm_json.Normalize Json Text    ${expected_rsp}    keys_with_bits=${keys_with_bits}
+    ${rsp}=    RequestsLibrary.Get Request    session    ${FLOWSPEC_URL}
+    BuiltIn.Log    ${rsp.content}
+    ${received_json}=    norm_json.Normalize Json Text    ${rsp.content}    keys_with_bits=${keys_with_bits}
+    BuiltIn.Log    ${received_json}
+    BuiltIn.Log    ${expected_json}
+    BuiltIn.Should Be Equal    ${received_json}    ${expected_json}