diff --git a/.coveragerc b/.coveragerc index 85bf3bb..055fbe5 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,2 +1,2 @@ [run] -omit = meshtastic/*_pb2.py,meshtastic/test.py,meshtastic/test/*.py +omit = meshtastic/*_pb2.py,meshtastic/tests/*.py diff --git a/README.md b/README.md index ac8f760..003c2be 100644 --- a/README.md +++ b/README.md @@ -231,11 +231,11 @@ pytest -m smokewifi * To run a specific test: ``` -pytest -msmoke1 meshtastic/test/test_smoke1.py::test_smoke1_info +pytest -msmoke1 meshtastic/tests/test_smoke1.py::test_smoke1_info # or to run a specific smoke2 test -pytest -m smoke2 meshtastic/test/test_smoke2.py::test_smoke2_info +pytest -m smoke2 meshtastic/tests/test_smoke2.py::test_smoke2_info # or to run a specific smoke_wifi test -pytest -m smokewifi meshtastic/test/test_smoke_wifi.py::test_smokewifi_info +pytest -m smokewifi meshtastic/tests/test_smoke_wifi.py::test_smokewifi_info ``` * To add another classification of tests such as "unit" or "smoke1", see [pytest.ini](pytest.ini). diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index f060465..a8738c8 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -11,12 +11,13 @@ import yaml from pubsub import pub import pyqrcode import pkg_resources +import meshtastic.util +import meshtastic.test from .serial_interface import SerialInterface from .tcp_interface import TCPInterface from .ble_interface import BLEInterface -from . import test, remote_hardware +from . import remote_hardware from . import portnums_pb2, channel_pb2, mesh_pb2, radioconfig_pb2 -from .util import support_info, our_exit, genPSK256, fromPSK, fromStr from .globals import Globals """We only import the tunnel code if we are on a platform that can run it""" @@ -98,7 +99,7 @@ def setPref(attributes, name, valStr): print(f" {f.name}") return - val = fromStr(valStr) + val = meshtastic.util.fromStr(valStr) enumType = field.enum_type # pylint: disable=C0123 @@ -232,7 +233,7 @@ def onConnected(interface): getNode().setOwner(args.set_ham, is_licensed=True) # Must turn off crypt on primary channel ch = getNode().channels[0] - ch.settings.psk = fromPSK("none") + ch.settings.psk = meshtastic.util.fromPSK("none") print(f"Writing modified channels to device") getNode().writeChannel(0) @@ -349,7 +350,7 @@ def onConnected(interface): closeNow = True n = getNode() if len(args.ch_add) > 10: - our_exit("Warning: Channel name must be shorter. Channel not added.") + meshtastic.util.our_exit("Warning: Channel name must be shorter. Channel not added.") ch = n.getChannelByName(args.ch_add) if ch: logging.error( @@ -357,9 +358,9 @@ def onConnected(interface): else: ch = n.getDisabledChannel() if not ch: - our_exit("Warning: No free channels were found") + meshtastic.util.our_exit("Warning: No free channels were found") chs = channel_pb2.ChannelSettings() - chs.psk = genPSK256() + chs.psk = meshtastic.util.genPSK256() chs.name = args.ch_add ch.settings.CopyFrom(chs) ch.role = channel_pb2.Channel.Role.SECONDARY @@ -383,7 +384,7 @@ def onConnected(interface): if args.ch_longslow or args.ch_longfast or args.ch_mediumslow or args.ch_mediumfast or args.ch_shortslow or args.ch_shortfast: if channelIndex != 0: - our_exit("Warning: Standard channel settings can only be applied to the PRIMARY channel") + meshtastic.util.our_exit("Warning: Standard channel settings can only be applied to the PRIMARY channel") enable = True # force enable @@ -425,7 +426,7 @@ def onConnected(interface): # Handle the channel settings for pref in (args.ch_set or []): if pref[0] == "psk": - ch.settings.psk = fromPSK(pref[1]) + ch.settings.psk = meshtastic.util.fromPSK(pref[1]) else: setPref(ch.settings, pref[0], pref[1]) enable = True # If we set any pref, assume the user wants to enable the channel @@ -512,11 +513,11 @@ def common(): if len(sys.argv) == 1: parser.print_help(sys.stderr) - our_exit("", 1) + meshtastic.util.our_exit("", 1) else: if args.support: - support_info() - our_exit("", 0) + meshtastic.util.support_info() + meshtastic.util.our_exit("", 0) if args.ch_index is not None: channelIndex = int(args.ch_index) @@ -540,11 +541,13 @@ def common(): logging.error( 'This option has been deprecated, see help below for the correct replacement...') parser.print_help(sys.stderr) - our_exit('', 1) + meshtastic.util.our_exit('', 1) elif args.test: - result = test.testAll() + result = meshtastic.test.testAll() if not result: - our_exit("Warning: Test was not successful.") + meshtastic.util.our_exit("Warning: Test was not successful.") + else: + meshtastic.util.our_exit("Test was a success.", 0) else: if args.seriallog == "stdout": logfile = sys.stdout diff --git a/meshtastic/test.py b/meshtastic/test.py index 9930cae..0c70f73 100644 --- a/meshtastic/test.py +++ b/meshtastic/test.py @@ -7,11 +7,11 @@ import sys import traceback from dotmap import DotMap from pubsub import pub -from . import util +import meshtastic.util from .__init__ import BROADCAST_NUM from .serial_interface import SerialInterface from .tcp_interface import TCPInterface -from .util import our_exit + """The interfaces we are using for our tests""" interfaces = None @@ -146,9 +146,9 @@ def testAll(numTests=5): This is called from the cli with the "--test" option. """ - ports = util.findPorts() + ports = meshtastic.util.findPorts() if len(ports) < 2: - our_exit("Warning: Must have at least two devices connected to USB.") + meshtastic.util.our_exit("Warning: Must have at least two devices connected to USB.") pub.subscribe(onConnection, "meshtastic.connection") pub.subscribe(onReceive, "meshtastic.receive") diff --git a/meshtastic/test/__init__.py b/meshtastic/tests/__init__.py similarity index 100% rename from meshtastic/test/__init__.py rename to meshtastic/tests/__init__.py diff --git a/meshtastic/test/test_globals.py b/meshtastic/tests/test_globals.py similarity index 100% rename from meshtastic/test/test_globals.py rename to meshtastic/tests/test_globals.py diff --git a/meshtastic/test/test_int.py b/meshtastic/tests/test_int.py similarity index 100% rename from meshtastic/test/test_int.py rename to meshtastic/tests/test_int.py diff --git a/meshtastic/test/test_main.py b/meshtastic/tests/test_main.py similarity index 63% rename from meshtastic/test/test_main.py rename to meshtastic/tests/test_main.py index d9eaaaa..58e48b3 100644 --- a/meshtastic/test/test_main.py +++ b/meshtastic/tests/test_main.py @@ -4,6 +4,7 @@ import sys import argparse import re +from unittest.mock import patch import pytest from meshtastic.__main__ import initParser, main, Globals @@ -120,3 +121,61 @@ def test_main_ch_index_no_devices(capsys): out, err = capsys.readouterr() assert re.search(r'Warning: No Meshtastic devices detected', out, re.MULTILINE) assert err == '' + + +@pytest.mark.unit +@patch('meshtastic.util.findPorts', return_value=[]) +def test_main_test_no_ports(patched_find_ports): + """Test --test with no hardware""" + sys.argv = ['', '--test'] + args = sys.argv + parser = None + parser = argparse.ArgumentParser() + our_globals = Globals.getInstance() + our_globals.set_parser(parser) + our_globals.set_args(args) + assert our_globals.get_target_node() is None + with pytest.raises(SystemExit) as pytest_wrapped_e: + main() + assert pytest_wrapped_e.type == SystemExit + assert pytest_wrapped_e.value.code == 1 + patched_find_ports.assert_called() + + +@pytest.mark.unit +@patch('meshtastic.util.findPorts', return_value=['/dev/ttyFake1']) +def test_main_test_one_port(patched_find_ports): + """Test --test with one fake port""" + sys.argv = ['', '--test'] + args = sys.argv + parser = None + parser = argparse.ArgumentParser() + our_globals = Globals.getInstance() + our_globals.set_parser(parser) + our_globals.set_args(args) + assert our_globals.get_target_node() is None + with pytest.raises(SystemExit) as pytest_wrapped_e: + main() + assert pytest_wrapped_e.type == SystemExit + assert pytest_wrapped_e.value.code == 1 + patched_find_ports.assert_called() + + +@pytest.mark.unit +@patch('meshtastic.test.testAll', return_value=True) +@patch('meshtastic.util.findPorts', return_value=['/dev/ttyFake1', '/dev/ttyFake2']) +def test_main_test_two_ports_success(patched_find_ports, patched_test_all): + """Test --test two fake ports""" + sys.argv = ['', '--test'] + args = sys.argv + parser = None + parser = argparse.ArgumentParser() + our_globals = Globals.getInstance() + our_globals.set_parser(parser) + our_globals.set_args(args) + with pytest.raises(SystemExit) as pytest_wrapped_e: + main() + assert pytest_wrapped_e.type == SystemExit + assert pytest_wrapped_e.value.code == 0 + # TODO: why does this fail? patched_find_ports.assert_called() + patched_test_all.assert_called() diff --git a/meshtastic/test/test_mesh_interface.py b/meshtastic/tests/test_mesh_interface.py similarity index 100% rename from meshtastic/test/test_mesh_interface.py rename to meshtastic/tests/test_mesh_interface.py diff --git a/meshtastic/test/test_serial_interface.py b/meshtastic/tests/test_serial_interface.py similarity index 100% rename from meshtastic/test/test_serial_interface.py rename to meshtastic/tests/test_serial_interface.py diff --git a/meshtastic/test/test_smoke1.py b/meshtastic/tests/test_smoke1.py similarity index 100% rename from meshtastic/test/test_smoke1.py rename to meshtastic/tests/test_smoke1.py diff --git a/meshtastic/test/test_smoke2.py b/meshtastic/tests/test_smoke2.py similarity index 100% rename from meshtastic/test/test_smoke2.py rename to meshtastic/tests/test_smoke2.py diff --git a/meshtastic/test/test_smoke_wifi.py b/meshtastic/tests/test_smoke_wifi.py similarity index 100% rename from meshtastic/test/test_smoke_wifi.py rename to meshtastic/tests/test_smoke_wifi.py diff --git a/meshtastic/test/test_stream_interface.py b/meshtastic/tests/test_stream_interface.py similarity index 100% rename from meshtastic/test/test_stream_interface.py rename to meshtastic/tests/test_stream_interface.py diff --git a/meshtastic/test/test_tcp_interface.py b/meshtastic/tests/test_tcp_interface.py similarity index 100% rename from meshtastic/test/test_tcp_interface.py rename to meshtastic/tests/test_tcp_interface.py diff --git a/meshtastic/test/test_util.py b/meshtastic/tests/test_util.py similarity index 100% rename from meshtastic/test/test_util.py rename to meshtastic/tests/test_util.py