121 lines
3.2 KiB
Python
121 lines
3.2 KiB
Python
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
|