Tribler/py-ipv8

Errors in unit tests when running with IPv6 enabled

qstokkink opened this issue · 2 comments

When running the unit tests with TEST_IPV8_WITH_IPV6=1 set, the following errors sometimes appear.

FAIL: test_full_protocol (ipv8.test.dht.test_community.TestDHTCommunityXL.test_full_protocol)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\py-ipv8\ipv8\test\base.py", line 189, in _callTearDown
    self._callAsync(self.tearDown)
  File "C:\Python311\Lib\unittest\async_case.py", line 104, in _callAsync
    return self._asyncioRunner.run(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\test\base.py", line 279, in tearDown
    raise self._uncaught_async_failure["exception"]
  File "C:\py-ipv8\ipv8\test\mocking\endpoint.py", line 23, in crash_event_loop
    raise forwarded_exception
  File "C:\Python311\Lib\asyncio\events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "C:\py-ipv8\ipv8\messaging\interfaces\endpoint.py", line 89, in notify_listeners
    self._deliver_later(listener, packet)
  File "C:\py-ipv8\ipv8\messaging\interfaces\endpoint.py", line 79, in _deliver_later
    listener.on_packet(packet)
  File "C:\py-ipv8\ipv8\test\base.py", line 39, in _on_packet_fragile_cb
    result = self.decode_map[packet[1][22]](*packet)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\lazy_community.py", line 172, in wrapper
    return func(self, source_address, *unpacked)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\community.py", line 564, in on_new_puncture_request
    self.on_puncture_request(source_address, dist, payload, True)
  File "C:\py-ipv8\ipv8\community.py", line 580, in on_puncture_request
    self.endpoint.send(target, packet)
  File "C:\py-ipv8\ipv8\test\mocking\endpoint.py", line 85, in send
    raise e
AssertionError: Attempted to send data to unregistered address UDPv6Address(ip='515b:a64c:d5e6:9a78:7:2c0d:b4b4:29', port=25622)
FAIL: test_tunnel_endpoint_anon (ipv8.test.messaging.anonymization.test_community.TestTunnelCommunity.test_tunnel_endpoint_anon)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\py-ipv8\ipv8\test\base.py", line 189, in _callTearDown
    self._callAsync(self.tearDown)
  File "C:\Python311\Lib\unittest\async_case.py", line 104, in _callAsync
    return self._asyncioRunner.run(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\test\messaging\anonymization\test_community.py", line 66, in tearDown
    return await super().tearDown()
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\test\base.py", line 279, in tearDown
    raise self._uncaught_async_failure["exception"]
  File "C:\py-ipv8\ipv8\test\mocking\endpoint.py", line 23, in crash_event_loop
    raise forwarded_exception
  File "C:\Python311\Lib\asyncio\events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "C:\py-ipv8\ipv8\messaging\interfaces\endpoint.py", line 89, in notify_listeners
    self._deliver_later(listener, packet)
  File "C:\py-ipv8\ipv8\messaging\interfaces\endpoint.py", line 79, in _deliver_later
    listener.on_packet(packet)
  File "C:\py-ipv8\ipv8\test\base.py", line 39, in _on_packet_fragile_cb
    result = self.decode_map[packet[1][22]](*packet)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\lazy_community.py", line 172, in wrapper
    return func(self, source_address, *unpacked)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\community.py", line 564, in on_new_puncture_request
    self.on_puncture_request(source_address, dist, payload, True)
  File "C:\py-ipv8\ipv8\community.py", line 580, in on_puncture_request
    self.endpoint.send(target, packet)
  File "C:\py-ipv8\ipv8\test\mocking\endpoint.py", line 85, in send
    raise e
AssertionError: Attempted to send data to unregistered address UDPv6Address(ip='4:ef5d:bced:c9d5:53bd:1093:6368:a42d', port=30931)

I set up the TestDHTCommunityXL.test_full_protocol to run until failure and I added the following print statement to debug:

diff --git a/ipv8/dht/community.py b/ipv8/dht/community.py
index 1a23252..26b5ca9 100644
--- a/ipv8/dht/community.py
+++ b/ipv8/dht/community.py
@@ -680,6 +680,7 @@ class DHTCommunity(Community):
             nodes = routing_table.closest_nodes(payload.target, exclude_node=node, max_nodes=MAX_NODES_IN_FIND)
             # Send puncture request to the closest node
             if nodes:
+                print(self.endpoint.wan_address, "FIND REQUEST", nodes[0].address)
                 packet = self.create_puncture_request(payload.lan_address, peer.address, payload.identifier)
                 self.endpoint.send(nodes[0].address, packet)

This led to the following output:

Executing <Task pending name='Task-91' coro=<TestDHTCommunityXL.test_full_protocol() running at C:\py-ipv8\ipv8\test\dht\test_community.py:263> wait_for=<Future pending cb=[Task.task_wakeup()] created at C:\Python311\Lib\asyncio\base_events.py:427> cb=[_run_until_complete_cb() at C:\Python311\Lib\asyncio\base_events.py:180] created at C:\Python311\Lib\asyncio\runners.py:100> took 0.187 seconds
UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394) FIND REQUEST UDPv6Address(ip='ad2c:5117:7221:890:79e6:56fb:9b52:88ee', port=64743)
UDPv6Address(ip='ad2c:5117:7221:890:79e6:56fb:9b52:88ee', port=64743) FIND REQUEST UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394)
UDPv6Address(ip='462f:4942:a1d4:3b25:e70e:da4:a194:a2a1', port=34912) FIND REQUEST UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394)
UDPv6Address(ip='326a:da25:6584:6d6e:6515:cc22:813e:6ec9', port=52770) FIND REQUEST UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394)
UDPv6Address(ip='326a:da25:6584:6d6e:6515:cc22:813e:6ec9', port=52770) FIND REQUEST UDPv6Address(ip='1434:5d18:bff1:c26:fc6e:f7bb:bab1:da31', port=53142)
UDPv6Address(ip='326a:da25:6584:6d6e:6515:cc22:813e:6ec9', port=52770) FIND REQUEST UDPv6Address(ip='d4c3:905e:26da:7089:151e:60bd:2614:17e3', port=34691)
UDPv6Address(ip='326a:da25:6584:6d6e:6515:cc22:813e:6ec9', port=52770) FIND REQUEST UDPv6Address(ip='e0f9:6301:2907:422b:86eb:1080:7f7:f55b', port=31860)
UDPv6Address(ip='326a:da25:6584:6d6e:6515:cc22:813e:6ec9', port=52770) FIND REQUEST UDPv6Address(ip='902c:1dad:6a54:52fc:14b1:1f93:85e5:5af6', port=38518)
UDPv6Address(ip='1434:5d18:bff1:c26:fc6e:f7bb:bab1:da31', port=53142) FIND REQUEST UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394)
UDPv6Address(ip='d4c3:905e:26da:7089:151e:60bd:2614:17e3', port=34691) FIND REQUEST UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394)
UDPv6Address(ip='e0f9:6301:2907:422b:86eb:1080:7f7:f55b', port=31860) FIND REQUEST UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394)
UDPv6Address(ip='902c:1dad:6a54:52fc:14b1:1f93:85e5:5af6', port=38518) FIND REQUEST UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394)
UDPv6Address(ip='902c:1dad:6a54:52fc:14b1:1f93:85e5:5af6', port=38518) FIND REQUEST UDPv6Address(ip='8671:b266:4235:5c34:787c:e249:4529:d47b', port=59520)
UDPv6Address(ip='8671:b266:4235:5c34:787c:e249:4529:d47b', port=59520) FIND REQUEST UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394)
UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621) FIND REQUEST UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394)
UDPv6Address(ip='300d:9263:fc63:3a2e:366b:d042:53fd:a478', port=26394) FIND REQUEST UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)
UDPv6Address(ip='ad2c:5117:7221:890:79e6:56fb:9b52:88ee', port=64743) FIND REQUEST UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)
UDPv6Address(ip='462f:4942:a1d4:3b25:e70e:da4:a194:a2a1', port=34912) FIND REQUEST UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)
UDPv6Address(ip='462f:4942:a1d4:3b25:e70e:da4:a194:a2a1', port=34912) FIND REQUEST UDPv6Address(ip='326a:da25:6584:6d6e:6515:cc22:813e:6ec9', port=52770)
UDPv6Address(ip='462f:4942:a1d4:3b25:e70e:da4:a194:a2a1', port=34912) FIND REQUEST UDPv6Address(ip='1434:5d18:bff1:c26:fc6e:f7bb:bab1:da31', port=53142)
UDPv6Address(ip='462f:4942:a1d4:3b25:e70e:da4:a194:a2a1', port=34912) FIND REQUEST UDPv6Address(ip='d4c3:905e:26da:7089:151e:60bd:2614:17e3', port=34691)
UDPv6Address(ip='462f:4942:a1d4:3b25:e70e:da4:a194:a2a1', port=34912) FIND REQUEST UDPv6Address(ip='e0f9:6301:2907:422b:86eb:1080:7f7:f55b', port=31860)
UDPv6Address(ip='326a:da25:6584:6d6e:6515:cc22:813e:6ec9', port=52770) FIND REQUEST UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)
UDPv6Address(ip='1434:5d18:bff1:c26:fc6e:f7bb:bab1:da31', port=53142) FIND REQUEST UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)
UDPv6Address(ip='d4c3:905e:26da:7089:151e:60bd:2614:17e3', port=34691) FIND REQUEST UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)
UDPv6Address(ip='e0f9:6301:2907:422b:86eb:1080:7f7:f55b', port=31860) FIND REQUEST UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)
UDPv6Address(ip='e0f9:6301:2907:422b:86eb:1080:7f7:f55b', port=31860) FIND REQUEST UDPv6Address(ip='902c:1dad:6a54:52fc:14b1:1f93:85e5:5af6', port=38518)
UDPv6Address(ip='902c:1dad:6a54:52fc:14b1:1f93:85e5:5af6', port=38518) FIND REQUEST UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)

Failure
Traceback (most recent call last):
  File "C:\py-ipv8\ipv8\test\base.py", line 189, in _callTearDown
    self._callAsync(self.tearDown)
  File "C:\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\test\base.py", line 279, in tearDown
    raise self._uncaught_async_failure["exception"]
  File "C:\py-ipv8\ipv8\test\mocking\endpoint.py", line 23, in crash_event_loop
    raise forwarded_exception
  File "C:\Python311\Lib\asyncio\events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "C:\py-ipv8\ipv8\messaging\interfaces\endpoint.py", line 89, in notify_listeners
    self._deliver_later(listener, packet)
  File "C:\py-ipv8\ipv8\messaging\interfaces\endpoint.py", line 79, in _deliver_later
    listener.on_packet(packet)
  File "C:\py-ipv8\ipv8\test\base.py", line 39, in _on_packet_fragile_cb
    result = self.decode_map[packet[1][22]](*packet)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\lazy_community.py", line 172, in wrapper
    return func(self, source_address, *unpacked)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\py-ipv8\ipv8\community.py", line 564, in on_new_puncture_request
    self.on_puncture_request(source_address, dist, payload, True)
  File "C:\py-ipv8\ipv8\community.py", line 580, in on_puncture_request
    self.endpoint.send(target, packet)
  File "C:\py-ipv8\ipv8\test\mocking\endpoint.py", line 85, in send
    raise e
AssertionError: Attempted to send data to unregistered address UDPv6Address(ip='b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)

At this point, my intuition (this may be wrong) is that the reported IP strings are not an exact match and that this is causing the error:

UDPv6Address(ip='0b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)
UDPv6Address(ip='b:9529:bf07:f953:3086:af1:a14a:41d3', port=37621)

Confirmed that this test always fails if I change the following line:

b0 = random.randint(0, 65535)

to be:

b0 = 11

Update: actually, setting any of these values [b0 .. b7] to 11 will cause the test to fail.