From 1eff35ce76db346b8163e3a19888c5c842d22a1a Mon Sep 17 00:00:00 2001 From: Jack Robison Date: Tue, 20 Feb 2018 13:47:14 -0500 Subject: [PATCH] update dht unit tests to use task.Clock --- lbrynet/tests/unit/dht/test_protocol.py | 109 +++++++++++++++--------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/lbrynet/tests/unit/dht/test_protocol.py b/lbrynet/tests/unit/dht/test_protocol.py index d616451d9..d10a5a5e7 100644 --- a/lbrynet/tests/unit/dht/test_protocol.py +++ b/lbrynet/tests/unit/dht/test_protocol.py @@ -1,33 +1,54 @@ import time import unittest -import twisted.internet.selectreactor - +from twisted.internet.task import Clock +from twisted.internet import defer import lbrynet.dht.protocol import lbrynet.dht.contact import lbrynet.dht.constants import lbrynet.dht.msgtypes from lbrynet.dht.error import TimeoutError from lbrynet.dht.node import Node, rpcmethod +from lbrynet.tests.mocks import listenUDP, resolve + +import logging + +log = logging.getLogger() class KademliaProtocolTest(unittest.TestCase): """ Test case for the Protocol class """ - def setUp(self): - 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) + udpPort = 9182 + 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): """ 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) - lbrynet.dht.protocol.reactor.run() + + d = defer.Deferred() + self._reactor.callLater(1, d.callback, True) + self._reactor.advance(1) + result = yield d + self.assertTrue(result) def testRPCTimeout(self): """ 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 def fake_ping(*args, **kwargs): time.sleep(lbrynet.dht.constants.rpcTimeout + 1) @@ -38,19 +59,18 @@ class KademliaProtocolTest(unittest.TestCase): real_attempts = lbrynet.dht.constants.rpcAttempts lbrynet.dht.constants.rpcAttempts = 1 lbrynet.dht.constants.rpcTimeout = 1 + 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 - 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)') - lbrynet.dht.protocol.reactor.listenUDP(9182, self.protocol) + self.node.start_listening() # 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): - self.assertEqual(type(err), TimeoutError) + self.assertEqual(err.type, TimeoutError) df.addErrback(check_timeout) @@ -61,20 +81,24 @@ class KademliaProtocolTest(unittest.TestCase): # See if the contact was removed due to the timeout 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.') df.addCallback(lambda _: reset_values()) # Stop the reactor if a result arrives (timeout or not) - df.addBoth(lambda _: lbrynet.dht.protocol.reactor.stop()) df.addCallback(lambda _: check_removed_contact()) - lbrynet.dht.protocol.reactor.run() + self._reactor.pump([1 for _ in range(20)]) def testRPCRequest(self): """ 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.error = None def handleError(f): @@ -87,16 +111,18 @@ class KademliaProtocolTest(unittest.TestCase): % (expectedResult, result) # Publish the "local" node on the network - lbrynet.dht.protocol.reactor.listenUDP(9182, self.protocol) + self.node.start_listening() # Simulate the RPC df = remoteContact.ping() df.addCallback(handleResult) 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) # 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, ' 'but the transaction is already done!') @@ -105,8 +131,12 @@ class KademliaProtocolTest(unittest.TestCase): Verifies that a RPC request for an existing but unpublished method is denied, and that the associated (remote) exception gets raised locally """ - remoteContact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.1', 9182, self.protocol) - self.node.addContact(remoteContact) + 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() + remote_contact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.2', 9182, self.node._protocol) + self.node.addContact(remote_contact) + self.error = None def handleError(f): @@ -123,24 +153,26 @@ class KademliaProtocolTest(unittest.TestCase): self.error = 'The remote method executed successfully, returning: "%s"; ' \ 'this RPC should not have been allowed.' % result - # Publish the "local" node on the network - lbrynet.dht.protocol.reactor.listenUDP(9182, self.protocol) + self.node.start_listening() + self._reactor.pump([1 for _ in range(10)]) # Simulate the RPC - df = remoteContact.not_a_rpc_function() + df = remote_contact.not_a_rpc_function() df.addCallback(handleResult) df.addErrback(handleError) - df.addBoth(lambda _: lbrynet.dht.protocol.reactor.stop()) - lbrynet.dht.protocol.reactor.run() + self._reactor.pump([1 for _ in range(10)]) self.failIf(self.error, self.error) # 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, ' 'but the transaction is already done!') def testRPCRequestArgs(self): """ Tests if an RPC requiring arguments is executed correctly """ - remoteContact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.1', 9182, self.protocol) - self.node.addContact(remoteContact) + 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() + remote_contact = lbrynet.dht.contact.Contact('2' * 48, '127.0.0.2', 9182, self.node._protocol) + self.node.addContact(remote_contact) self.error = None def handleError(f): @@ -153,15 +185,14 @@ class KademliaProtocolTest(unittest.TestCase): (expectedResult, result) # Publish the "local" node on the network - lbrynet.dht.protocol.reactor.listenUDP(9182, self.protocol) + self.node.start_listening() # Simulate the RPC - df = remoteContact.ping() + df = remote_contact.ping() df.addCallback(handleResult) df.addErrback(handleError) - df.addBoth(lambda _: lbrynet.dht.protocol.reactor.stop()) - lbrynet.dht.protocol.reactor.run() + self._reactor.pump([1 for _ in range(10)]) self.failIf(self.error, self.error) # 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, ' 'but the transaction is already done!')