mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 19:10:35 +00:00
lib: improve json_cmp
Allow json_cmp to compare JSON values which begin with a list instead of a dictionary. Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
parent
5a2f1e6fbe
commit
a82e5f9a7f
@ -89,6 +89,47 @@ def json_diff(d1, d2):
|
|||||||
dstr2 = json.dumps(d2, **json_format_opts)
|
dstr2 = json.dumps(d2, **json_format_opts)
|
||||||
return difflines(dstr2, dstr1, title1='Expected value', title2='Current value', n=0)
|
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):
|
def json_cmp(d1, d2):
|
||||||
"""
|
"""
|
||||||
JSON compare function. Receives two parameters:
|
JSON compare function. Receives two parameters:
|
||||||
@ -102,11 +143,20 @@ def json_cmp(d1, d2):
|
|||||||
"""
|
"""
|
||||||
squeue = [(d1, d2, 'json')]
|
squeue = [(d1, d2, 'json')]
|
||||||
result = json_cmp_result()
|
result = json_cmp_result()
|
||||||
|
|
||||||
for s in squeue:
|
for s in squeue:
|
||||||
nd1, nd2, parent = s
|
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.
|
# 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])
|
s2_req = set([key for key in nd2 if nd2[key] is not None])
|
||||||
diff = s2_req - s1
|
diff = s2_req - s1
|
||||||
if diff != set({}):
|
if diff != set({}):
|
||||||
@ -119,6 +169,7 @@ def json_cmp(d1, d2):
|
|||||||
result.add_error('"{}" should not exist in {} (have {}):\n{}'.format(
|
result.add_error('"{}" should not exist in {} (have {}):\n{}'.format(
|
||||||
key, parent, str(s1), json_diff(nd1[key], nd2[key])))
|
key, parent, str(s1), json_diff(nd1[key], nd2[key])))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# If nd1 key is a dict, we have to recurse in it later.
|
# If nd1 key is a dict, we have to recurse in it later.
|
||||||
if isinstance(nd2[key], type({})):
|
if isinstance(nd2[key], type({})):
|
||||||
if not isinstance(nd1[key], type({})):
|
if not isinstance(nd1[key], type({})):
|
||||||
@ -130,42 +181,10 @@ def json_cmp(d1, d2):
|
|||||||
nparent = '{}["{}"]'.format(parent, key)
|
nparent = '{}["{}"]'.format(parent, key)
|
||||||
squeue.append((nd1[key], nd2[key], nparent))
|
squeue.append((nd1[key], nd2[key], nparent))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check list items
|
# Check list items
|
||||||
if isinstance(nd2[key], type([])):
|
if isinstance(nd2[key], type([])):
|
||||||
if not isinstance(nd1[key], type([])):
|
_json_list_cmp(nd1[key], nd2[key], parent, result)
|
||||||
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])))
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Compare JSON values
|
# Compare JSON values
|
||||||
@ -180,6 +199,7 @@ def json_cmp(d1, d2):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def run_and_expect(func, what, count=20, wait=3):
|
def run_and_expect(func, what, count=20, wait=3):
|
||||||
"""
|
"""
|
||||||
Run `func` and compare the result with `what`. Do it for `count` times
|
Run `func` and compare the result with `what`. Do it for `count` times
|
||||||
|
Loading…
Reference in New Issue
Block a user