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
- 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.
100 lines
3.4 KiB
Python
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)
|