-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: add test utils for cleaner API output expected assertion
- Loading branch information
Mathias Brulatout
committed
Mar 18, 2024
1 parent
7ab04c2
commit d04249b
Showing
2 changed files
with
94 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
from tests.utils import find_recursive | ||
|
||
|
||
def test_find_recursive(): | ||
ret_value = [ | ||
{ | ||
"AccessorID": "accessorid", | ||
"CreateIndex": 1, | ||
"CreateTime": "timestamp", | ||
"Description": "description", | ||
"Hash": "hash", | ||
"Local": False, | ||
"ModifyIndex": 1, | ||
"Policies": [{"ID": "id", "Name": "name"}], | ||
"SecretID": "secretid", | ||
}, | ||
{ | ||
"AccessorID": "accessorid", | ||
"CreateIndex": 1, | ||
"CreateTime": "timestamp", | ||
"Description": "description", | ||
"Hash": "hash", | ||
"Local": False, | ||
"ModifyIndex": 1, | ||
"Policies": [{"ID": "id", "Name": "name"}], | ||
"SecretID": "secretid2", | ||
}, | ||
] | ||
|
||
wanted = { | ||
"AccessorID": "accessorid", | ||
"Description": "description", | ||
"Policies": [{"Name": "name"}], | ||
"SecretID": "secretid", | ||
} | ||
wanted2 = { | ||
"AccessorID": "accessorid", | ||
"SecretID": "secretid2", | ||
} | ||
unwanted = { | ||
"AccessorID": "accessorid", | ||
"Description": "description", | ||
"Policies": [{"Name": "name-ish"}], | ||
"SecretID": "secretid", | ||
} | ||
|
||
assert find_recursive(ret_value, wanted) | ||
assert find_recursive(ret_value, wanted2) | ||
assert find_recursive(ret_value, [wanted, wanted2]) | ||
assert find_recursive(wanted, wanted) | ||
assert not find_recursive(ret_value, unwanted) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from __future__ import annotations | ||
|
||
|
||
def find_recursive(list_or_single_dict: list[dict] | dict, wanted: list[dict] | dict) -> bool: | ||
""" | ||
Check if the 'wanted' item(s) sub-dictionary structure is/are present in any of the dictionaries in 'list_or_single_dict'. | ||
'list_or_single_dict' can be either a list of dictionaries or a single dictionary. | ||
""" | ||
|
||
def matches_subdict(haystack: dict, needle: dict) -> bool: | ||
""" | ||
Check if all key-value pairs in needle are present in haystack. | ||
This function recursively checks nested dictionaries and lists of dictionaries. | ||
""" | ||
for key, needle_value in needle.items(): | ||
if key not in haystack: | ||
return False | ||
|
||
haystack_value = haystack[key] | ||
|
||
if isinstance(needle_value, dict): | ||
if not isinstance(haystack_value, dict) or not matches_subdict(haystack_value, needle_value): | ||
return False | ||
elif isinstance(needle_value, list): | ||
if not all( | ||
any(matches_subdict(haystack_item, needle_item) for haystack_item in haystack_value) | ||
for needle_item in needle_value | ||
): | ||
return False | ||
else: | ||
if haystack_value != needle_value: | ||
return False | ||
|
||
return True | ||
|
||
# Turn both args into lists to handle single/multi lookup | ||
if isinstance(list_or_single_dict, dict): | ||
list_or_single_dict = [list_or_single_dict] | ||
|
||
if isinstance(wanted, dict): | ||
wanted = [wanted] | ||
|
||
return all(any(matches_subdict(item, single_wanted) for item in list_or_single_dict) for single_wanted in wanted) |