]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: improve json_cmp
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Wed, 23 May 2018 19:39:05 +0000 (16:39 -0300)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 28 Nov 2018 01:22:14 +0000 (20:22 -0500)
Allow json_cmp to compare JSON values which begin with a list instead of
a dictionary.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
tests/topotests/lib/topotest.py

index 11e2a572193d45461a6a3aeca103870bbab5c8ee..7f66098fc746f11ace5782e6b792f07b7613e52c 100644 (file)
@@ -89,6 +89,47 @@ def json_diff(d1, d2):
     dstr2 = json.dumps(d2, **json_format_opts)
     return difflines(dstr2, dstr1, title1='Expected value', title2='Current value', n=0)
 
+
+def _json_list_cmp(list1, list2, parent, result):
+    "Handles list type entries."
+    # Check second list2 type
+    if not isinstance(list1, type([])) or not isinstance(list2, type([])):
+        result.add_error(
+            '{} has different type than expected '.format(parent) +
+            '(have {}, expected {}):\n{}'.format(
+                type(list1), type(list2), json_diff(list1, list2)))
+        return
+
+    # Check list size
+    if len(list2) > len(list1):
+        result.add_error(
+            '{} too few items '.format(parent) +
+            '(have {}, expected {}:\n {})'.format(
+                len(list1), len(list2),
+                json_diff(list1, list2)))
+        return
+
+    # List all unmatched items errors
+    unmatched = []
+    for expected in list2:
+        matched = False
+        for value in list1:
+            if json_cmp({'json': value}, {'json': expected}) is None:
+                matched = True
+                break
+
+        if matched:
+            break
+        if not matched:
+            unmatched.append(expected)
+
+    # If there are unmatched items, error out.
+    if unmatched:
+        result.add_error(
+            '{} value is different (\n{})'.format(
+                parent, json_diff(list1, list2)))
+
+
 def json_cmp(d1, d2):
     """
     JSON compare function. Receives two parameters:
@@ -102,11 +143,20 @@ def json_cmp(d1, d2):
     """
     squeue = [(d1, d2, 'json')]
     result = json_cmp_result()
+
     for s in squeue:
         nd1, nd2, parent = s
-        s1, s2 = set(nd1), set(nd2)
+
+        # Handle JSON beginning with lists.
+        if isinstance(nd1, type([])) or isinstance(nd2, type([])):
+            _json_list_cmp(nd1, nd2, parent, result)
+            if result.has_errors():
+                return result
+            else:
+                return None
 
         # Expect all required fields to exist.
+        s1, s2 = set(nd1), set(nd2)
         s2_req = set([key for key in nd2 if nd2[key] is not None])
         diff = s2_req - s1
         if diff != set({}):
@@ -119,6 +169,7 @@ def json_cmp(d1, d2):
                 result.add_error('"{}" should not exist in {} (have {}):\n{}'.format(
                     key, parent, str(s1), json_diff(nd1[key], nd2[key])))
                 continue
+
             # If nd1 key is a dict, we have to recurse in it later.
             if isinstance(nd2[key], type({})):
                 if not isinstance(nd1[key], type({})):
@@ -130,42 +181,10 @@ def json_cmp(d1, d2):
                 nparent = '{}["{}"]'.format(parent, key)
                 squeue.append((nd1[key], nd2[key], nparent))
                 continue
+
             # Check list items
             if isinstance(nd2[key], type([])):
-                if not isinstance(nd1[key], type([])):
-                    result.add_error(
-                        '{}["{}"] has different type than expected '.format(parent, key) +
-                        '(have {}, expected {}):\n{}'.format(
-                            type(nd1[key]), type(nd2[key]), json_diff(nd1[key], nd2[key])))
-                    continue
-                # Check list size
-                if len(nd2[key]) > len(nd1[key]):
-                    result.add_error(
-                        '{}["{}"] too few items '.format(parent, key) +
-                        '(have {}, expected {}:\n {})'.format(
-                            len(nd1[key]), len(nd2[key]),
-                            json_diff(nd1[key], nd2[key])))
-                    continue
-
-                # List all unmatched items errors
-                unmatched = []
-                for expected in nd2[key]:
-                    matched = False
-                    for value in nd1[key]:
-                        if json_cmp({'json': value}, {'json': expected}) is None:
-                            matched = True
-                            break
-
-                    if matched:
-                        break
-                    if not matched:
-                        unmatched.append(expected)
-
-                # If there are unmatched items, error out.
-                if unmatched:
-                    result.add_error(
-                        '{}["{}"] value is different (\n{})'.format(
-                            parent, key, json_diff(nd1[key], nd2[key])))
+                _json_list_cmp(nd1[key], nd2[key], parent, result)
                 continue
 
             # Compare JSON values
@@ -180,6 +199,7 @@ def json_cmp(d1, d2):
 
     return None
 
+
 def run_and_expect(func, what, count=20, wait=3):
     """
     Run `func` and compare the result with `what`. Do it for `count` times