diff options
6 files changed, 64 insertions, 95 deletions
diff --git a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py index 5658eea146..1e0883db27 100644 --- a/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py +++ b/resources/libraries/python/honeycomb/HcAPIKwInterfaces.py @@ -1313,43 +1313,72 @@ class InterfaceKeywords(object): node, super_interface, path, None) @staticmethod - def compare_data_structures(data, ref, ignore=(), list_order=True): - """Checks if data obtained from UUT is as expected. + def compare_data_structures(data, ref, _path=''): + """Checks if data obtained from UUT is as expected. If it is not, + proceeds down the list/dictionary tree and finds the point of mismatch. :param data: Data to be checked. :param ref: Referential data used for comparison. - :param ignore: Dictionary keys to be ignored. - :param list_order: Whether to consider the order of list items\ - in comparison. + :param _path: Used in recursive calls, stores the path taken down + the JSON tree. :type data: dict :type ref: dict - :type ignore: iterable - :type list_order: bool + :type _path: str - :raises HoneycombError: If a parameter from referential data is not - present in operational data or if it has different value. + :raises HoneycombError: If the data structures do not match in some way, + or if they are not in deserialized JSON format. """ - errors = "" - - for key, item in ref.items(): - if key in ignore: - continue - try: - if data[key] != item: - if not list_order and sorted(data[key]) == sorted(item): - pass + if data == ref: + return True + + elif isinstance(data, dict) and isinstance(ref, dict): + for key in ref: + if key not in data: + raise HoneycombError( + "Key {key} is not present in path {path}. Keys in path:" + "{data_keys}".format( + key=key, + path=_path, + data_keys=data.keys())) + + if data[key] != ref[key]: + if isinstance(data[key], list) \ + or isinstance(data[key], dict): + InterfaceKeywords.compare_data_structures( + data[key], ref[key], + _path + '[{0}]'.format(key)) else: - errors += ("\nThe value of parameter '{0}' is " - "incorrect. It should be " - "'{1}' but it is '{2}'". - format(key, item, data[key])) - except KeyError: - errors += ("\nThe parameter '{0}' is not present in " - "operational data".format(key)) + raise HoneycombError( + "Data mismatch, key {key} in path {path} has value" + " {data}, but should be {ref}".format( + key=key, + path=_path, + data=data[key], + ref=ref[key])) + + elif isinstance(data, list) and isinstance(ref, list): + for item in ref: + if item not in data: + if isinstance(item, dict): + InterfaceKeywords.compare_data_structures( + data[0], item, + _path + '[{0}]'.format(ref.index(item))) + else: + raise HoneycombError( + "Data mismatch, list item {index} in path {path}" + " has value {data}, but should be {ref}".format( + index=ref.index(item), + path=_path, + data=data[0], + ref=item)) - if errors: - raise HoneycombError(errors) + else: + raise HoneycombError( + "Unexpected data type {data_type}, reference type is" + " {ref_type}. Must be list or dictionary.".format( + data_type=type(data), + ref_type=type(ref))) @staticmethod def compare_interface_lists(list1, list2): diff --git a/resources/libraries/python/honeycomb/HoneycombUtil.py b/resources/libraries/python/honeycomb/HoneycombUtil.py index 747c9dae8e..c290af9a6e 100644 --- a/resources/libraries/python/honeycomb/HoneycombUtil.py +++ b/resources/libraries/python/honeycomb/HoneycombUtil.py @@ -27,8 +27,7 @@ from enum import Enum, unique from robot.api import logger -from resources.libraries.python.ssh import SSH -from resources.libraries.python.HTTPRequest import HTTPRequest, HTTPCodes +from resources.libraries.python.HTTPRequest import HTTPRequest from resources.libraries.python.constants import Constants as Const @@ -302,10 +301,7 @@ class HoneycombUtil(object): base_path = HoneycombUtil.read_path_from_url_file(url_file) path = base_path + path status_code, resp = HTTPRequest.get(node, path) - response = loads(resp) - if status_code != HTTPCodes.OK: - HoneycombUtil.read_log_tail(node) - return status_code, response + return status_code, loads(resp) @staticmethod def put_honeycomb_data(node, url_file, data, path="", @@ -343,13 +339,9 @@ class HoneycombUtil(object): base_path = HoneycombUtil.read_path_from_url_file(url_file) path = base_path + path logger.trace(path) - (status_code, response) = HTTPRequest.put( + return HTTPRequest.put( node=node, path=path, headers=header, payload=data) - if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): - HoneycombUtil.read_log_tail(node) - return status_code, response - @staticmethod def post_honeycomb_data(node, url_file, data=None, data_representation=DataRepresentation.JSON, @@ -383,13 +375,9 @@ class HoneycombUtil(object): data = dumps(data) path = HoneycombUtil.read_path_from_url_file(url_file) - (status_code, response) = HTTPRequest.post( + return HTTPRequest.post( node=node, path=path, headers=header, payload=data, timeout=timeout) - if status_code not in (HTTPCodes.OK, HTTPCodes.ACCEPTED): - HoneycombUtil.read_log_tail(node) - return status_code, response - @staticmethod def delete_honeycomb_data(node, url_file, path=""): """Delete data from Honeycomb according to given URL. @@ -407,48 +395,4 @@ class HoneycombUtil(object): base_path = HoneycombUtil.read_path_from_url_file(url_file) path = base_path + path - (status_code, response) = HTTPRequest.delete(node, path) - - if status_code != HTTPCodes.OK: - HoneycombUtil.read_log_tail(node) - return status_code, response - - @staticmethod - def read_log_tail(node, lines=120): - """Read the last N lines of the Honeycomb log file and print them - to robot log. - - :param node: Honeycomb node. - :param lines: Number of lines to read. - :type node: dict - :type lines: int - :returns: Last N log lines. - :rtype: str - """ - - logger.trace( - "HTTP request failed, " - "obtaining last {0} lines of Honeycomb log...".format(lines)) - - ssh = SSH() - ssh.connect(node) - cmd = "tail -n {0} /var/log/honeycomb/honeycomb.log".format(lines) - # ssh also logs the reply on trace level - (_, stdout, _) = ssh.exec_command(cmd, timeout=30) - - return stdout - - @staticmethod - def archive_honeycomb_log(node): - """Copy honeycomb log file from DUT node to VIRL for archiving. - - :param node: Honeycomb node. - :type node: dict - """ - - ssh = SSH() - ssh.connect(node) - - cmd = "cp /var/log/honeycomb/honeycomb.log /scratch/" - - ssh.exec_command_sudo(cmd) + return HTTPRequest.delete(node, path) diff --git a/resources/libraries/robot/honeycomb/access_control_lists.robot b/resources/libraries/robot/honeycomb/access_control_lists.robot index a9ea7dffe6..d24da5bd96 100644 --- a/resources/libraries/robot/honeycomb/access_control_lists.robot +++ b/resources/libraries/robot/honeycomb/access_control_lists.robot @@ -12,7 +12,6 @@ # limitations under the License. *** Variables *** #TODO: update based on resolution of bug https://jira.fd.io/browse/HONEYCOMB-119 -| @{hc_table_ignore}= | memory_size *** Settings *** | Library | resources.libraries.python.Classify @@ -124,7 +123,7 @@ | | ... | \| ${settings} \| | | [Arguments] | ${node} | ${settings} | | ${data}= | Get classify table oper data | ${node} | ${settings['name']} -| | Compare data structures | ${data} | ${settings} | ignore=${hc_table_ignore} +| | Compare data structures | ${data} | ${settings} | ACL table from VAT should be | | [Documentation] | Retrieves ACL table information from VAT\ diff --git a/resources/libraries/robot/honeycomb/interfaces.robot b/resources/libraries/robot/honeycomb/interfaces.robot index 027b7d74a3..765aaef7c0 100644 --- a/resources/libraries/robot/honeycomb/interfaces.robot +++ b/resources/libraries/robot/honeycomb/interfaces.robot @@ -235,7 +235,7 @@ | | ${api_data}= | interfaceAPI.Get interface oper data | ${node} | ${interface} | | ${data_neighbors}= | Set Variable | ${api_data['ietf-ip:ipv4']['neighbor']} | | Compare data structures -| | ... | ${data_neighbors} | ${neighbors} | list_order=${False} +| | ... | ${data_neighbors} | ${neighbors} | | Should be equal | ${neighbor['fib_address']} | | ... | ${api_data['ietf-ip:ipv4']['neighbor'][0]['ip']} | | Should be equal | ${neighbor['fib_mac']} diff --git a/resources/libraries/robot/honeycomb/sub_interface.robot b/resources/libraries/robot/honeycomb/sub_interface.robot index e9b8aeb008..4a9f5c403b 100644 --- a/resources/libraries/robot/honeycomb/sub_interface.robot +++ b/resources/libraries/robot/honeycomb/sub_interface.robot @@ -68,7 +68,6 @@ | | ${api_data}= | interfaceAPI.Get sub interface oper data | | ... | ${node} | ${super_interface} | ${identifier} | | interfaceAPI.Compare Data Structures | ${api_data} | ${sub_if_settings} -| | ... | list_order=${False} | Sub-interface configuration from Honeycomb should be empty | | [Documentation] | Retrieves sub-interface configuration through Honeycomb \ @@ -391,7 +390,7 @@ | | ${api_data}= | interfaceAPI.Get tag rewrite oper data | | ... | ${node} | ${super_if} | ${identifier} | | interfaceAPI.Compare Data Structures -| | ... | ${api_data} | ${settings} | list_order=${False} +| | ... | ${api_data} | ${settings} | Rewrite tag from VAT should be | | [Documentation] | Retrieves sub-interface configuration through VAT and\ diff --git a/resources/test_data/honeycomb/acl.py b/resources/test_data/honeycomb/acl.py index 227330c2a9..ee7f9525b8 100644 --- a/resources/test_data/honeycomb/acl.py +++ b/resources/test_data/honeycomb/acl.py @@ -17,7 +17,6 @@ hc_acl_table = { "name": "acl_table_test", "nbuckets": 1, - "memory_size": 100000, "skip_n_vectors": 0, "miss_next": "permit", "mask": "00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:00:00:00:00" @@ -26,7 +25,6 @@ hc_acl_table = { hc_acl_table2 = { "name": "acl_table_test2", "nbuckets": 2, - "memory_size": 100000, "skip_n_vectors": 1, "next_table": "acl_table_test", "miss_next": "deny", |