Improving the network communication #4

Merged
PeterSurda merged 12 commits from lee.miller/MiNode:network into v0.3 2024-07-15 07:58:57 +02:00
Showing only changes of commit 5ca6e8a3e3 - Show all commits

View File

@ -5,6 +5,7 @@ import random
import unittest import unittest
import tempfile import tempfile
import time import time
from contextlib import contextmanager
from minode import connection, main, shared from minode import connection, main, shared
from minode.manager import Manager from minode.manager import Manager
@ -15,6 +16,21 @@ logging.basicConfig(
format='[%(asctime)s] [%(levelname)s] %(message)s') format='[%(asctime)s] [%(levelname)s] %(message)s')
@contextmanager
def time_offset(offset):
"""
Replace time.time() by a mock returning a constant value
with given offset from current time.
"""
started = time.time()
time_call = time.time
try:
time.time = lambda: started + offset
yield time_call
finally:
time.time = time_call
class TestNetwork(unittest.TestCase): class TestNetwork(unittest.TestCase):
"""Test case starting connections""" """Test case starting connections"""
@ -31,14 +47,17 @@ class TestNetwork(unittest.TestCase):
except FileNotFoundError: except FileNotFoundError:
pass pass
def test_connection(self): def _make_initial_nodes(self):
"""Check a normal connection - should receive objects"""
Manager.load_data() Manager.load_data()
self.assertGreaterEqual(len(shared.core_nodes), 3) self.assertGreaterEqual(len(shared.core_nodes), 3)
main.bootstrap_from_dns() main.bootstrap_from_dns()
self.assertGreaterEqual(len(shared.unchecked_node_pool), 3) self.assertGreaterEqual(len(shared.unchecked_node_pool), 3)
def test_connection(self):
"""Check a normal connection - should receive objects"""
self._make_initial_nodes()
started = time.time() started = time.time()
nodes = list(shared.core_nodes.union(shared.unchecked_node_pool)) nodes = list(shared.core_nodes.union(shared.unchecked_node_pool))
random.shuffle(nodes) random.shuffle(nodes)
@ -67,3 +86,33 @@ class TestNetwork(unittest.TestCase):
break break
else: else:
self.fail('Failed to establish a proper connection') self.fail('Failed to establish a proper connection')
def test_time_offset(self):
"""Assert the network bans for large time offset"""
def try_connect(nodes, timeout, call):
started = call()
for node in nodes:
c = connection.Connection(*node)
c.start()
while call() < started + timeout:
if c.status == 'fully_established':
return 'Established a connection'
if c.status in ('disconnected', 'failed'):
break
time.sleep(0.2)
else:
return 'Spent too much time trying to connect'
def time_offset_connections(nodes, offset):
"""Spoof time.time and open connections with given time offset"""
with time_offset(offset) as time_call:
result = try_connect(nodes, 200, time_call)
if result:
self.fail(result)
self._make_initial_nodes()
nodes = random.sample(
tuple(shared.core_nodes.union(shared.unchecked_node_pool)), 5)
time_offset_connections(nodes, 4000)
time_offset_connections(nodes, -4000)