From 53ee2e3e024b136e5e7ab8fe6ad7c588ad7b9536 Mon Sep 17 00:00:00 2001 From: Danny Allen Date: Tue, 14 Apr 2020 09:13:07 -0700 Subject: [PATCH] [dvslib] Improve support for assert logging (#1258) Signed-off-by: Danny Allen --- tests/dvslib/dvs_common.py | 15 +++-- tests/dvslib/dvs_database.py | 111 +++++++++++++++++++++++++++++++---- 2 files changed, 109 insertions(+), 17 deletions(-) diff --git a/tests/dvslib/dvs_common.py b/tests/dvslib/dvs_common.py index fe2e77d2b724..ce7db9859666 100644 --- a/tests/dvslib/dvs_common.py +++ b/tests/dvslib/dvs_common.py @@ -37,8 +37,11 @@ def wait_for_result(polling_function, polling_config): not, as well as some return value. Returns: - Any: The output of the polling function, if it is succesful, - None otherwise. + (bool, Any): If the polling function succeeds, then this method + will return True and the output of the polling function. If it + does not succeed within the provided timeout, it will return False + and whatever the output of the polling function was on the final + attempt. """ if polling_config.polling_interval == 0: iterations = 1 @@ -46,14 +49,14 @@ def wait_for_result(polling_function, polling_config): iterations = int(polling_config.timeout // polling_config.polling_interval) + 1 for _ in range(iterations): - (status, result) = polling_function() + status, result = polling_function() if status: - return result + return (True, result) time.sleep(polling_config.polling_interval) if polling_config.strict: - assert False + assert False, "Operation timed out after {}s".format(polling_config.timeout) - return None + return (False, result) diff --git a/tests/dvslib/dvs_database.py b/tests/dvslib/dvs_database.py index d22375139ec0..23392fe175be 100644 --- a/tests/dvslib/dvs_database.py +++ b/tests/dvslib/dvs_database.py @@ -119,7 +119,14 @@ def _access_function(): fv_pairs = self.get_entry(table_name, key) return (bool(fv_pairs), fv_pairs) - return wait_for_result(_access_function, polling_config) + status, result = wait_for_result(_access_function, + self._disable_strict_polling(polling_config)) + + if not status: + assert not polling_config.strict, \ + "Entry not found: key=\"{}\", table=\"{}\"".format(key, table_name) + + return result def wait_for_field_match(self, table_name, @@ -131,9 +138,6 @@ def wait_for_field_match(self, at `key` in the specified table. This method will wait for the fields to exist. - Note: - This method does not check for an exact match. - Args: table_name (str): The name of the table where the entry is stored. @@ -152,12 +156,57 @@ def _access_function(): fv_pairs = self.get_entry(table_name, key) return (all(fv_pairs.get(k) == v for k, v in expected_fields.items()), fv_pairs) - return wait_for_result(_access_function, polling_config) + status, result = wait_for_result(_access_function, + self._disable_strict_polling(polling_config)) + + if not status: + assert not polling_config.strict, \ + "Expected fields not found: expected={}, received={}, \ + key=\"{}\", table=\"{}\"".format(expected_fields, result, key, table_name) - def wait_for_empty_entry(self, + return result + + def wait_for_exact_match(self, table_name, key, + expected_entry, polling_config=DEFAULT_POLLING_CONFIG): + """ + Checks if the provided entry matches the entry stored at `key` + in the specified table. This method will wait for the exact entry + to exist. + + Args: + table_name (str): The name of the table where the entry is + stored. + key (str): The key that maps to the entry being checked. + expected_entry (dict): The entry we expect to see. + polling_config (PollingConfig): The parameters to use to poll + the db. + + Returns: + Dict[str, str]: The entry stored at `key`. If no entry is found, + then an empty Dict will be returned. + """ + + def _access_function(): + fv_pairs = self.get_entry(table_name, key) + return (fv_pairs == expected_entry, fv_pairs) + + status, result = wait_for_result(_access_function, + self._disable_strict_polling(polling_config)) + + if not status: + assert not polling_config.strict, \ + "Exact match not found: expected={}, received={}, \ + key=\"{}\", table=\"{}\"".format(expected_entry, result, key, table_name) + + return result + + def wait_for_deleted_entry(self, + table_name, + key, + polling_config=DEFAULT_POLLING_CONFIG): """ Checks if there is any entry stored at `key` in the specified table. This method will wait for the entry to be empty. @@ -169,14 +218,23 @@ def wait_for_empty_entry(self, the db. Returns: - bool: True if no entry exists at `key`, False otherwise. + Dict[str, str]: The entry stored at `key`. If no entry is found, + then an empty Dict will be returned. """ def _access_function(): fv_pairs = self.get_entry(table_name, key) return (not bool(fv_pairs), fv_pairs) - return wait_for_result(_access_function, polling_config) + status, result = wait_for_result(_access_function, + self._disable_strict_polling(polling_config)) + + if not status: + assert not polling_config.strict, \ + "Entry still exists: entry={}, key=\"{}\", table=\"{}\""\ + .format(result, key, table_name) + + return result def wait_for_n_keys(self, table_name, @@ -203,7 +261,15 @@ def _access_function(): keys = self.get_keys(table_name) return (len(keys) == num_keys, keys) - return wait_for_result(_access_function, polling_config) + status, result = wait_for_result(_access_function, + self._disable_strict_polling(polling_config)) + + if not status: + assert not polling_config.strict, \ + "Unexpected number of keys: expected={}, received={} ({}), table=\"{}\""\ + .format(num_keys, len(result), result, table_name) + + return result def wait_for_matching_keys(self, table_name, @@ -230,7 +296,15 @@ def _access_function(): keys = self.get_keys(table_name) return (all(key in keys for key in expected_keys), keys) - return wait_for_result(_access_function, polling_config) + status, result = wait_for_result(_access_function, + self._disable_strict_polling(polling_config)) + + if not status: + assert not polling_config.strict, \ + "Expected keys not found: expected={}, received={}, table=\"{}\""\ + .format(expected_keys, result, table_name) + + return result def wait_for_deleted_keys(self, table_name, @@ -257,4 +331,19 @@ def _access_function(): keys = self.get_keys(table_name) return (all(key not in keys for key in deleted_keys), keys) - return wait_for_result(_access_function, polling_config) + status, result = wait_for_result(_access_function, + self._disable_strict_polling(polling_config)) + + if not status: + assert not polling_config.strict, \ + "Unexpected keys found: expected={}, received={}, table=\"{}\""\ + .format(deleted_keys, result, table_name) + + return result + + @staticmethod + def _disable_strict_polling(polling_config): + disabled_config = PollingConfig(polling_interval=polling_config.polling_interval, + timeout=polling_config.timeout, + strict=False) + return disabled_config