import ctypes import socket from pybusmonitor1553.core.dispatcher import MessageDispatcher from pybusmonitor1553.lib1553.headers import UDP1553Header, UDP1553MessageHeader, CommandWordUnion from pybusmonitor1553.lib1553.constants import Subaddress def _make_packet_with_cw(sub_addr, transmit=False, data_len=64, udp_marker=None): cw = CommandWordUnion(rt_addr=0, sub_addr=sub_addr, word_count=0, transmit=transmit) msg_hdr = UDP1553MessageHeader(command_word_union=cw) udp_hdr = UDP1553Header() if udp_marker is not None: udp_hdr.marker1553 = udp_marker header_bytes = ctypes.string_at(ctypes.addressof(udp_hdr), ctypes.sizeof(udp_hdr)) msg_hdr_bytes = ctypes.string_at(ctypes.addressof(msg_hdr), ctypes.sizeof(msg_hdr)) data_bytes = b"\x00" * data_len return header_bytes + msg_hdr_bytes + data_bytes def test_invalid_magic_number_returns_none(): disp = MessageDispatcher() # Provide wrong marker raw = _make_packet_with_cw(int(Subaddress.RX_SETTINGS), transmit=False, udp_marker=0xFFFF) h, msg = disp.parse_packet(raw) assert h is None and msg is None def test_unknown_subaddress_returns_header_and_none(): disp = MessageDispatcher() # Use a subaddress not registered (0 is not in registry) raw = _make_packet_with_cw(0, transmit=False) h, msg = disp.parse_packet(raw) assert h is not None and msg is None def test_message_class_instantiation_exception_is_handled(monkeypatch): disp = MessageDispatcher() # Create a faulty class that raises on construction class Faulty: SUBADDRESS = int(Subaddress.RX_SETTINGS) IS_TRANSMIT = False def __init__(self, data): raise RuntimeError("boom") key = (int(Subaddress.RX_SETTINGS), False) # Replace registry entry with faulty disp._registry[key] = Faulty raw = _make_packet_with_cw(int(Subaddress.RX_SETTINGS), transmit=False) h, msg = disp.parse_packet(raw) assert h is not None and msg is None def test_udp_start_handles_socket_error(monkeypatch): # Monkeypatch socket.socket to raise on bind import socket as _socket class FakeSock: def __init__(self, *a, **k): pass def setsockopt(self, *a, **k): pass def bind(self, addr): raise OSError("bind failed") monkeypatch.setattr(_socket, 'socket', lambda *a, **k: FakeSock()) from pybusmonitor1553.core.network import UdpHandler h = UdpHandler(rx_ip='127.0.0.1', rx_port=0) # Should not raise h.start() assert not h._running def test_udp_send_handles_send_error(): from pybusmonitor1553.core.network import UdpHandler h = UdpHandler(rx_ip='127.0.0.1', rx_port=0) class BadSock: def sendto(self, data, addr): raise RuntimeError("send error") h._sock = BadSock() # Should not raise h.send(b'data') def test_receive_loop_handles_exceptions_and_exits(): from pybusmonitor1553.core.network import UdpHandler h = UdpHandler(rx_ip='127.0.0.1', rx_port=0) class ExplodingSock: def recvfrom(self, n): # set running False as side-effect then raise h._running = False raise RuntimeError("recv boom") h._sock = ExplodingSock() h._running = True # Run the loop; it should catch the exception and then exit h._receive_loop() assert not h._running