Files
MeshChatX/tests/backend/test_fuzzing_telemetry.py
Sudo-Ivan e2586e9052
Some checks failed
CI / test-backend (push) Successful in 32s
CI / lint (push) Failing after 2m12s
CI / build-frontend (pull_request) Successful in 1m38s
Build and Publish Docker Image / build (pull_request) Has been skipped
CI / test-backend (pull_request) Successful in 24s
OSV-Scanner PR Scan / scan-pr (pull_request) Successful in 53s
CI / test-lang (pull_request) Successful in 1m15s
CI / lint (pull_request) Failing after 5m8s
CI / build-frontend (push) Successful in 9m46s
CI / test-lang (push) Successful in 9m48s
Tests / test (push) Successful in 13m32s
Tests / test (pull_request) Successful in 11m23s
Build Test / Build and Test (push) Successful in 15m56s
Build and Publish Docker Image / build-dev (pull_request) Successful in 13m42s
Build Test / Build and Test (pull_request) Successful in 16m9s
feat(tests): add comprehensive telemetry and interface tests
- Introduced new test files for telemetry functionality, including integration, fuzzing, and extended tests to ensure robustness and performance.
- Added tests for parsing LXMF display names and telemetry data, addressing potential bugs and ensuring correct handling of various input formats.
- Implemented performance tests for the InterfacesPage component, validating rendering efficiency with a large number of discovered interfaces.
- Enhanced existing tests for markdown rendering and link utilities to cover additional edge cases and improve stability.
2026-01-07 19:22:00 -06:00

100 lines
3.4 KiB
Python

from hypothesis import given, settings, strategies as st
from meshchatx.src.backend.telemetry_utils import Telemeter
# Strategies for telemetry data
st_lat_lon = st.floats(min_value=-90, max_value=90)
st_alt = st.floats(min_value=-10000, max_value=100000)
st_speed = st.floats(min_value=0, max_value=2000)
st_bearing = st.floats(min_value=0, max_value=360)
st_accuracy = st.floats(min_value=0, max_value=10000)
st_timestamp = st.integers(min_value=0, max_value=2**32 - 1)
@settings(deadline=None)
@given(
lat=st_lat_lon,
lon=st_lat_lon,
alt=st_alt,
speed=st_speed,
bearing=st_bearing,
acc=st_accuracy,
ts=st_timestamp,
)
def test_fuzz_pack_location(lat, lon, alt, speed, bearing, acc, ts):
packed = Telemeter.pack_location(lat, lon, alt, speed, bearing, acc, ts)
if packed is not None:
unpacked = Telemeter.unpack_location(packed)
if unpacked:
# Check for reasonable precision (we use 1e6 for lat/lon, 1e2 for others)
assert abs(unpacked["latitude"] - lat) < 0.000002
assert abs(unpacked["longitude"] - lon) < 0.000002
assert abs(unpacked["altitude"] - alt) < 0.02
assert abs(unpacked["speed"] - speed) < 0.02
assert abs(unpacked["bearing"] - bearing) < 0.02
assert abs(unpacked["accuracy"] - acc) < 0.02
assert unpacked["last_update"] == ts
@settings(deadline=None)
@given(
charge=st.integers(min_value=0, max_value=100),
charging=st.integers(min_value=0, max_value=1),
rssi=st.integers(min_value=-150, max_value=0),
snr=st.floats(min_value=-20, max_value=20),
q=st.integers(min_value=0, max_value=100),
)
def test_fuzz_full_telemetry_packing(charge, charging, rssi, snr, q):
battery = {"charge_percent": charge, "charging": charging}
physical_link = {"rssi": rssi, "snr": snr, "q": q}
packed = Telemeter.pack(battery=battery, physical_link=physical_link)
unpacked = Telemeter.from_packed(packed)
assert unpacked["battery"]["charge_percent"] == charge
assert unpacked["battery"]["charging"] == charging
assert unpacked["physical_link"]["rssi"] == rssi
assert abs(unpacked["physical_link"]["snr"] - snr) < 0.01
assert unpacked["physical_link"]["q"] == q
@settings(deadline=None)
@given(data=st.binary(min_size=0, max_size=2000))
def test_fuzz_from_packed_random_bytes(data):
# This should never crash
try:
Telemeter.from_packed(data)
except Exception:
pass
@settings(deadline=None)
@given(
commands=st.lists(
st.dictionaries(
keys=st.one_of(st.integers(), st.text()),
values=st.one_of(st.integers(), st.text(), st.floats(), st.booleans()),
),
max_size=10,
)
)
def test_fuzz_command_parsing(commands):
# This simulates how commands are handled in meshchat.py
processed_commands = []
for cmd in commands:
new_cmd = {}
for k, v in cmd.items():
try:
if isinstance(k, str):
if k.startswith("0x"):
new_cmd[int(k, 16)] = v
else:
new_cmd[int(k)] = v
else:
new_cmd[k] = v
except (ValueError, TypeError):
new_cmd[k] = v
processed_commands.append(new_cmd)
# Just ensure no crash
assert len(processed_commands) == len(commands)