Skip to content

Commit e7664cb

Browse files
authored
Merge pull request #204 from mkinney/add_more_unit_tests
get last two lines covered in node
2 parents 9380f04 + 83c18f4 commit e7664cb

File tree

3 files changed

+112
-8
lines changed

3 files changed

+112
-8
lines changed

meshtastic/mesh_interface.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,7 @@ def __enter__(self):
6868

6969
def __exit__(self, exc_type, exc_value, traceback):
7070
if exc_type is not None and exc_value is not None:
71-
logging.error(
72-
f'An exception of type {exc_type} with value {exc_value} has occurred')
71+
logging.error(f'An exception of type {exc_type} with value {exc_value} has occurred')
7372
if traceback is not None:
7473
logging.error(f'Traceback: {traceback}')
7574
self.close()
@@ -394,11 +393,11 @@ def getShortName(self):
394393
return user.get('shortName', None)
395394
return None
396395

397-
def _waitConnected(self):
396+
def _waitConnected(self, timeout=15.0):
398397
"""Block until the initial node db download is complete, or timeout
399398
and raise an exception"""
400399
if not self.noProto:
401-
if not self.isConnected.wait(15.0): # timeout after x seconds
400+
if not self.isConnected.wait(timeout): # timeout after x seconds
402401
raise Exception("Timed out waiting for connection completion")
403402

404403
# If we failed while connecting, raise the connection to the client
@@ -416,8 +415,7 @@ def _generatePacketId(self):
416415
def _disconnected(self):
417416
"""Called by subclasses to tell clients this interface has disconnected"""
418417
self.isConnected.clear()
419-
publishingThread.queueWork(lambda: pub.sendMessage(
420-
"meshtastic.connection.lost", interface=self))
418+
publishingThread.queueWork(lambda: pub.sendMessage("meshtastic.connection.lost", interface=self))
421419

422420
def _startHeartbeat(self):
423421
"""We need to send a heartbeat message to the device every X seconds"""
@@ -443,8 +441,7 @@ def _connected(self):
443441
if not self.isConnected.is_set():
444442
self.isConnected.set()
445443
self._startHeartbeat()
446-
publishingThread.queueWork(lambda: pub.sendMessage(
447-
"meshtastic.connection.established", interface=self))
444+
publishingThread.queueWork(lambda: pub.sendMessage("meshtastic.connection.established", interface=self))
448445

449446
def _startConfig(self):
450447
"""Start device packets flowing"""

meshtastic/tests/test_mesh_interface.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
from ..node import Node
1111
from .. import mesh_pb2
1212
from ..__init__ import LOCAL_ADDR, BROADCAST_ADDR
13+
from ..radioconfig_pb2 import RadioConfig
14+
from ..util import Timeout
1315

1416

1517
@pytest.mark.unit
@@ -164,6 +166,22 @@ def test_sendPosition(reset_globals, caplog):
164166
assert re.search(r'p.time:', caplog.text, re.MULTILINE)
165167

166168

169+
@pytest.mark.unit
170+
def test_close_with_heartbeatTimer(reset_globals, caplog):
171+
"""Test close() with heartbeatTimer"""
172+
iface = MeshInterface(noProto=True)
173+
anode = Node('foo', 'bar')
174+
radioConfig = RadioConfig()
175+
radioConfig.preferences.phone_timeout_secs = 10
176+
anode.radioConfig = radioConfig
177+
iface.localNode = anode
178+
assert iface.heartbeatTimer is None
179+
with caplog.at_level(logging.DEBUG):
180+
iface._startHeartbeat()
181+
assert iface.heartbeatTimer is not None
182+
iface.close()
183+
184+
167185
@pytest.mark.unit
168186
def test_handleFromRadio_empty_payload(reset_globals, caplog):
169187
"""Test _handleFromRadio"""
@@ -543,3 +561,70 @@ def test_getOrCreateByNum(capsys, reset_globals, iface_with_nodes):
543561
iface.myInfo.my_node_num = 2475227164
544562
tmp = iface._getOrCreateByNum(2475227164)
545563
assert tmp['num'] == 2475227164
564+
565+
566+
@pytest.mark.unit
567+
def test_enter():
568+
"""Test __enter__()"""
569+
iface = MeshInterface(noProto=True)
570+
assert iface == iface.__enter__()
571+
572+
573+
@pytest.mark.unit
574+
def test_exit_with_exception(caplog):
575+
"""Test __exit__()"""
576+
iface = MeshInterface(noProto=True)
577+
with caplog.at_level(logging.ERROR):
578+
iface.__exit__('foo', 'bar', 'baz')
579+
assert re.search(r'An exception of type foo with value bar has occurred', caplog.text, re.MULTILINE)
580+
assert re.search(r'Traceback: baz', caplog.text, re.MULTILINE)
581+
582+
583+
@pytest.mark.unit
584+
def test_showNodes_exclude_self(capsys, caplog, reset_globals, iface_with_nodes):
585+
"""Test that we hit that continue statement"""
586+
with caplog.at_level(logging.DEBUG):
587+
iface = iface_with_nodes
588+
iface.localNode.nodeNum = 2475227164
589+
iface.showNodes()
590+
iface.showNodes(includeSelf=False)
591+
capsys.readouterr()
592+
593+
594+
@pytest.mark.unit
595+
def test_waitForConfig(caplog, capsys):
596+
"""Test waitForConfig()"""
597+
iface = MeshInterface(noProto=True)
598+
# override how long to wait
599+
iface._timeout = Timeout(0.01)
600+
with pytest.raises(Exception) as pytest_wrapped_e:
601+
iface.waitForConfig()
602+
assert pytest_wrapped_e.type == Exception
603+
out, err = capsys.readouterr()
604+
assert re.search(r'Exception: Timed out waiting for interface config', err, re.MULTILINE)
605+
assert out == ''
606+
607+
608+
@pytest.mark.unit
609+
def test_waitConnected_raises_an_exception(caplog, capsys):
610+
"""Test waitConnected()"""
611+
iface = MeshInterface(noProto=True)
612+
with pytest.raises(Exception) as pytest_wrapped_e:
613+
iface.failure = "warn about something"
614+
iface._waitConnected(0.01)
615+
assert pytest_wrapped_e.type == Exception
616+
out, err = capsys.readouterr()
617+
assert re.search(r'warn about something', err, re.MULTILINE)
618+
assert out == ''
619+
620+
621+
@pytest.mark.unit
622+
def test_waitConnected_isConnected_timeout(caplog, capsys):
623+
"""Test waitConnected()"""
624+
with pytest.raises(Exception) as pytest_wrapped_e:
625+
iface = MeshInterface()
626+
iface._waitConnected(0.01)
627+
assert pytest_wrapped_e.type == Exception
628+
out, err = capsys.readouterr()
629+
assert re.search(r'warn about something', err, re.MULTILINE)
630+
assert out == ''

meshtastic/tests/test_node.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from ..admin_pb2 import AdminMessage
1212
from ..channel_pb2 import Channel
1313
from ..radioconfig_pb2 import RadioConfig
14+
from ..util import Timeout
1415

1516

1617
@pytest.mark.unit
@@ -90,6 +91,16 @@ def test_setOwner_no_short_name_and_long_name_has_words(caplog):
9091
assert re.search(r'p.set_owner.team:0', caplog.text, re.MULTILINE)
9192

9293

94+
@pytest.mark.unit
95+
def test_setOwner_long_name_no_short(caplog):
96+
"""Test setOwner"""
97+
anode = Node('foo', 'bar', noProto=True)
98+
with caplog.at_level(logging.DEBUG):
99+
anode.setOwner(long_name ='Aabo', is_licensed=True)
100+
assert re.search(r'p.set_owner.long_name:Aabo:', caplog.text, re.MULTILINE)
101+
assert re.search(r'p.set_owner.short_name:Aab:', caplog.text, re.MULTILINE)
102+
103+
93104
@pytest.mark.unit
94105
def test_exitSimulator(caplog):
95106
"""Test exitSimulator"""
@@ -869,3 +880,14 @@ def test_onResponseRequestSetting_with_error(capsys):
869880
out, err = capsys.readouterr()
870881
assert re.search(r'Error on response', out)
871882
assert err == ''
883+
884+
885+
@pytest.mark.unit
886+
def test_waitForConfig():
887+
"""Test waitForConfig()"""
888+
anode = Node('foo', 'bar')
889+
radioConfig = RadioConfig()
890+
anode.radioConfig = radioConfig
891+
anode._timeout = Timeout(0.01)
892+
result = anode.waitForConfig()
893+
assert not result

0 commit comments

Comments
 (0)