forked from LBRYCommunity/lbry-sdk
update dht unit tests to use task.Clock
This commit is contained in:
parent
0ab5dd28bc
commit
1eff35ce76
1 changed files with 70 additions and 39 deletions
|
@ -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!')
|
||||||
|
|
Loading…
Add table
Reference in a new issue