update dht unit tests to use task.Clock

This commit is contained in:
Jack Robison 2018-02-20 13:47:14 -05:00
parent 0ab5dd28bc
commit 1eff35ce76
No known key found for this signature in database
GPG key ID: DF25C68FE0239BB2

View file

@ -1,33 +1,54 @@
import time import time
import unittest import unittest
import twisted.internet.selectreactor from twisted.internet.task import Clock
from twisted.internet import defer
import lbrynet.dht.protocol import lbrynet.dht.protocol
import lbrynet.dht.contact import lbrynet.dht.contact
import lbrynet.dht.constants import lbrynet.dht.constants
import lbrynet.dht.msgtypes import lbrynet.dht.msgtypes
from lbrynet.dht.error import TimeoutError from lbrynet.dht.error import TimeoutError
from lbrynet.dht.node import Node, rpcmethod from lbrynet.dht.node import Node, rpcmethod
from lbrynet.tests.mocks import listenUDP, resolve
import logging
log = logging.getLogger()
class KademliaProtocolTest(unittest.TestCase): class KademliaProtocolTest(unittest.TestCase):
""" Test case for the Protocol class """ """ Test case for the Protocol class """
def setUp(self): udpPort = 9182
del lbrynet.dht.protocol.reactor
lbrynet.dht.protocol.reactor = twisted.internet.selectreactor.SelectReactor()
self.node = Node(node_id='1' * 48, udpPort=9182, externalIP="127.0.0.1")
self.protocol = lbrynet.dht.protocol.KademliaProtocol(self.node)
def setUp(self):
self._reactor = Clock()
self.node = Node(node_id='1' * 48, udpPort=self.udpPort, externalIP="127.0.0.1", listenUDP=listenUDP,
resolve=resolve, clock=self._reactor, callLater=self._reactor.callLater)
def tearDown(self):
del self._reactor
@defer.inlineCallbacks
def testReactor(self): def testReactor(self):
""" Tests if the reactor can start/stop the protocol correctly """ """ Tests if the reactor can start/stop the protocol correctly """
lbrynet.dht.protocol.reactor.listenUDP(0, self.protocol)
lbrynet.dht.protocol.reactor.callLater(0, lbrynet.dht.protocol.reactor.stop) d = defer.Deferred()
lbrynet.dht.protocol.reactor.run() self._reactor.callLater(1, d.callback, True)
self._reactor.advance(1)
result = yield d
self.assertTrue(result)
def testRPCTimeout(self): def testRPCTimeout(self):
""" Tests if a RPC message sent to a dead remote node times out correctly """ """ Tests if a RPC message sent to a dead remote node times out correctly """
dead_node = Node(node_id='2' * 48, udpPort=self.udpPort, externalIP="127.0.0.2", listenUDP=listenUDP,
resolve=resolve, clock=self._reactor, callLater=self._reactor.callLater)
dead_node.start_listening()
dead_node.stop()
self._reactor.pump([1 for _ in range(10)])
dead_contact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.2', 9182, self.node._protocol)
self.node.addContact(dead_contact)
@rpcmethod @rpcmethod
def fake_ping(*args, **kwargs): def fake_ping(*args, **kwargs):
time.sleep(lbrynet.dht.constants.rpcTimeout + 1) time.sleep(lbrynet.dht.constants.rpcTimeout + 1)
@ -38,19 +59,18 @@ class KademliaProtocolTest(unittest.TestCase):
real_attempts = lbrynet.dht.constants.rpcAttempts real_attempts = lbrynet.dht.constants.rpcAttempts
lbrynet.dht.constants.rpcAttempts = 1 lbrynet.dht.constants.rpcAttempts = 1
lbrynet.dht.constants.rpcTimeout = 1 lbrynet.dht.constants.rpcTimeout = 1
self.node.ping = fake_ping self.node.ping = fake_ping
deadContact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.1', 9182, self.protocol)
self.node.addContact(deadContact)
# Make sure the contact was added # Make sure the contact was added
self.failIf(deadContact not in self.node.contacts, self.failIf(dead_contact not in self.node.contacts,
'Contact not added to fake node (error in test code)') 'Contact not added to fake node (error in test code)')
lbrynet.dht.protocol.reactor.listenUDP(9182, self.protocol) self.node.start_listening()
# Run the PING RPC (which should raise a timeout error) # Run the PING RPC (which should raise a timeout error)
df = self.protocol.sendRPC(deadContact, 'ping', {}) df = self.node._protocol.sendRPC(dead_contact, 'ping', {})
def check_timeout(err): def check_timeout(err):
self.assertEqual(type(err), TimeoutError) self.assertEqual(err.type, TimeoutError)
df.addErrback(check_timeout) df.addErrback(check_timeout)
@ -61,20 +81,24 @@ class KademliaProtocolTest(unittest.TestCase):
# See if the contact was removed due to the timeout # See if the contact was removed due to the timeout
def check_removed_contact(): def check_removed_contact():
self.failIf(deadContact in self.node.contacts, self.failIf(dead_contact in self.node.contacts,
'Contact was not removed after RPC timeout; check exception types.') 'Contact was not removed after RPC timeout; check exception types.')
df.addCallback(lambda _: reset_values()) df.addCallback(lambda _: reset_values())
# Stop the reactor if a result arrives (timeout or not) # Stop the reactor if a result arrives (timeout or not)
df.addBoth(lambda _: lbrynet.dht.protocol.reactor.stop())
df.addCallback(lambda _: check_removed_contact()) df.addCallback(lambda _: check_removed_contact())
lbrynet.dht.protocol.reactor.run() self._reactor.pump([1 for _ in range(20)])
def testRPCRequest(self): def testRPCRequest(self):
""" Tests if a valid RPC request is executed and responded to correctly """ """ Tests if a valid RPC request is executed and responded to correctly """
remoteContact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.1', 9182, self.protocol)
remote_node = Node(node_id='2' * 48, udpPort=self.udpPort, externalIP="127.0.0.2", listenUDP=listenUDP,
resolve=resolve, clock=self._reactor, callLater=self._reactor.callLater)
remote_node.start_listening()
remoteContact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.2', 9182, self.node._protocol)
self.node.addContact(remoteContact) self.node.addContact(remoteContact)
self.error = None self.error = None
def handleError(f): def handleError(f):
@ -87,16 +111,18 @@ class KademliaProtocolTest(unittest.TestCase):
% (expectedResult, result) % (expectedResult, result)
# Publish the "local" node on the network # Publish the "local" node on the network
lbrynet.dht.protocol.reactor.listenUDP(9182, self.protocol) self.node.start_listening()
# Simulate the RPC # Simulate the RPC
df = remoteContact.ping() df = remoteContact.ping()
df.addCallback(handleResult) df.addCallback(handleResult)
df.addErrback(handleError) df.addErrback(handleError)
df.addBoth(lambda _: lbrynet.dht.protocol.reactor.stop())
lbrynet.dht.protocol.reactor.run() for _ in range(10):
self._reactor.advance(1)
self.failIf(self.error, self.error) self.failIf(self.error, self.error)
# The list of sent RPC messages should be empty at this stage # The list of sent RPC messages should be empty at this stage
self.failUnlessEqual(len(self.protocol._sentMessages), 0, self.failUnlessEqual(len(self.node._protocol._sentMessages), 0,
'The protocol is still waiting for a RPC result, ' 'The protocol is still waiting for a RPC result, '
'but the transaction is already done!') 'but the transaction is already done!')
@ -105,8 +131,12 @@ class KademliaProtocolTest(unittest.TestCase):
Verifies that a RPC request for an existing but unpublished Verifies that a RPC request for an existing but unpublished
method is denied, and that the associated (remote) exception gets method is denied, and that the associated (remote) exception gets
raised locally """ raised locally """
remoteContact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.1', 9182, self.protocol) remote_node = Node(node_id='2' * 48, udpPort=self.udpPort, externalIP="127.0.0.2", listenUDP=listenUDP,
self.node.addContact(remoteContact) resolve=resolve, clock=self._reactor, callLater=self._reactor.callLater)
remote_node.start_listening()
remote_contact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.2', 9182, self.node._protocol)
self.node.addContact(remote_contact)
self.error = None self.error = None
def handleError(f): def handleError(f):
@ -123,24 +153,26 @@ class KademliaProtocolTest(unittest.TestCase):
self.error = 'The remote method executed successfully, returning: "%s"; ' \ self.error = 'The remote method executed successfully, returning: "%s"; ' \
'this RPC should not have been allowed.' % result 'this RPC should not have been allowed.' % result
# Publish the "local" node on the network self.node.start_listening()
lbrynet.dht.protocol.reactor.listenUDP(9182, self.protocol) self._reactor.pump([1 for _ in range(10)])
# Simulate the RPC # Simulate the RPC
df = remoteContact.not_a_rpc_function() df = remote_contact.not_a_rpc_function()
df.addCallback(handleResult) df.addCallback(handleResult)
df.addErrback(handleError) df.addErrback(handleError)
df.addBoth(lambda _: lbrynet.dht.protocol.reactor.stop()) self._reactor.pump([1 for _ in range(10)])
lbrynet.dht.protocol.reactor.run()
self.failIf(self.error, self.error) self.failIf(self.error, self.error)
# The list of sent RPC messages should be empty at this stage # The list of sent RPC messages should be empty at this stage
self.failUnlessEqual(len(self.protocol._sentMessages), 0, self.failUnlessEqual(len(self.node._protocol._sentMessages), 0,
'The protocol is still waiting for a RPC result, ' 'The protocol is still waiting for a RPC result, '
'but the transaction is already done!') 'but the transaction is already done!')
def testRPCRequestArgs(self): def testRPCRequestArgs(self):
""" Tests if an RPC requiring arguments is executed correctly """ """ Tests if an RPC requiring arguments is executed correctly """
remoteContact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.1', 9182, self.protocol) remote_node = Node(node_id='2' * 48, udpPort=self.udpPort, externalIP="127.0.0.2", listenUDP=listenUDP,
self.node.addContact(remoteContact) resolve=resolve, clock=self._reactor, callLater=self._reactor.callLater)
remote_node.start_listening()
remote_contact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.2', 9182, self.node._protocol)
self.node.addContact(remote_contact)
self.error = None self.error = None
def handleError(f): def handleError(f):
@ -153,15 +185,14 @@ class KademliaProtocolTest(unittest.TestCase):
(expectedResult, result) (expectedResult, result)
# Publish the "local" node on the network # Publish the "local" node on the network
lbrynet.dht.protocol.reactor.listenUDP(9182, self.protocol) self.node.start_listening()
# Simulate the RPC # Simulate the RPC
df = remoteContact.ping() df = remote_contact.ping()
df.addCallback(handleResult) df.addCallback(handleResult)
df.addErrback(handleError) df.addErrback(handleError)
df.addBoth(lambda _: lbrynet.dht.protocol.reactor.stop()) self._reactor.pump([1 for _ in range(10)])
lbrynet.dht.protocol.reactor.run()
self.failIf(self.error, self.error) self.failIf(self.error, self.error)
# The list of sent RPC messages should be empty at this stage # The list of sent RPC messages should be empty at this stage
self.failUnlessEqual(len(self.protocol._sentMessages), 0, self.failUnlessEqual(len(self.node._protocol._sentMessages), 0,
'The protocol is still waiting for a RPC result, ' 'The protocol is still waiting for a RPC result, '
'but the transaction is already done!') 'but the transaction is already done!')