import socket import types import pytest from target_simulator.utils import network class DummySocket: def __init__(self, fail_on_bind=False, rcvbuf=4096): self._closed = False self._fail_on_bind = fail_on_bind self._rcvbuf = rcvbuf self._timeout = None def getsockopt(self, level, optname): return self._rcvbuf def setsockopt(self, level, optname, value): # Simulate refusal if value is absurd (for edge test) if value > 10 * 1024 * 1024: raise OSError("too large") def bind(self, addr): if self._fail_on_bind: raise socket.error("bind failed") def recvfrom(self, bufsize): if self._timeout: raise socket.timeout() return b"data", ("127.0.0.1", 1234) def fileno(self): return -1 if self._closed else 3 def close(self): if self._closed: raise socket.error("already closed") self._closed = True def test_create_udp_socket_success(monkeypatch): dummy = DummySocket() def fake_socket(family, type_): return dummy monkeypatch.setattr(network.socket, "socket", fake_socket) s = network.create_udp_socket("127.0.0.1", 0) # Should return our dummy socket object assert s is dummy def test_create_udp_socket_bind_failure(monkeypatch): dummy = DummySocket(fail_on_bind=True) def fake_socket(family, type_): return dummy monkeypatch.setattr(network.socket, "socket", fake_socket) s = network.create_udp_socket("127.0.0.1", 0) # On bind failure implementation returns None assert s is None def test_create_udp_socket_buf_set_failure(monkeypatch): # Simulate setsockopt raising OSError when trying to set very large buffer dummy = DummySocket() def fake_socket(family, type_): return dummy # Also patch dummy.setsockopt to raise def bad_setsockopt(level, optname, value): raise OSError("no permission") dummy.setsockopt = bad_setsockopt monkeypatch.setattr(network.socket, "socket", fake_socket) # Should still return the socket even if buffer set fails s = network.create_udp_socket("127.0.0.1", 0) assert s is dummy def test_receive_udp_packet_success_and_timeout(monkeypatch): dummy = DummySocket() # Normal receive data, addr = network.receive_udp_packet(dummy) assert data == b"data" assert addr == ("127.0.0.1", 1234) # Simulate timeout dummy._timeout = True data, addr = network.receive_udp_packet(dummy) assert data is None and addr is None def test_receive_udp_packet_error(monkeypatch): class ErrSock(DummySocket): def recvfrom(self, bufsize): raise socket.error("recv failed") err = ErrSock() data, addr = network.receive_udp_packet(err) assert data is None and addr is None def test_close_udp_socket_open_and_closed(monkeypatch): dummy = DummySocket() # Open socket: fileno != -1 -> will call close dummy._closed = False network.close_udp_socket(dummy) assert dummy._closed is True # Now calling close on an already-closed socket should hit the debug branch # and not raise network.close_udp_socket(dummy) # should be no-op and not raise