mirror of
https://github.com/meshtastic/python.git
synced 2025-12-28 18:37:52 -05:00
Merge pull request #153 from mkinney/even_more_unit_tests
Even more unit tests
This commit is contained in:
@@ -16,15 +16,12 @@ from .tcp_interface import TCPInterface
|
||||
from .ble_interface import BLEInterface
|
||||
from . import test, remote_hardware
|
||||
from . import portnums_pb2, channel_pb2, mesh_pb2, radioconfig_pb2
|
||||
from . import tunnel
|
||||
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"""
|
||||
have_tunnel = platform.system() == 'Linux'
|
||||
|
||||
channelIndex = 0
|
||||
|
||||
|
||||
def onReceive(packet, interface):
|
||||
"""Callback invoked when a packet arrives"""
|
||||
@@ -131,9 +128,6 @@ def setPref(attributes, name, valStr):
|
||||
print(f"Can't set {name} due to {ex}")
|
||||
|
||||
|
||||
targetNode = None
|
||||
|
||||
|
||||
def onConnected(interface):
|
||||
"""Callback invoked when we connect to a radio"""
|
||||
closeNow = False # Should we drop the connection after we finish?
|
||||
@@ -145,9 +139,10 @@ def onConnected(interface):
|
||||
|
||||
def getNode():
|
||||
"""This operation could be expensive, so we try to cache the results"""
|
||||
global targetNode
|
||||
targetNode = our_globals.get_target_node()
|
||||
if not targetNode:
|
||||
targetNode = interface.getNode(args.destOrLocal)
|
||||
our_globals.set_target_node(targetNode)
|
||||
return targetNode
|
||||
|
||||
if args.setlat or args.setlon or args.setalt:
|
||||
@@ -374,12 +369,14 @@ def onConnected(interface):
|
||||
if args.ch_del:
|
||||
closeNow = True
|
||||
|
||||
channelIndex = our_globals.get_channel_index()
|
||||
print(f"Deleting channel {channelIndex}")
|
||||
ch = getNode().deleteChannel(channelIndex)
|
||||
|
||||
if args.ch_set or args.ch_longslow or args.ch_longfast or args.ch_mediumslow or args.ch_mediumfast or args.ch_shortslow or args.ch_shortfast:
|
||||
closeNow = True
|
||||
|
||||
channelIndex = our_globals.get_channel_index()
|
||||
ch = getNode().channels[channelIndex]
|
||||
|
||||
enable = args.ch_enable # should we enable this channel?
|
||||
@@ -475,6 +472,8 @@ def onConnected(interface):
|
||||
print(qr.terminal())
|
||||
|
||||
if have_tunnel and args.tunnel:
|
||||
# pylint: disable=C0415
|
||||
from . import tunnel
|
||||
# Even if others said we could close, stay open if the user asked for a tunnel
|
||||
closeNow = False
|
||||
tunnel.Tunnel(interface, subnet=args.tunnel_net)
|
||||
@@ -513,16 +512,15 @@ def common():
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
parser.print_help(sys.stderr)
|
||||
sys.exit(1)
|
||||
our_exit("", 1)
|
||||
else:
|
||||
if args.support:
|
||||
print("")
|
||||
support_info()
|
||||
sys.exit(0)
|
||||
our_exit("", 0)
|
||||
|
||||
if args.ch_index is not None:
|
||||
global channelIndex
|
||||
channelIndex = int(args.ch_index)
|
||||
our_globals.set_channel_index(channelIndex)
|
||||
|
||||
# Some commands require dest to be set, so we now use destOrAll/destOrLocal for more lenient commands
|
||||
if not args.dest:
|
||||
@@ -542,10 +540,9 @@ def common():
|
||||
logging.error(
|
||||
'This option has been deprecated, see help below for the correct replacement...')
|
||||
parser.print_help(sys.stderr)
|
||||
sys.exit(1)
|
||||
elif args.numTests:
|
||||
numTests = int(args.numTests[0])
|
||||
result = test.testAll(numTests)
|
||||
our_exit('', 1)
|
||||
elif args.test:
|
||||
result = test.testAll()
|
||||
if not result:
|
||||
our_exit("Warning: Test was not successful.")
|
||||
else:
|
||||
@@ -722,7 +719,7 @@ def initParser():
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("--test", help="Run stress test against all connected Meshtastic devices",
|
||||
nargs=1, dest='numTests', action="store")
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("--ble", help="BLE mac address to connect to (BLE is not yet supported for this tool)",
|
||||
default=None)
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
This is not much better than using python's globals, but it allows
|
||||
us to better test meshtastic. Plus, there are some weird python
|
||||
global issues/gotcha that we can hopefully avoid by using this
|
||||
class in stead.
|
||||
class instead.
|
||||
|
||||
"""
|
||||
|
||||
class Globals:
|
||||
@@ -26,6 +27,8 @@ class Globals:
|
||||
Globals.__instance = self
|
||||
self.args = None
|
||||
self.parser = None
|
||||
self.target_node = None
|
||||
self.channel_index = 0
|
||||
|
||||
def set_args(self, args):
|
||||
"""Set the args"""
|
||||
@@ -35,6 +38,14 @@ class Globals:
|
||||
"""Set the parser"""
|
||||
self.parser = parser
|
||||
|
||||
def set_target_node(self, target_node):
|
||||
"""Set the target_node"""
|
||||
self.target_node = target_node
|
||||
|
||||
def set_channel_index(self, channel_index):
|
||||
"""Set the channel_index"""
|
||||
self.channel_index = channel_index
|
||||
|
||||
def get_args(self):
|
||||
"""Get args"""
|
||||
return self.args
|
||||
@@ -42,3 +53,11 @@ class Globals:
|
||||
def get_parser(self):
|
||||
"""Get parser"""
|
||||
return self.parser
|
||||
|
||||
def get_target_node(self):
|
||||
"""Get target_node"""
|
||||
return self.target_node
|
||||
|
||||
def get_channel_index(self):
|
||||
"""Get channel_index"""
|
||||
return self.channel_index
|
||||
|
||||
@@ -38,9 +38,8 @@ class RemoteHardwareClient:
|
||||
|
||||
def _sendHardware(self, nodeid, r, wantResponse=False, onResponse=None):
|
||||
if not nodeid:
|
||||
# pylint: disable=W1401
|
||||
raise Exception(
|
||||
"You must set a destination node ID for this operation (use --dest \!xxxxxxxxx)")
|
||||
r"You must set a destination node ID for this operation (use --dest \!xxxxxxxxx)")
|
||||
return self.iface.sendData(r, nodeid, portnums_pb2.REMOTE_HARDWARE_APP,
|
||||
wantAck=True, channelIndex=self.channelIndex, wantResponse=wantResponse, onResponse=onResponse)
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ def openDebugLog(portName):
|
||||
return open(debugname, 'w+', buffering=1, encoding='utf8')
|
||||
|
||||
|
||||
def testAll(numTests=50):
|
||||
def testAll(numTests=5):
|
||||
"""
|
||||
Run a series of tests using devices we can find.
|
||||
This is called from the cli with the "--test" option.
|
||||
|
||||
@@ -6,7 +6,7 @@ import re
|
||||
|
||||
import pytest
|
||||
|
||||
from meshtastic.__main__ import initParser, Globals
|
||||
from meshtastic.__main__ import initParser, main, Globals
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@@ -41,3 +41,82 @@ def test_main_init_parser_version(capsys):
|
||||
out, err = capsys.readouterr()
|
||||
assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
|
||||
assert err == ''
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_main_main_version(capsys):
|
||||
"""Test --version"""
|
||||
sys.argv = ['', '--version']
|
||||
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
|
||||
out, err = capsys.readouterr()
|
||||
assert re.match(r'[0-9]+\.[0-9]+\.[0-9]', out)
|
||||
assert err == ''
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_main_main_no_args():
|
||||
"""Test with no args"""
|
||||
sys.argv = ['']
|
||||
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 == 1
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_main_support(capsys):
|
||||
"""Test --support"""
|
||||
sys.argv = ['', '--support']
|
||||
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
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r'System', out, re.MULTILINE)
|
||||
assert re.search(r'Platform', out, re.MULTILINE)
|
||||
assert re.search(r'Machine', out, re.MULTILINE)
|
||||
assert re.search(r'Executable', out, re.MULTILINE)
|
||||
assert err == ''
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
def test_main_ch_index_no_devices(capsys):
|
||||
"""Test --ch-index 1"""
|
||||
sys.argv = ['', '--ch-index', '1']
|
||||
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
|
||||
assert our_globals.get_channel_index() == 0
|
||||
with pytest.raises(SystemExit) as pytest_wrapped_e:
|
||||
main()
|
||||
assert our_globals.get_channel_index() == 1
|
||||
assert pytest_wrapped_e.type == SystemExit
|
||||
assert pytest_wrapped_e.value.code == 1
|
||||
out, err = capsys.readouterr()
|
||||
assert re.search(r'Warning: No Meshtastic devices detected', out, re.MULTILINE)
|
||||
assert err == ''
|
||||
|
||||
@@ -65,21 +65,12 @@ def test_smoke1_pos_fields():
|
||||
assert return_value == 0
|
||||
|
||||
|
||||
@pytest.mark.smoke1
|
||||
def test_smoke1_test_no_arg():
|
||||
"""Test --test
|
||||
Note: Test without arg.
|
||||
"""
|
||||
return_value, _ = subprocess.getstatusoutput('meshtastic --test')
|
||||
assert return_value == 2
|
||||
|
||||
|
||||
@pytest.mark.smoke1
|
||||
def test_smoke1_test_with_arg_but_no_hardware():
|
||||
"""Test --test
|
||||
Note: Since only one device is connected, it will not do much.
|
||||
"""
|
||||
return_value, out = subprocess.getstatusoutput('meshtastic --test 5')
|
||||
return_value, out = subprocess.getstatusoutput('meshtastic --test')
|
||||
assert re.search(r'^Warning: Must have at least two devices', out, re.MULTILINE)
|
||||
assert return_value == 1
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ def test_smoke2_info():
|
||||
@pytest.mark.smoke2
|
||||
def test_smoke2_test():
|
||||
"""Test --test"""
|
||||
return_value, out = subprocess.getstatusoutput('meshtastic --test 5')
|
||||
return_value, out = subprocess.getstatusoutput('meshtastic --test')
|
||||
assert re.search(r'Writing serial debugging', out, re.MULTILINE)
|
||||
assert re.search(r'Ports opened', out, re.MULTILINE)
|
||||
assert re.search(r'Running 5 tests', out, re.MULTILINE)
|
||||
|
||||
@@ -175,6 +175,7 @@ def our_exit(message, return_value = 1):
|
||||
|
||||
def support_info():
|
||||
"""Print out info that is helping in support of the cli."""
|
||||
print('')
|
||||
print('If having issues with meshtastic cli or python library')
|
||||
print('or wish to make feature requests, visit:')
|
||||
print('https://github.com/meshtastic/Meshtastic-python/issues')
|
||||
@@ -183,10 +184,11 @@ def support_info():
|
||||
print(' Platform: {0}'.format(platform.platform()))
|
||||
print(' Release: {0}'.format(platform.uname().release))
|
||||
print(' Machine: {0}'.format(platform.uname().machine))
|
||||
print(' Encoding (stdin): {0}'.format(sys.stdin.encoding))
|
||||
print(' Encoding (stdout): {0}'.format(sys.stdout.encoding))
|
||||
print(' meshtastic: v{0}'.format(pkg_resources.require('meshtastic')[0].version))
|
||||
print(' Executable: {0}'.format(sys.argv[0]))
|
||||
print(' Python: {0} {1} {2}'.format(platform.python_version(),
|
||||
platform.python_implementation(), platform.python_compiler()))
|
||||
print('')
|
||||
print('Please add the output from the command: meshtastic --info')
|
||||
print('')
|
||||
|
||||
Reference in New Issue
Block a user