modjam/tests/test_config.py
Alec Perkins 0f478bf720 Implement test/control stations, simulator, tests
Adds the modjam package: a MeshCore-backed test station service for
Pi (IDLE + RUNNING states, cuesheet-driven), a control station REPL
for the Mac, and a UDP simulator that swaps in for the radio when
SIMULATOR=true (drops cross-config packets and a configurable
fraction of test-payload datagrams to mimic real radio loss).
docker-compose runs three sim stations + control on a bridge net.
TSV log format matches the reference traces.

Pytest suite covers protocol codec, cuesheet builder, TSV logger,
config loader, and UDP radio packet routing/loss; .forgejo/workflows
runs it on push to main and on PRs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 21:27:41 -04:00

63 lines
1.5 KiB
Python

import json
import pytest
from modjam.config import StationConfig
SAMPLE = {
"this_station_name": "A",
"channel_name": "modjam",
"channel_psk": "MTIzNGFiY2RlZmdoaWprbA==",
"idle_heartbeat_min": 2,
"control_radio": {
"frequency_mhz": 915.125,
"bandwidth_khz": 500,
"spread_factor": 12,
"coding_rate": 8,
"tx_power_dbm": 22,
},
"data_radio": {
"frequency_mhz": 915.125,
"bandwidth_khz": 500,
"spread_factor": 7,
"coding_rate": 5,
"tx_power_dbm": 1,
},
}
def _write(tmp_path, data):
p = tmp_path / "modjam-config.json"
p.write_text(json.dumps(data))
return p
def test_load_full_config(tmp_path):
cfg = StationConfig.load(_write(tmp_path, SAMPLE))
assert cfg.this_station_name == "A"
assert cfg.idle_heartbeat_min == 2
assert cfg.control_radio.spread_factor == 12
assert cfg.data_radio is not None
assert cfg.data_radio.tx_power_dbm == 1
def test_load_defaults_heartbeat(tmp_path):
d = dict(SAMPLE)
d.pop("idle_heartbeat_min")
cfg = StationConfig.load(_write(tmp_path, d))
assert cfg.idle_heartbeat_min == 15
def test_load_without_data_radio(tmp_path):
d = dict(SAMPLE)
d.pop("data_radio")
cfg = StationConfig.load(_write(tmp_path, d))
assert cfg.data_radio is None
def test_load_missing_required(tmp_path):
d = dict(SAMPLE)
d.pop("channel_name")
with pytest.raises(KeyError):
StationConfig.load(_write(tmp_path, d))