-
Notifications
You must be signed in to change notification settings - Fork 329
Initial implementation of simradio-based testing with a multi-node simulated mesh #946
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
ab14fb2
1cd1aed
9b89271
2f9b285
15438c8
ceca7b3
bffaff1
7950798
2281ea5
5760fb3
4339cda
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| name: Daily SimRadio Tests | ||
|
|
||
| on: | ||
| schedule: | ||
| - cron: 0 6 * * * | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| simradio_testing: | ||
| runs-on: ubuntu-latest | ||
| if: github.repository == 'meshtastic/meshtastic-python' | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Install Python 3 | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.12" | ||
| - name: Install meshtastic from local | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip3 install poetry | ||
| poetry install --all-extras --with dev | ||
| poetry run meshtastic --version | ||
| - name: Install meshtasticd (daily) from PPA | ||
| run: | | ||
| sudo add-apt-repository -y ppa:meshtastic/daily | ||
| sudo apt-get update | ||
| sudo apt-get install -y meshtasticd | ||
| - name: Run firmware smoke tests | ||
| run: poetry run pytest -m "smokevirt or smokemesh" -v | ||
| timeout-minutes: 15 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,87 @@ | |
| from meshtastic import mt_config | ||
|
|
||
| from ..mesh_interface import MeshInterface | ||
| from .firmware_harness import ( | ||
| CHAIN_TOPOLOGY, | ||
| DEFAULT_BASE_PORT, | ||
| SimMesh, | ||
| find_meshtasticd, | ||
| is_compatible_host, | ||
| ) | ||
| from .fw_helpers import set_region | ||
|
|
||
| # Use a different base port for the single-node fixture so it doesn't | ||
| # conflict with the multi-node mesh fixture. | ||
| SINGLE_NODE_BASE_PORT = DEFAULT_BASE_PORT + 100 | ||
|
|
||
|
|
||
| def _skip_firmware_if_unavailable() -> None: | ||
| """Skip the test when meshtasticd can't run on this host.""" | ||
| if not is_compatible_host(): | ||
| pytest.skip("meshtasticd firmware tests require Linux") | ||
| if find_meshtasticd() is None: | ||
| pytest.skip( | ||
| "meshtasticd not found — set MESHTASTICD_BIN or install it on PATH" | ||
| ) | ||
|
|
||
|
|
||
| @pytest.fixture(scope="function") | ||
| def firmware_node(): | ||
| """A single meshtasticd sim node for smokevirt tests. | ||
|
|
||
| Function-scoped so every test gets a freshly-erased node with no | ||
| state leaking from previous tests. This makes destructive commands | ||
| (``--reboot``, ``--set factory_reset true``) safe to run and lets | ||
| tests be order-independent. | ||
|
|
||
| Yields the SimNode instance. The node is booted with a fresh erased | ||
| config and listens on localhost at its TCP port. Region is set to US | ||
| so modem-preset tests work against firmware >= 2.8, which clamps | ||
| presets to the legal set for the current region. | ||
| """ | ||
| _skip_firmware_if_unavailable() | ||
| mesh = SimMesh(n_nodes=1, base_port=SINGLE_NODE_BASE_PORT) | ||
| mesh.start() | ||
| node = mesh.get_node(0) | ||
| set_region(node.port, "US") | ||
| # The region commit restarts the TCP listener, so reconnect the harness | ||
| # interface in case a test wants to use it directly. | ||
| if node.iface is not None: | ||
| try: | ||
| node.iface.close() | ||
| except Exception: # pylint: disable=broad-except | ||
| pass | ||
| node.connect() | ||
| yield node | ||
| mesh.stop() | ||
|
ianmcorvidae marked this conversation as resolved.
|
||
|
|
||
|
|
||
| @pytest.fixture(scope="function") | ||
| def firmware_mesh(): | ||
| """A 3-node chain (A-B-C) meshtasticd sim mesh for smokemesh tests. | ||
|
|
||
| Yields the SimMesh instance. Nodes are connected and the SIMULATOR_APP | ||
| packet bridge is running. Region is set to US for firmware >= 2.8 | ||
| compatibility, interfaces are reconnected after the region change, and | ||
| node DB convergence is awaited. | ||
| """ | ||
| _skip_firmware_if_unavailable() | ||
| mesh = SimMesh(n_nodes=3, topology=CHAIN_TOPOLOGY) | ||
| mesh.start() | ||
| for node in mesh.nodes: | ||
| set_region(node.port, "US") | ||
| # The region commit restarts each node's TCP listener, so reconnect the | ||
| # harness interfaces before waiting for convergence. | ||
| for node in mesh.nodes: | ||
| if node.iface is not None: | ||
| try: | ||
| node.iface.close() | ||
| except Exception: # pylint: disable=broad-except | ||
| pass | ||
| node.connect() | ||
| mesh.wait_for_convergence(timeout=30) | ||
| yield mesh | ||
| mesh.stop() | ||
|
Comment on lines
+35
to
+91
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Inspect SimMesh.start/stop and SimNode.start/close for partial-failure cleanup handling
fd firmware_harness.py meshtastic/tests --exec cat -n {}Repository: meshtastic/python Length of output: 14743 Handle partial startup cleanup in 🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| @pytest.fixture | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.