J
2026-04-13 11:48:15 -04:00
|
|
|
from ria_toolkit_oss.agent import hardware
|
|
|
|
|
from ria_toolkit_oss.sdr import detect_available
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_detect_available_includes_mock():
|
|
|
|
|
drivers = detect_available()
|
|
|
|
|
assert "mock" in drivers
|
|
|
|
|
from ria_toolkit_oss.sdr.mock import MockSDR
|
|
|
|
|
|
|
|
|
|
assert drivers["mock"] is MockSDR
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_available_devices_sorted_list():
|
|
|
|
|
devices = hardware.available_devices()
|
|
|
|
|
assert isinstance(devices, list)
|
|
|
|
|
assert devices == sorted(devices)
|
|
|
|
|
assert "mock" in devices
|
|
|
|
|
|
|
|
|
|
|
J
2026-06-05 10:03:14 -04:00
|
|
|
def _device_names(hardware_list):
|
|
|
|
|
return {e["device"] for e in hardware_list}
|
|
|
|
|
|
|
|
|
|
|
J
2026-04-13 11:48:15 -04:00
|
|
|
def test_heartbeat_payload_shape():
|
|
|
|
|
p = hardware.heartbeat_payload()
|
|
|
|
|
assert p["type"] == "heartbeat"
|
|
|
|
|
assert p["status"] == "idle"
|
J
2026-06-05 10:03:14 -04:00
|
|
|
# hardware is now a list of rich dict entries.
|
|
|
|
|
assert "mock" in _device_names(p["hardware"])
|
J
2026-04-13 11:48:15 -04:00
|
|
|
assert "app_id" not in p
|
J
2026-04-16 11:13:43 -04:00
|
|
|
# New fields, default shape
|
|
|
|
|
assert p["capabilities"] == ["rx"]
|
|
|
|
|
assert p["tx_enabled"] is False
|
J
2026-04-13 11:48:15 -04:00
|
|
|
|
|
|
|
|
p2 = hardware.heartbeat_payload(status="streaming", app_id="abc")
|
|
|
|
|
assert p2["status"] == "streaming"
|
|
|
|
|
assert p2["app_id"] == "abc"
|
J
2026-04-16 11:13:43 -04:00
|
|
|
|
|
|
|
|
|
J
2026-06-05 10:03:14 -04:00
|
|
|
def test_detect_devices_entry_shape():
|
|
|
|
|
devices = hardware.detect_devices(use_cache=False)
|
|
|
|
|
assert isinstance(devices, list)
|
|
|
|
|
for entry in devices:
|
|
|
|
|
assert set(entry) >= {"device", "identifier", "label", "connected"}
|
|
|
|
|
assert isinstance(entry["device"], str)
|
|
|
|
|
# identifier round-trips through parse_ident: None or a string.
|
|
|
|
|
assert entry["identifier"] is None or isinstance(entry["identifier"], str)
|
|
|
|
|
mock = next(e for e in devices if e["device"] == "mock")
|
|
|
|
|
assert mock["label"] # has a human label
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_detect_devices_cache():
|
|
|
|
|
a = hardware.detect_devices(use_cache=False)
|
|
|
|
|
b = hardware.detect_devices(use_cache=True)
|
|
|
|
|
assert _device_names(a) == _device_names(b)
|
|
|
|
|
|
|
|
|
|
|
J
2026-04-16 11:13:43 -04:00
|
|
|
def test_heartbeat_payload_tx_capability_from_cfg():
|
|
|
|
|
from ria_toolkit_oss.agent.config import AgentConfig
|
|
|
|
|
|
|
|
|
|
p = hardware.heartbeat_payload(cfg=AgentConfig(tx_enabled=True))
|
|
|
|
|
assert p["capabilities"] == ["rx", "tx"]
|
|
|
|
|
assert p["tx_enabled"] is True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_heartbeat_payload_sessions_field():
|
|
|
|
|
sessions = {"rx": {"app_id": "a", "state": "streaming"}}
|
|
|
|
|
p = hardware.heartbeat_payload(status="streaming", app_id="a", sessions=sessions)
|
|
|
|
|
assert p["sessions"] == sessions
|
J
2026-04-16 15:12:56 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_heartbeat_payload_surfaces_tx_caps_when_enabled():
|
|
|
|
|
from ria_toolkit_oss.agent.config import AgentConfig
|
|
|
|
|
|
|
|
|
|
cfg = AgentConfig(
|
|
|
|
|
tx_enabled=True,
|
|
|
|
|
tx_max_gain_db=-10.0,
|
|
|
|
|
tx_max_duration_s=60.0,
|
|
|
|
|
tx_allowed_freq_ranges=[[2.4e9, 2.5e9], [5.7e9, 5.8e9]],
|
|
|
|
|
)
|
|
|
|
|
p = hardware.heartbeat_payload(cfg=cfg)
|
|
|
|
|
assert p["tx_max_gain_db"] == -10.0
|
|
|
|
|
assert p["tx_max_duration_s"] == 60.0
|
|
|
|
|
assert p["tx_allowed_freq_ranges"] == [[2.4e9, 2.5e9], [5.7e9, 5.8e9]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_heartbeat_payload_omits_caps_when_tx_disabled():
|
|
|
|
|
from ria_toolkit_oss.agent.config import AgentConfig
|
|
|
|
|
|
|
|
|
|
# Caps set but tx_enabled=False — don't leak them; they're only meaningful
|
|
|
|
|
# when the hub can attempt a tx_start.
|
|
|
|
|
cfg = AgentConfig(tx_enabled=False, tx_max_gain_db=-10.0)
|
|
|
|
|
p = hardware.heartbeat_payload(cfg=cfg)
|
|
|
|
|
assert "tx_max_gain_db" not in p
|
|
|
|
|
assert "tx_max_duration_s" not in p
|
|
|
|
|
assert "tx_allowed_freq_ranges" not in p
|