"""Tests for bidirectional forwarder — TDD: tests before implementation.""" import asyncio import pytest from i2p_apps.i2ptunnel.forwarder import forward, bridge def _make_streams(data: bytes = b""): """Create an in-memory StreamReader pre-loaded with data, and a StreamWriter backed by a transport.""" reader = asyncio.StreamReader() if data: reader.feed_data(data) reader.feed_eof() return reader class _CapturingTransport: """Minimal transport that captures written bytes.""" def __init__(self): self.data = bytearray() self._closing = False def write(self, data): self.data.extend(data) def is_closing(self): return self._closing def close(self): self._closing = True def get_extra_info(self, key, default=None): return default def _make_writer_pair(): """Return (writer, captured_bytes_transport).""" transport = _CapturingTransport() protocol = asyncio.StreamReaderProtocol(asyncio.StreamReader()) writer = asyncio.StreamWriter(transport, protocol, asyncio.StreamReader(), asyncio.get_event_loop()) return writer, transport class TestForward: @pytest.mark.asyncio async def test_forward_copies_data(self): reader = _make_streams(b"hello world") writer, transport = _make_writer_pair() await forward(reader, writer) assert bytes(transport.data) == b"hello world" @pytest.mark.asyncio async def test_forward_handles_empty(self): reader = _make_streams(b"") writer, transport = _make_writer_pair() await forward(reader, writer) assert bytes(transport.data) == b"" @pytest.mark.asyncio async def test_forward_large_data(self): data = b"x" * 50000 reader = _make_streams(data) writer, transport = _make_writer_pair() await forward(reader, writer) assert bytes(transport.data) == data class TestBridge: @pytest.mark.asyncio async def test_bridge_bidirectional(self): """Data flows in both directions.""" # A->B: reader_a has data, writer_b captures reader_a = _make_streams(b"from-a") writer_b, transport_b = _make_writer_pair() # B->A: reader_b has data, writer_a captures reader_b = _make_streams(b"from-b") writer_a, transport_a = _make_writer_pair() await bridge(reader_a, writer_a, reader_b, writer_b) assert bytes(transport_b.data) == b"from-a" assert bytes(transport_a.data) == b"from-b" @pytest.mark.asyncio async def test_bridge_one_side_empty(self): reader_a = _make_streams(b"payload") writer_b, transport_b = _make_writer_pair() reader_b = _make_streams(b"") writer_a, transport_a = _make_writer_pair() await bridge(reader_a, writer_a, reader_b, writer_b) assert bytes(transport_b.data) == b"payload" assert bytes(transport_a.data) == b""