A Python port of the Invisible Internet Project (I2P)
at main 222 lines 7.2 kB view raw
1"""Tests for I2NP message routing — InboundMessageHandler, OutboundMessageRouter, MessageDispatcher.""" 2 3import struct 4 5import pytest 6 7 8class TestInboundMessageHandlerRegistration: 9 def test_register_and_dispatch_custom_handler(self): 10 from i2p_data.message_router import InboundMessageHandler 11 12 handler = InboundMessageHandler() 13 14 def custom(payload: bytes) -> bytes: 15 return payload[::-1] 16 17 handler.register(99, custom) 18 result = handler.handle(99, b"abc") 19 assert result == b"cba" 20 21 def test_handle_returns_none_for_unregistered_type(self): 22 from i2p_data.message_router import InboundMessageHandler 23 24 handler = InboundMessageHandler() 25 result = handler.handle(255, b"anything") 26 assert result is None 27 28 29class TestInboundDatabaseStoreAndLookup: 30 def test_store_and_lookup(self): 31 from i2p_data.message_router import InboundMessageHandler 32 33 handler = InboundMessageHandler() 34 key = b"\x01" * 32 35 value = b"router info data" 36 payload = key + value 37 handler.on_database_store(payload) 38 39 result = handler.on_database_lookup(key) 40 assert result == value 41 42 def test_lookup_missing_key_returns_none(self): 43 from i2p_data.message_router import InboundMessageHandler 44 45 handler = InboundMessageHandler() 46 key = b"\x02" * 32 47 result = handler.on_database_lookup(key) 48 assert result is None 49 50 51class TestInboundDeliveryStatus: 52 def test_extract_message_id(self): 53 from i2p_data.message_router import InboundMessageHandler 54 55 handler = InboundMessageHandler() 56 msg_id = 0xDEADBEEF 57 payload = msg_id.to_bytes(4, "big") + b"\x00" * 8 58 result = handler.on_delivery_status(payload) 59 assert result == 0xDEADBEEF 60 61 def test_extract_message_id_zero(self): 62 from i2p_data.message_router import InboundMessageHandler 63 64 handler = InboundMessageHandler() 65 payload = (0).to_bytes(4, "big") + b"\x00" * 8 66 result = handler.on_delivery_status(payload) 67 assert result == 0 68 69 70class TestInboundTunnelData: 71 def test_extract_tunnel_id_and_data(self): 72 from i2p_data.message_router import InboundMessageHandler 73 74 handler = InboundMessageHandler() 75 tunnel_id = 42 76 data = b"tunnel payload here" 77 payload = tunnel_id.to_bytes(4, "big") + data 78 tid, tdata = handler.on_tunnel_data(payload) 79 assert tid == 42 80 assert tdata == data 81 82 def test_extract_tunnel_id_empty_data(self): 83 from i2p_data.message_router import InboundMessageHandler 84 85 handler = InboundMessageHandler() 86 payload = (100).to_bytes(4, "big") 87 tid, tdata = handler.on_tunnel_data(payload) 88 assert tid == 100 89 assert tdata == b"" 90 91 92class TestInboundGarlic: 93 def test_on_garlic_returns_single_clove(self): 94 from i2p_data.message_router import InboundMessageHandler 95 96 handler = InboundMessageHandler() 97 payload = b"garlic clove data" 98 cloves = handler.on_garlic(payload) 99 assert cloves == [payload] 100 101 102class TestInboundDefaultHandlers: 103 def test_default_handlers_registered(self): 104 from i2p_data.message_router import InboundMessageHandler 105 106 handler = InboundMessageHandler() 107 # DATABASE_STORE=1, DATABASE_LOOKUP=2, DELIVERY_STATUS=10, 108 # GARLIC=11, TUNNEL_DATA=18, TUNNEL_GATEWAY=19 109 assert 1 in handler._handlers 110 assert 2 in handler._handlers 111 assert 10 in handler._handlers 112 assert 11 in handler._handlers 113 assert 18 in handler._handlers 114 assert 19 in handler._handlers 115 116 117class TestOutboundMessageRouterLocal: 118 def test_route_local(self): 119 from i2p_data.message_router import OutboundMessageRouter 120 121 router = OutboundMessageRouter() 122 result = router.route(0, b"local payload") 123 assert result == {"type": "local", "payload": b"local payload"} 124 125 126class TestOutboundMessageRouterRouter: 127 def test_route_router(self): 128 from i2p_data.message_router import OutboundMessageRouter 129 130 router = OutboundMessageRouter() 131 rh = b"\xAA" * 32 132 result = router.route(1, b"data", router_hash=rh) 133 assert result == {"type": "router", "router_hash": rh, "payload": b"data"} 134 135 136class TestOutboundMessageRouterTunnel: 137 def test_route_tunnel(self): 138 from i2p_data.message_router import OutboundMessageRouter 139 140 router = OutboundMessageRouter() 141 gw = b"\xBB" * 32 142 result = router.route(2, b"tdata", tunnel_id=7, gateway=gw) 143 assert result == { 144 "type": "tunnel", 145 "tunnel_id": 7, 146 "gateway": gw, 147 "payload": b"tdata", 148 } 149 150 151class TestOutboundMessageRouterDestination: 152 def test_route_destination(self): 153 from i2p_data.message_router import OutboundMessageRouter 154 155 router = OutboundMessageRouter() 156 dest = b"\xCC" * 32 157 result = router.route(3, b"dest_data", destination=dest) 158 assert result == { 159 "type": "destination", 160 "destination": dest, 161 "payload": b"dest_data", 162 } 163 164 165class TestOutboundMessageRouterUnknown: 166 def test_route_unknown_raises_value_error(self): 167 from i2p_data.message_router import OutboundMessageRouter 168 169 router = OutboundMessageRouter() 170 with pytest.raises(ValueError, match="Unknown delivery type"): 171 router.route(99, b"payload") 172 173 174class TestMessageDispatcher: 175 def test_dispatch_inbound(self): 176 from i2p_data.message_router import ( 177 InboundMessageHandler, 178 MessageDispatcher, 179 OutboundMessageRouter, 180 ) 181 182 inbound = InboundMessageHandler() 183 outbound = OutboundMessageRouter() 184 dispatcher = MessageDispatcher(inbound, outbound) 185 186 # Dispatch delivery status (type 10) 187 msg_id = 0x12345678 188 payload = msg_id.to_bytes(4, "big") + b"\x00" * 8 189 result = dispatcher.dispatch_inbound(10, payload) 190 assert result == 0x12345678 191 192 def test_dispatch_outbound(self): 193 from i2p_data.message_router import ( 194 InboundMessageHandler, 195 MessageDispatcher, 196 OutboundMessageRouter, 197 ) 198 199 inbound = InboundMessageHandler() 200 outbound = OutboundMessageRouter() 201 dispatcher = MessageDispatcher(inbound, outbound) 202 203 result = dispatcher.dispatch_outbound(0, b"payload") 204 assert result == {"type": "local", "payload": b"payload"} 205 206 def test_register_inbound_handler(self): 207 from i2p_data.message_router import ( 208 InboundMessageHandler, 209 MessageDispatcher, 210 OutboundMessageRouter, 211 ) 212 213 inbound = InboundMessageHandler() 214 outbound = OutboundMessageRouter() 215 dispatcher = MessageDispatcher(inbound, outbound) 216 217 def my_handler(payload: bytes) -> str: 218 return "handled" 219 220 dispatcher.register_inbound_handler(200, my_handler) 221 result = dispatcher.dispatch_inbound(200, b"test") 222 assert result == "handled"