import time from progpib.exceptions import TransportClosed, TransportTimeout from progpib.transport import EthernetTransport def test_read_line_reassembles_split_recv(mock_server): def handler(conn): conn.sendall(b"hello, wo") time.sleep(0.05) conn.sendall(b"rld\n") time.sleep(0.2) server = mock_server(handler) transport = EthernetTransport(server.host, server.port) transport.open() try: line = transport.read_line(timeout=2.0) assert line == b"hello, world" finally: transport.close() def test_read_line_strips_crlf(mock_server): def handler(conn): conn.sendall(b"line one\r\n") time.sleep(0.2) server = mock_server(handler) transport = EthernetTransport(server.host, server.port) transport.open() try: assert transport.read_line(timeout=2.0) == b"line one" finally: transport.close() def test_read_line_times_out_with_no_data(mock_server): def handler(conn): time.sleep(0.5) server = mock_server(handler) transport = EthernetTransport(server.host, server.port) transport.open() try: try: transport.read_line(timeout=0.1) assert False, "expected TransportTimeout" except TransportTimeout: pass finally: transport.close() def test_read_until_quiet_stops_after_idle_gap(mock_server): def handler(conn): conn.sendall(b"abc") time.sleep(0.05) conn.sendall(b"def") time.sleep(0.5) # long gap -- read_until_quiet should stop before this conn.sendall(b"ghi") server = mock_server(handler) transport = EthernetTransport(server.host, server.port) transport.open() try: data = transport.read_until_quiet(timeout=2.0, idle=0.2) assert data == b"abcdef" finally: transport.close() def test_read_until_quiet_returns_empty_with_no_data(mock_server): def handler(conn): time.sleep(0.3) server = mock_server(handler) transport = EthernetTransport(server.host, server.port) transport.open() try: assert transport.read_until_quiet(timeout=0.15) == b"" finally: transport.close() def test_recv_raises_closed_on_peer_disconnect(mock_server): def handler(conn): conn.close() server = mock_server(handler) transport = EthernetTransport(server.host, server.port) transport.open() try: time.sleep(0.1) try: transport.read_line(timeout=1.0) assert False, "expected TransportClosed" except TransportClosed: pass finally: transport.close()