From 5d11ca7650809ec6f700e988561a7540f3c07b32 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Fri, 14 Jun 2024 00:37:58 -0500 Subject: [PATCH 01/16] Increasing unit test line coverage a bit for some of the BLE classes; very very minor code cleanup where I remove a line of code that simply will not be reached. --- meshtastic/ble_interface.py | 1 - meshtastic/tests/test_ble_interface.py | 36 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 meshtastic/tests/test_ble_interface.py diff --git a/meshtastic/ble_interface.py b/meshtastic/ble_interface.py index 1c12758d..55a12b87 100644 --- a/meshtastic/ble_interface.py +++ b/meshtastic/ble_interface.py @@ -57,7 +57,6 @@ def __init__(self, address: Optional[str], noProto: bool = False, debugOut = Non except BLEInterface.BLEError as e: self.close() our_exit(e.message, 1) - return logging.debug("Mesh init starting") MeshInterface.__init__(self, debugOut = debugOut, noProto = noProto, noNodes = noNodes) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py new file mode 100644 index 00000000..13678b55 --- /dev/null +++ b/meshtastic/tests/test_ble_interface.py @@ -0,0 +1,36 @@ +"""Meshtastic unit tests for ble_interface.py""" +import logging +from unittest.mock import patch + +import pytest + +from meshtastic.ble_interface import BLEClient, BLEInterface + +def test_ble_client_no_addr_logs_message(caplog): + caplog.set_level(level=logging.DEBUG) + test_client = BLEClient(address=None) + assert "No address provided - only discover method will work." in caplog.text + +def test_ble_interface_no_addr_returns_only_basic_object(): + """ + We want BLEState to be the only property of the BLEInterface if + it's initialized with an address of None. + """ + test_interface = BLEInterface(address=None) + test_interface_dict = test_interface.__dict__ + assert len(test_interface_dict) == 1 + assert 'state' in test_interface_dict + assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) + +def test_ble_interface_bogus_addr_exits_process(): + """ + If we initialize BLEInterface with a BT address that doesn't + exist, we should exit the process + """ + # with patch('meshtastic.util.our_exit') as patch_exit: + # patch_exit.return_value = None + # test_interface = BLEInterface(address="bogus") + # patch_exit.assert_called_once() + with pytest.raises(SystemExit) as exc: + test_interface = BLEInterface(address="bogus") + assert exc.value.code == 1 \ No newline at end of file From 3513d1b4ae29869eae82a01dd938e3fb57d84494 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Fri, 14 Jun 2024 00:45:37 -0500 Subject: [PATCH 02/16] Taking linter feedback into account. --- meshtastic/tests/test_ble_interface.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 13678b55..bbe55a25 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -1,14 +1,17 @@ """Meshtastic unit tests for ble_interface.py""" import logging -from unittest.mock import patch import pytest from meshtastic.ble_interface import BLEClient, BLEInterface def test_ble_client_no_addr_logs_message(caplog): + """ + We want to see a debug message describing the error + if we try to initialize a BLEClient with no address. + """ caplog.set_level(level=logging.DEBUG) - test_client = BLEClient(address=None) + BLEClient(address=None) assert "No address provided - only discover method will work." in caplog.text def test_ble_interface_no_addr_returns_only_basic_object(): @@ -27,10 +30,6 @@ def test_ble_interface_bogus_addr_exits_process(): If we initialize BLEInterface with a BT address that doesn't exist, we should exit the process """ - # with patch('meshtastic.util.our_exit') as patch_exit: - # patch_exit.return_value = None - # test_interface = BLEInterface(address="bogus") - # patch_exit.assert_called_once() with pytest.raises(SystemExit) as exc: - test_interface = BLEInterface(address="bogus") - assert exc.value.code == 1 \ No newline at end of file + BLEInterface(address="bogus") + assert exc.value.code == 1 From 3ec7b96a8bc20452e2c810d2eca1a61f98f7f775 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Fri, 14 Jun 2024 00:55:07 -0500 Subject: [PATCH 03/16] Because GHA is hanging on the final test, I'm commenting it out, and reversing the change I made. --- meshtastic/tests/test_ble_interface.py | 17 +++++++++-------- meshtastic/util.py | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index bbe55a25..4b679809 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -25,11 +25,12 @@ def test_ble_interface_no_addr_returns_only_basic_object(): assert 'state' in test_interface_dict assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) -def test_ble_interface_bogus_addr_exits_process(): - """ - If we initialize BLEInterface with a BT address that doesn't - exist, we should exit the process - """ - with pytest.raises(SystemExit) as exc: - BLEInterface(address="bogus") - assert exc.value.code == 1 +# TODO: figure out why GitHub Actions just hangs on this test. +# def test_ble_interface_bogus_addr_exits_process(): +# """ +# If we initialize BLEInterface with a BT address that doesn't +# exist, we should exit the process +# """ +# with pytest.raises(SystemExit) as exc: +# BLEInterface(address="bogus") +# assert exc.value.code == 1 diff --git a/meshtastic/util.py b/meshtastic/util.py index 14f6a544..c0f96559 100644 --- a/meshtastic/util.py +++ b/meshtastic/util.py @@ -270,6 +270,7 @@ def our_exit(message, return_value=1) -> NoReturn: """ print(message) sys.exit(return_value) + return def support_info(): From f0a7e9358769d9184b67795e7ac9b8d84ae7fafb Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Fri, 14 Jun 2024 00:57:27 -0500 Subject: [PATCH 04/16] Linting feedback --- meshtastic/tests/test_ble_interface.py | 2 -- meshtastic/util.py | 1 - 2 files changed, 3 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 4b679809..f92c2adc 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -1,8 +1,6 @@ """Meshtastic unit tests for ble_interface.py""" import logging -import pytest - from meshtastic.ble_interface import BLEClient, BLEInterface def test_ble_client_no_addr_logs_message(caplog): diff --git a/meshtastic/util.py b/meshtastic/util.py index c0f96559..14f6a544 100644 --- a/meshtastic/util.py +++ b/meshtastic/util.py @@ -270,7 +270,6 @@ def our_exit(message, return_value=1) -> NoReturn: """ print(message) sys.exit(return_value) - return def support_info(): From 15770cd354ebc81786f23d9e80177087b335c9fe Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Mon, 17 Jun 2024 23:00:30 -0500 Subject: [PATCH 05/16] Trying to kick off new build to test things again. --- meshtastic/tests/test_ble_interface.py | 1 + 1 file changed, 1 insertion(+) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index f92c2adc..3d4a2491 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -24,6 +24,7 @@ def test_ble_interface_no_addr_returns_only_basic_object(): assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) # TODO: figure out why GitHub Actions just hangs on this test. +# Does it need to have the BT library need mocking? # def test_ble_interface_bogus_addr_exits_process(): # """ # If we initialize BLEInterface with a BT address that doesn't From a348a70dddcf7f725f3fccf7d8417b868a6b6499 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Mon, 17 Jun 2024 23:12:06 -0500 Subject: [PATCH 06/16] Hanging test job again, so eliminating another test to see if it's the problem. --- meshtastic/tests/test_ble_interface.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 3d4a2491..92c6faa8 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -12,16 +12,16 @@ def test_ble_client_no_addr_logs_message(caplog): BLEClient(address=None) assert "No address provided - only discover method will work." in caplog.text -def test_ble_interface_no_addr_returns_only_basic_object(): - """ - We want BLEState to be the only property of the BLEInterface if - it's initialized with an address of None. - """ - test_interface = BLEInterface(address=None) - test_interface_dict = test_interface.__dict__ - assert len(test_interface_dict) == 1 - assert 'state' in test_interface_dict - assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) +# def test_ble_interface_no_addr_returns_only_basic_object(): +# """ +# We want BLEState to be the only property of the BLEInterface if +# it's initialized with an address of None. +# """ +# test_interface = BLEInterface(address=None) +# test_interface_dict = test_interface.__dict__ +# assert len(test_interface_dict) == 1 +# assert 'state' in test_interface_dict +# assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) # TODO: figure out why GitHub Actions just hangs on this test. # Does it need to have the BT library need mocking? From fc55e790c4268bfd63a178e5625be9a9c85e3bcd Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Mon, 17 Jun 2024 23:14:46 -0500 Subject: [PATCH 07/16] Fixing lint problems --- meshtastic/tests/test_ble_interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 92c6faa8..2f288e3c 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -1,7 +1,7 @@ """Meshtastic unit tests for ble_interface.py""" import logging -from meshtastic.ble_interface import BLEClient, BLEInterface +from meshtastic.ble_interface import BLEClient def test_ble_client_no_addr_logs_message(caplog): """ @@ -14,7 +14,7 @@ def test_ble_client_no_addr_logs_message(caplog): # def test_ble_interface_no_addr_returns_only_basic_object(): # """ -# We want BLEState to be the only property of the BLEInterface if +# We want BLEState to be the only property of the BLEInterface if # it's initialized with an address of None. # """ # test_interface = BLEInterface(address=None) From 484218973678c370f1c7c4c3bbd411ca4762d360 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Mon, 17 Jun 2024 23:26:38 -0500 Subject: [PATCH 08/16] More diagnosing of problems with CI/CD --- meshtastic/tests/test_ble_interface.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 2f288e3c..007a5c28 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -1,16 +1,16 @@ """Meshtastic unit tests for ble_interface.py""" -import logging +# import logging -from meshtastic.ble_interface import BLEClient +# from meshtastic.ble_interface import BLEClient -def test_ble_client_no_addr_logs_message(caplog): - """ - We want to see a debug message describing the error - if we try to initialize a BLEClient with no address. - """ - caplog.set_level(level=logging.DEBUG) - BLEClient(address=None) - assert "No address provided - only discover method will work." in caplog.text +# def test_ble_client_no_addr_logs_message(caplog): +# """ +# We want to see a debug message describing the error +# if we try to initialize a BLEClient with no address. +# """ +# caplog.set_level(level=logging.DEBUG) +# BLEClient(address=None) +# assert "No address provided - only discover method will work." in caplog.text # def test_ble_interface_no_addr_returns_only_basic_object(): # """ From 473401a9d4af3c0129aed60f6c33606dde681506 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Tue, 25 Jun 2024 21:19:19 -0500 Subject: [PATCH 09/16] ble_code_coverage_1: hanging on first test was due to an open client. Closing it solves issue. Problem with third test case is more complex; needs a mock of Bluetooth device. --- meshtastic/tests/test_ble_interface.py | 52 ++++++++++++++------------ 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 007a5c28..69e04a95 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -1,35 +1,41 @@ """Meshtastic unit tests for ble_interface.py""" -# import logging +import logging -# from meshtastic.ble_interface import BLEClient +import pytest -# def test_ble_client_no_addr_logs_message(caplog): -# """ -# We want to see a debug message describing the error -# if we try to initialize a BLEClient with no address. -# """ -# caplog.set_level(level=logging.DEBUG) -# BLEClient(address=None) -# assert "No address provided - only discover method will work." in caplog.text +from meshtastic.ble_interface import BLEClient, BLEInterface -# def test_ble_interface_no_addr_returns_only_basic_object(): -# """ -# We want BLEState to be the only property of the BLEInterface if -# it's initialized with an address of None. -# """ -# test_interface = BLEInterface(address=None) -# test_interface_dict = test_interface.__dict__ -# assert len(test_interface_dict) == 1 -# assert 'state' in test_interface_dict -# assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) -# TODO: figure out why GitHub Actions just hangs on this test. -# Does it need to have the BT library need mocking? +def test_ble_client_no_addr_logs_message(caplog): + """ + We want to see a debug message describing the error + if we try to initialize a BLEClient with no address. + """ + caplog.set_level(level=logging.DEBUG) + test_ble_client = BLEClient(address=None) + test_ble_client.close() + assert "No address provided - only discover method will work." in caplog.text + + +def test_ble_interface_no_addr_returns_only_basic_object(): + """ + We want BLEState to be the only property of the BLEInterface if + it's initialized with an address of None. + """ + test_interface = BLEInterface(address=None) + test_interface_dict = test_interface.__dict__ + assert len(test_interface_dict) == 1 + assert 'state' in test_interface_dict + assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) + +# TODO: this method definitely requires a Bluetooth device be present and on +# TODO: mock out whatever it needs # def test_ble_interface_bogus_addr_exits_process(): # """ # If we initialize BLEInterface with a BT address that doesn't # exist, we should exit the process # """ # with pytest.raises(SystemExit) as exc: -# BLEInterface(address="bogus") +# test_ble_int = BLEInterface(address="bogus") # assert exc.value.code == 1 +# test_ble_int.client.close() From 340a9c20be295f48c54bb83a54b098972f108cf4 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Tue, 25 Jun 2024 22:26:11 -0500 Subject: [PATCH 10/16] ble_code_coverage_1: trying to suss out the type of error being thrown when processed in CI/CD --- meshtastic/ble_interface.py | 1 + meshtastic/tests/test_ble_interface.py | 19 +++++++++---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/meshtastic/ble_interface.py b/meshtastic/ble_interface.py index 55a12b87..6de2bce4 100644 --- a/meshtastic/ble_interface.py +++ b/meshtastic/ble_interface.py @@ -55,6 +55,7 @@ def __init__(self, address: Optional[str], noProto: bool = False, debugOut = Non self.state.BLE = True logging.debug("BLE connected") except BLEInterface.BLEError as e: + logging.debug(f"we have an error: {e}") self.close() our_exit(e.message, 1) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 69e04a95..5a01d4cd 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -29,13 +29,12 @@ def test_ble_interface_no_addr_returns_only_basic_object(): assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) # TODO: this method definitely requires a Bluetooth device be present and on -# TODO: mock out whatever it needs -# def test_ble_interface_bogus_addr_exits_process(): -# """ -# If we initialize BLEInterface with a BT address that doesn't -# exist, we should exit the process -# """ -# with pytest.raises(SystemExit) as exc: -# test_ble_int = BLEInterface(address="bogus") -# assert exc.value.code == 1 -# test_ble_int.client.close() +# TODO: mock out whatever it needs. +def test_ble_interface_bogus_addr_exits_process(): + """ + If we initialize BLEInterface with a BT address that doesn't + exist, we should exit the process + """ + with pytest.raises(SystemExit) as exc: + test_ble_int = BLEInterface(address="bogus") + assert exc.value.code == 1 From 445c03acf78ca9677448ef8ccdfc4ea695aafa82 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Tue, 25 Jun 2024 22:29:26 -0500 Subject: [PATCH 11/16] ble_code_coverage_1: linting --- meshtastic/tests/test_ble_interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 5a01d4cd..80cc2f3c 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -15,7 +15,7 @@ def test_ble_client_no_addr_logs_message(caplog): test_ble_client = BLEClient(address=None) test_ble_client.close() assert "No address provided - only discover method will work." in caplog.text - + def test_ble_interface_no_addr_returns_only_basic_object(): """ @@ -36,5 +36,5 @@ def test_ble_interface_bogus_addr_exits_process(): exist, we should exit the process """ with pytest.raises(SystemExit) as exc: - test_ble_int = BLEInterface(address="bogus") + BLEInterface(address="bogus") assert exc.value.code == 1 From 5dad15cefbb772979a9f91de10928e2a90497ca1 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Tue, 25 Jun 2024 22:41:12 -0500 Subject: [PATCH 12/16] ble_code_coverage_1: additional test cases for _sanitize_address --- meshtastic/tests/test_ble_interface.py | 40 ++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 80cc2f3c..1912724f 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -28,13 +28,37 @@ def test_ble_interface_no_addr_returns_only_basic_object(): assert 'state' in test_interface_dict assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) -# TODO: this method definitely requires a Bluetooth device be present and on -# TODO: mock out whatever it needs. -def test_ble_interface_bogus_addr_exits_process(): +def test_ble_interface_sanitize_address_returns_lower(): + """ + _sanitize_address should only return lower case letters + """ + assert BLEInterface._sanitize_address("HELLO") == "hello" + +def test_ble_interface_sanitize_address_returns_no_underscores(): + """ + _sanitize_address should only return strings without underscores + """ + assert BLEInterface._sanitize_address("hello_world") == "helloworld" + +def test_ble_interface_sanitize_address_returns_no_dash(): + """ + _sanitize_address should only return strings without dashes + """ + assert BLEInterface._sanitize_address("hello-world") == "helloworld" + +def test_ble_interface_sanitize_address_returns_no_colon(): """ - If we initialize BLEInterface with a BT address that doesn't - exist, we should exit the process + _sanitize_address should only return strings without colons """ - with pytest.raises(SystemExit) as exc: - BLEInterface(address="bogus") - assert exc.value.code == 1 + assert BLEInterface._sanitize_address("hello:world") == "helloworld" + +# TODO: this method definitely requires a Bluetooth device be present and on +# TODO: mock out whatever it needs. +# def test_ble_interface_bogus_addr_exits_process(): +# """ +# If we initialize BLEInterface with a BT address that doesn't +# exist, we should exit the process +# """ +# with pytest.raises(SystemExit) as exc: +# BLEInterface(address="bogus") +# assert exc.value.code == 1 From 1bb912893bee4fcb04c7f756f84b33fca1c9fd7a Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Tue, 25 Jun 2024 22:43:31 -0500 Subject: [PATCH 13/16] ble_code_coverage_1: linting --- meshtastic/tests/test_ble_interface.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 1912724f..8c8d8cb2 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -1,8 +1,6 @@ """Meshtastic unit tests for ble_interface.py""" import logging -import pytest - from meshtastic.ble_interface import BLEClient, BLEInterface From 8f0af0d24fff079993b8c95e96af259eae9a1d2a Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Tue, 25 Jun 2024 23:57:52 -0500 Subject: [PATCH 14/16] ble_code_coverage_1: At a stopping point, need to understand the underlying code around connections before I change it more. --- meshtastic/ble_interface.py | 1 - 1 file changed, 1 deletion(-) diff --git a/meshtastic/ble_interface.py b/meshtastic/ble_interface.py index 6de2bce4..55a12b87 100644 --- a/meshtastic/ble_interface.py +++ b/meshtastic/ble_interface.py @@ -55,7 +55,6 @@ def __init__(self, address: Optional[str], noProto: bool = False, debugOut = Non self.state.BLE = True logging.debug("BLE connected") except BLEInterface.BLEError as e: - logging.debug(f"we have an error: {e}") self.close() our_exit(e.message, 1) From 268911034cbbbdcae7ce05475d80f3c1b1ac6496 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Mon, 8 Jul 2024 21:40:31 -0500 Subject: [PATCH 15/16] ble_code_coverage_1: adding Linux tests for several new lines; removing now-obsolete test, adding test for non-CI environments --- meshtastic/ble_interface.py | 9 ++++--- meshtastic/tests/test_ble_interface.py | 35 ++++++++++---------------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/meshtastic/ble_interface.py b/meshtastic/ble_interface.py index bc57157a..e9cced87 100644 --- a/meshtastic/ble_interface.py +++ b/meshtastic/ble_interface.py @@ -3,6 +3,7 @@ import asyncio import atexit import logging +import platform import struct import time from threading import Thread @@ -80,7 +81,8 @@ def __init__( # We MUST run atexit (if we can) because otherwise (at least on linux) the BLE device is not disconnected # and future connection attempts will fail. (BlueZ kinda sucks) # Note: the on disconnected callback will call our self.close which will make us nicely wait for threads to exit - self._exit_handler = atexit.register(self.client.disconnect) + if platform.system() == "Linux": + self._exit_handler = atexit.register(self.client.disconnect) def from_num_handler(self, _, b): # pylint: disable=C0116 """Handle callbacks for fromnum notify. @@ -227,7 +229,8 @@ def _sendToRadioImpl(self, toRadio): self.should_read = True def close(self): - atexit.unregister(self._exit_handler) + if platform.system() == "Linux": + atexit.unregister(self._exit_handler) try: MeshInterface.close(self) except Exception as e: @@ -238,7 +241,7 @@ def close(self): self._receiveThread.join(timeout=2) # If bleak is hung, don't wait for the thread to exit (it is critical we disconnect) self._receiveThread = None - if self.client: + if hasattr(self, "client"): self.client.disconnect() self.client.close() self.client = None diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index 8c8d8cb2..ef73b708 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -1,5 +1,8 @@ """Meshtastic unit tests for ble_interface.py""" import logging +import os + +import pytest from meshtastic.ble_interface import BLEClient, BLEInterface @@ -14,18 +17,6 @@ def test_ble_client_no_addr_logs_message(caplog): test_ble_client.close() assert "No address provided - only discover method will work." in caplog.text - -def test_ble_interface_no_addr_returns_only_basic_object(): - """ - We want BLEState to be the only property of the BLEInterface if - it's initialized with an address of None. - """ - test_interface = BLEInterface(address=None) - test_interface_dict = test_interface.__dict__ - assert len(test_interface_dict) == 1 - assert 'state' in test_interface_dict - assert isinstance(test_interface_dict['state'], BLEInterface.BLEState) - def test_ble_interface_sanitize_address_returns_lower(): """ _sanitize_address should only return lower case letters @@ -50,13 +41,13 @@ def test_ble_interface_sanitize_address_returns_no_colon(): """ assert BLEInterface._sanitize_address("hello:world") == "helloworld" -# TODO: this method definitely requires a Bluetooth device be present and on -# TODO: mock out whatever it needs. -# def test_ble_interface_bogus_addr_exits_process(): -# """ -# If we initialize BLEInterface with a BT address that doesn't -# exist, we should exit the process -# """ -# with pytest.raises(SystemExit) as exc: -# BLEInterface(address="bogus") -# assert exc.value.code == 1 + +@pytest.mark.skipif(os.environ.get("CI") == "true", reason="Bluetooth tests are not supported in CI environment") +def test_ble_interface_bogus_addr_exits_process(): + """ + If we initialize BLEInterface with a BT address that doesn't + exist, we should exit the process + """ + with pytest.raises(BLEInterface.BLEError) as exc: + BLEInterface(address="bogus") + assert "No Meshtastic BLE peripheral with identifier or address 'bogus' found" in exc.value.args[0] From d02292a329bb47a152c66b54a2a87a18d98533c7 Mon Sep 17 00:00:00 2001 From: Nerdenator Date: Mon, 15 Jul 2024 00:17:47 -0500 Subject: [PATCH 16/16] ble_code_coverage_1: more attempts to get the remaining lines of code covered --- meshtastic/tests/test_ble_interface.py | 11 +++++++++++ poetry.lock | 4 ++-- pyproject.toml | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/meshtastic/tests/test_ble_interface.py b/meshtastic/tests/test_ble_interface.py index ef73b708..4ed60ce3 100644 --- a/meshtastic/tests/test_ble_interface.py +++ b/meshtastic/tests/test_ble_interface.py @@ -1,6 +1,7 @@ """Meshtastic unit tests for ble_interface.py""" import logging import os +from unittest.mock import patch import pytest @@ -41,6 +42,16 @@ def test_ble_interface_sanitize_address_returns_no_colon(): """ assert BLEInterface._sanitize_address("hello:world") == "helloworld" +def test_linux_exit_handler(): + """ + Given a platform.system of Linux (or as I like to call it, Ganoo plus Linux), + we should register an exit handler. + """ + with patch("platform.system") as fake_platform: + fake_platform.return_value = "Linux" + test_interface = BLEInterface(address="") + assert test_interface._exit_handler is not None + @pytest.mark.skipif(os.environ.get("CI") == "true", reason="Bluetooth tests are not supported in CI environment") def test_ble_interface_bogus_addr_exits_process(): diff --git a/poetry.lock b/poetry.lock index 4c4b23d4..8dfc8bf8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "altgraph" @@ -4009,4 +4009,4 @@ tunnel = [] [metadata] lock-version = "2.0" python-versions = "^3.9,<3.13" -content-hash = "a6032933510dcce0d89660fb1548219dee51e3373a65cf4addcec1f2b93fbceb" +content-hash = "7f256b39b5a108cf14addd9803c903d2c18ad2febce53f648b54941a5ed8d2f3" diff --git a/pyproject.toml b/pyproject.toml index d089606f..1d1b3de7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,7 @@ ppk2-api = "^0.9.2" pyarrow = "^16.1.0" platformdirs = "^4.2.2" print-color = "^0.4.6" +dbus-fast = "^2.22.1" [tool.poetry.group.dev.dependencies] hypothesis = "^6.103.2"