"""Tests for Transport bid integration (banlist, self-send, failure tracking).""" import asyncio from i2p_transport.manager import TransportManager from i2p_transport.transport_base import Transport, TransportBid, TransportStyle class MockTransport(Transport): """Transport that always succeeds or always fails.""" def __init__(self, succeed=True): self._succeed = succeed self._style = TransportStyle.NTCP2 @property def style(self): return self._style async def start(self): pass async def stop(self): pass async def bid(self, peer_hash): return TransportBid(latency_ms=10, transport=self) async def send(self, peer_hash, data): return self._succeed @property def current_address(self): return None @property def reachability(self): from i2p_transport.transport_base import ReachabilityStatus return ReachabilityStatus.OK @property def is_running(self): return True class MockBanlist: def __init__(self, banned=None): self._banned = set(banned or []) def is_banlisted(self, peer_hash): return peer_hash in self._banned def _run(coro): return asyncio.run(coro) def test_reject_self_send(): my_hash = b"\x01" * 32 tm = TransportManager(router_hash=my_hash) tm.register(MockTransport()) assert _run(tm.send(my_hash, b"data")) is False def test_reject_banlisted(): peer = b"\x02" * 32 banlist = MockBanlist(banned=[peer]) tm = TransportManager(banlist=banlist) tm.register(MockTransport()) assert _run(tm.send(peer, b"data")) is False def test_success_clears_failure(): peer = b"\x03" * 32 tm = TransportManager() tm.register(MockTransport(succeed=True)) assert _run(tm.send(peer, b"data")) is True assert tm._failed_counts.get(peer) is None def test_failure_tracking(): peer = b"\x04" * 32 tm = TransportManager() tm.register(MockTransport(succeed=False)) _run(tm.send(peer, b"data")) # fail 1 assert tm._failed_counts[peer] == 1 _run(tm.send(peer, b"data")) # fail 2 assert tm._failed_counts[peer] == 2 # Third attempt should be rejected (> 1 failures) assert _run(tm.send(peer, b"data")) is False def test_no_banlist_still_works(): tm = TransportManager() # no banlist, no router_hash tm.register(MockTransport()) assert _run(tm.send(b"\x05" * 32, b"data")) is True def test_clear_failed_count(): tm = TransportManager() peer = b"\x06" * 32 tm._failed_counts[peer] = 5 tm.clear_failed_count(peer) assert peer not in tm._failed_counts