SXXXXXXX_PyBusMonitor1553/tests/test_more_coverage.py

108 lines
2.7 KiB
Python

import struct
import pytest
from enum import Enum
from pybusmonitor1553.lib1553.fields import Field, BitField, EnumField, ScaledField, ASCIIField
from pybusmonitor1553.lib1553.message_base import MessageBase
from pybusmonitor1553.lib1553.messages.msg_a3 import MsgA3
from pybusmonitor1553.lib1553.messages.msg_a5 import MsgA5
def test_descriptor_returns_self_on_class_access():
class M(MessageBase):
bf = BitField(word_index=0, start_bit=0, width=1)
# Accessing via class should return the descriptor itself
assert isinstance(M.bf, BitField)
def test_enumfield_auto_width_and_fallback():
class E(Enum):
A = 0
B = 1
C = 3
class M(MessageBase):
ef = EnumField(word_index=0, start_bit=0, enum_cls=E) # width auto
# Width auto-calculated to fit max value (3 -> 2 bits)
assert M.ef.width == 2
m = M()
# Set raw value directly to an undefined value (e.g., 2)
m.data[0] = 2 << (16 - (0 + M.ef.width))
# Should return raw int because 2 not in Enum
assert m.ef == 2
def test_asciifield_nonprintable_and_validation():
class M(MessageBase):
a = ASCIIField(word_index=0)
m = M()
# write a raw word with non-printable bytes 0x00 0x01
m._data[0] = (0 << 8) | 1
assert m.a == '??'
with pytest.raises(ValueError):
m.a = 'X' # too short
def test_message_base_pack_unpack_and_clamp():
class M(MessageBase):
pass
m = M()
# set some sample words
for i in range(32):
m._data[i] = i
packed = m.pack()
assert len(packed) == 64
# create raw with more than 32 words (e.g., 40 words)
extra = struct.pack('>40H', *list(range(40)))
m2 = M()
m2.unpack(extra)
# only first 32 should be loaded
assert m2._data[31] == 31
def test_msg_a3_25bit_signed_and_ascii():
m = MsgA3()
# positive raw
raw_25 = 0x00ABCDE
msw = (raw_25 >> 9) & 0xFFFF
lsw_fragment = raw_25 & 0x1FF
m._data[2] = msw
m._data[3] = (lsw_fragment << 7)
assert isinstance(m.wp1_latitude, float)
# negative value: set sign bit of 25-bit value
neg_raw = (1 << 24) | 12345
msw = (neg_raw >> 9) & 0xFFFF
lsw_fragment = neg_raw & 0x1FF
m._data[4] = msw
m._data[5] = (lsw_fragment << 7)
val = m.wp1_longitude
assert isinstance(val, float)
# ASCII fields
m.hpt_callsign_ab = 'AA'
assert m.hpt_callsign_ab == 'AA'
def test_msg_a5_32bit_signed_scaled_velocity():
m = MsgA5()
# build a negative 32-bit raw value
raw32 = (1 << 31) | 12345678 # sign bit set
msw = (raw32 >> 16) & 0xFFFF
lsw = raw32 & 0xFFFF
m._data[2] = msw
m._data[3] = lsw
expected = float((raw32 - (1 << 32)) * 3.81470e-6)
assert pytest.approx(m.velocity_x, rel=1e-9) == expected