From f9d37879428b98bf5227592e906f6601b8f54140 Mon Sep 17 00:00:00 2001 From: Jean Do Date: Mon, 22 May 2023 09:49:46 -0400 Subject: [PATCH 1/3] handle exceptions which have no message --- src/seedsigner/controller.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/seedsigner/controller.py b/src/seedsigner/controller.py index 4976d6f74..94cc2f6f0 100644 --- a/src/seedsigner/controller.py +++ b/src/seedsigner/controller.py @@ -309,7 +309,10 @@ def handle_exception(self, e) -> Destination: # So we extract the Exception type and trim off any "foo.bar." namespacing: last_line = traceback.format_exc().splitlines()[-1] exception_type = last_line.split(":")[0].split(".")[-1] - exception_msg = last_line.split(":")[1] + if ":" in last_line: + exception_msg = last_line.split(":")[1] + else: + exception_msg = "" # Scan for the last debugging line that includes a line number reference line_info = None From acc8517faccb8f905006c74260d42ce18a48fab9 Mon Sep 17 00:00:00 2001 From: Jean Do Date: Tue, 6 Jun 2023 13:44:54 -0400 Subject: [PATCH 2/3] added test_handle_exception() to test_controller.py --- src/seedsigner/controller.py | 2 ++ tests/test_controller.py | 55 ++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/seedsigner/controller.py b/src/seedsigner/controller.py index 94cc2f6f0..8f68c2647 100644 --- a/src/seedsigner/controller.py +++ b/src/seedsigner/controller.py @@ -309,6 +309,8 @@ def handle_exception(self, e) -> Destination: # So we extract the Exception type and trim off any "foo.bar." namespacing: last_line = traceback.format_exc().splitlines()[-1] exception_type = last_line.split(":")[0].split(".")[-1] + + # Extract the error message, if there is one if ":" in last_line: exception_msg = last_line.split(":")[1] else: diff --git a/tests/test_controller.py b/tests/test_controller.py index bd8b2c18e..4dda4f98c 100644 --- a/tests/test_controller.py +++ b/tests/test_controller.py @@ -43,6 +43,61 @@ def test_singleton_get_instance_preserves_state(reset_controller): assert controller.unverified_address == "123abc" +def test_handle_exception(reset_controller): + """ Handle exceptions that get caught by the controller """ + + def process_exception_return_error(exception_type, error_msg=None): + try: + if error_msg: + raise exception_type(error_msg) + else: + raise exception_type() + except Exception as e: + destination = controller.handle_exception(e) + return destination.view_args["error"] + + def is_valid_error_structure(error, exception_type, exception_msg): + """ + Exceptions caught by the controller are forwarded to the + UnhandledExceptionView with view_args["error"] being a list + of three strings, ie: [exception_type, line_info, exception_msg] + """ + if len(error) != 3: + return False + + if error[0] not in str(exception_type): + return False + + if type(error[1]) != str: + return False + + if exception_msg: + if exception_msg not in error[2]: + return False + else: + if error[2] != "": + return False + + return True + + # Initialize the controller + controller = Controller.get_instance() + + # Test exceptions with an exception_msg + error = process_exception_return_error(Exception, "foo") + assert is_valid_error_structure(error, Exception, "foo") + + error = process_exception_return_error(KeyError, "key not found") + assert is_valid_error_structure(error, KeyError, "key not found") + + # Test exceptions without an exception_msg + error = process_exception_return_error(Exception, "") + assert is_valid_error_structure(error, Exception, "") + + error = process_exception_return_error(Exception, None) + assert is_valid_error_structure(error, Exception, None) + + def test_missing_settings_get_defaults(reset_controller): """ Should gracefully handle all missing fields from `settings.json` """ From f683bc355e609cefea5c515e97a473eae826eb45 Mon Sep 17 00:00:00 2001 From: Jean Do Date: Tue, 6 Jun 2023 14:46:37 -0400 Subject: [PATCH 3/3] 2 helpers become 1, looping over test cases --- tests/test_controller.py | 63 ++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/tests/test_controller.py b/tests/test_controller.py index 4dda4f98c..2fce03876 100644 --- a/tests/test_controller.py +++ b/tests/test_controller.py @@ -46,56 +46,43 @@ def test_singleton_get_instance_preserves_state(reset_controller): def test_handle_exception(reset_controller): """ Handle exceptions that get caught by the controller """ - def process_exception_return_error(exception_type, error_msg=None): - try: - if error_msg: - raise exception_type(error_msg) - else: - raise exception_type() - except Exception as e: - destination = controller.handle_exception(e) - return destination.view_args["error"] - - def is_valid_error_structure(error, exception_type, exception_msg): + def process_exception_asserting_valid_error(exception_type, exception_msg=None): """ Exceptions caught by the controller are forwarded to the UnhandledExceptionView with view_args["error"] being a list of three strings, ie: [exception_type, line_info, exception_msg] """ - if len(error) != 3: - return False - - if error[0] not in str(exception_type): - return False - - if type(error[1]) != str: - return False + try: + if exception_msg: + raise exception_type(exception_msg) + else: + raise exception_type() + except Exception as e: + error = controller.handle_exception(e).view_args["error"] + # assert that error structure is valid + assert len(error) == 3 + assert error[0] in str(exception_type) + assert type(error[1]) == str if exception_msg: - if exception_msg not in error[2]: - return False + assert exception_msg in error[2] else: - if error[2] != "": - return False - - return True + assert error[2] == "" # Initialize the controller controller = Controller.get_instance() - # Test exceptions with an exception_msg - error = process_exception_return_error(Exception, "foo") - assert is_valid_error_structure(error, Exception, "foo") - - error = process_exception_return_error(KeyError, "key not found") - assert is_valid_error_structure(error, KeyError, "key not found") - - # Test exceptions without an exception_msg - error = process_exception_return_error(Exception, "") - assert is_valid_error_structure(error, Exception, "") - - error = process_exception_return_error(Exception, None) - assert is_valid_error_structure(error, Exception, None) + exception_tests = [ + # exceptions with an exception_msg + (Exception, "foo"), + (KeyError, "key not found"), + # exceptions without an exception_msg + (Exception, ""), + (Exception, None), + ] + + for exception_type, exception_msg in exception_tests: + process_exception_asserting_valid_error(exception_type, exception_msg) def test_missing_settings_get_defaults(reset_controller):