Skip to content

Commit

Permalink
Refactor test_kademlia_protocol (WIP) ethereum#50
Browse files Browse the repository at this point in the history
  • Loading branch information
konradkonrad committed Jan 18, 2017
1 parent af0f587 commit 3aa6f11
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 31 deletions.
4 changes: 2 additions & 2 deletions devp2p/kademlia.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ def _check_idle_buckets(self):
rid = random.randint(bucket.start, bucket.end)
self.find_node(rid)

def _expected_pongs(self):
def _expected_pong_set(self):
return set(v[1] for v in self._expected_pongs.values())

def _process_surprising_pong(self, node, pingid):
Expand All @@ -544,7 +544,7 @@ def _process_surprising_pong(self, node, pingid):
"""
assert pingid not in self._expected_pongs
log.debug('surprising pong', remoteid=node,
expected=self._expected_pongs(), pingid=pingid.encode('hex')[:8])
expected=self._expected_pong_set(), pingid=pingid.encode('hex')[:8])
if pingid in self._deleted_pingids:
log.debug('surprising pong was deleted')
else:
Expand Down
101 changes: 72 additions & 29 deletions devp2p/tests/test_kademlia_protocol.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import random
import time
from devp2p.utils import int_to_big_endian
from devp2p import kademlia
import pytest
Expand Down Expand Up @@ -81,13 +82,15 @@ def routing_table(num_nodes=1000):
return routing


def get_wired_protocol():
@pytest.fixture(scope="function")
def proto(request):
this_node = random_node()
return kademlia.KademliaProtocol(this_node, WireMock(this_node))
proto = kademlia.KademliaProtocol(this_node, WireMock(this_node))
request.addfinalizer(proto.wire.empty)
return proto


def test_bootstrap():
proto = get_wired_protocol()
def test_bootstrap(proto):
wire = proto.wire
other = routing_table()
# lookup self
Expand All @@ -98,12 +101,11 @@ def test_bootstrap():
assert wire.messages == []


def test_setup():
def test_setup(proto):
"""
nodes connect to any peer and do a lookup for them selfs
"""

proto = get_wired_protocol()
wire = proto.wire
other = routing_table()

Expand Down Expand Up @@ -135,8 +137,7 @@ def test_setup():

@pytest.mark.timeout(5)
@pytest.mark.xfail
def test_find_node_timeout():
proto = get_wired_protocol()
def test_find_node_timeout(proto):
other = routing_table()
wire = proto.wire

Expand All @@ -163,20 +164,24 @@ def test_find_node_timeout():
assert wire.messages == []


def test_eviction():
proto = get_wired_protocol()
def test_eviction(proto):
proto.routing = routing_table(1000)
wire = proto.wire

# trigger node ping
node = proto.routing.neighbours(random_node())[0]
proto.ping(node)

# manually set bonding
node.ping_recv = True

msg = wire.poll(node)
assert msg[0] == 'ping'
assert wire.messages == []
proto.recv_pong(node, msg[2])
assert node.pong_recv is True
assert not node.bonded

assert node.bonded

# expect no message and that node is still there
assert wire.messages == []
Expand All @@ -188,8 +193,7 @@ def test_eviction():

@pytest.mark.timeout(5)
@pytest.mark.xfail
def test_eviction_timeout():
proto = get_wired_protocol()
def test_eviction_timeout(proto):
proto.routing = routing_table(1000)
wire = proto.wire

Expand All @@ -211,11 +215,10 @@ def test_eviction_timeout():


@pytest.mark.timeout(15)
def test_eviction_node_active():
def test_eviction_node_active(proto):
"""
active nodes (replying in time) should not be evicted
"""
proto = get_wired_protocol()
proto.routing = routing_table(10000) # set high, so add won't split
wire = proto.wire

Expand All @@ -228,8 +231,17 @@ def test_eviction_node_active():
bucket_nodes = bucket.nodes[:]
eviction_candidate = bucket.head

# manually set bonding successful
eviction_candidate.ping_recv = eviction_candidate.pong_recv = True
assert eviction_candidate.bonded

# create node to insert
node = random_node()

#manually set bonding successful
node.ping_recv = node.pong_recv = True
assert node.bonded

node.id = bucket.start + 1 # should not split
assert bucket.in_range(node)
assert bucket == proto.routing.bucket_by_node(node)
Expand All @@ -249,6 +261,7 @@ def test_eviction_node_active():
assert node not in proto.routing

# expect a ping to bucket.head
assert len(wire.messages)
msg = wire.poll(eviction_candidate)
assert msg[0] == 'ping'
assert msg[1] == proto.this_node
Expand Down Expand Up @@ -279,11 +292,10 @@ def test_eviction_node_active():

@pytest.mark.timeout(5)
@pytest.mark.xfail
def test_eviction_node_inactive():
def test_eviction_node_inactive(proto):
"""
active nodes (replying in time) should not be evicted
"""
proto = get_wired_protocol()
proto.routing = routing_table(10000) # set high, so add won't split
wire = proto.wire

Expand All @@ -296,9 +308,18 @@ def test_eviction_node_inactive():
bucket_nodes = bucket.nodes[:]
eviction_candidate = bucket.head

# manually set bonding successful
eviction_candidate.ping_recv = eviction_candidate.pong_recv = True
assert eviction_candidate.bonded

# create node to insert
node = random_node()
assert not node.bonded

# manually set bonding successful
node.ping_recv = node.pong_recv = True
assert node.bonded

node.id = bucket.start + 1 # should not split
assert bucket.in_range(node)
assert bucket == proto.routing.bucket_by_node(node)
Expand Down Expand Up @@ -344,11 +365,10 @@ def test_eviction_node_inactive():
assert eviction_candidate not in bucket.replacement_cache


def test_eviction_node_split():
def test_eviction_node_split(proto):
"""
active nodes (replying in time) should not be evicted
"""
proto = get_wired_protocol()
proto.routing = routing_table(1000) # set lpw, so we'll split
wire = proto.wire

Expand All @@ -361,9 +381,18 @@ def test_eviction_node_split():
bucket_nodes = bucket.nodes[:]
eviction_candidate = bucket.head

# manually set bonding successful
eviction_candidate.ping_recv = eviction_candidate.pong_recv = True
assert eviction_candidate.bonded

# create node to insert
node = random_node()
node.id = bucket.start + 1 # should not split

# manually set bonding successful
node.ping_recv = node.pong_recv = True

assert node.bonded
assert bucket.in_range(node)
assert bucket == proto.routing.bucket_by_node(node)

Expand All @@ -389,21 +418,33 @@ def test_eviction_node_split():
assert eviction_candidate == bucket.head


def test_ping_adds_sender():
p = get_wired_protocol()
assert len(p.routing) == 0
@pytest.mark.xfail(reason="ping is not sufficent!")
def test_ping_adds_sender(proto):
assert len(proto.routing) == 0
for i in range(10):
n = random_node()
proto.recv_ping(n, 'some id %d' % i)
assert len(proto.routing) == i + 1
proto.wire.empty()


@pytest.mark.xfail(reason="test not finished")
def test_ping_pong_adds_sender(proto):
assert len(proto.routing) == 0
for i in range(10):
n = random_node()
p.recv_ping(n, 'some id %d' % i)
assert len(p.routing) == i + 1
p.wire.empty()
proto.recv_ping(n, 'some id %d' % i)
proto._expected_pongs['some id %d' % i] = (time.time() + 1000, n, None)
proto.recv_pong(n, 'some id %d' % i)
assert len(proto.routing) == i + 1
proto.wire.empty()


@pytest.mark.skip
def test_two():
print
one = get_wired_protocol()
one = proto()
one.routing = routing_table(100)
two = get_wired_protocol()
two = proto()
wire = one.wire
assert one.this_node != two.this_node
two.ping(one.this_node)
Expand All @@ -421,12 +462,13 @@ def test_two():
wire.empty()


@pytest.mark.skip
def test_many(num_nodes=17):
WireMock.empty()
assert num_nodes >= kademlia.k_bucket_size + 1
protos = []
for i in range(num_nodes):
protos.append(get_wired_protocol())
protos.append(proto())
bootstrap = protos[0]
wire = bootstrap.wire

Expand All @@ -447,6 +489,7 @@ def test_many(num_nodes=17):
return protos


@pytest.mark.skip
def test_find_closest(num_nodes=50):
"""
assert, that nodes find really the closest of all nodes
Expand Down

0 comments on commit 3aa6f11

Please sign in to comment.