def test_find_node_Received_sendsValidResponseMultipleNodes(self): # Create the protocol and populate its # routing table with nodes kresponder = Patched_KRPC_Responder() node_list = [] node_gen = lambda num: contact.Node(num, ("127.0.0.%d" % num, num)) for i in range(100): n = node_gen(i) if kresponder.routing_table.offer_node(n): node_list.append(n) querying_node = contact.Node(123, test_address) incoming_query = Query() incoming_query.rpctype = "find_node" incoming_query._from = querying_node.node_id incoming_query._transaction_id = 15 incoming_query.target_id = 777777 expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = 15 expected_response.rpctype = "find_node" node_list.sort(key = lambda node: node.distance(incoming_query.target_id)) node_list = node_list[:constants.k] expected_response.nodes = node_list kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response self.assertEquals(expected_response, actual_response)
def test_get_peers_Received_sendsValidResponseWithPeers(self): # Create the protocol and populate its # routing table with nodes kresponder = Patched_KRPC_Responder() peers = [("127.0.0.%d" % peer_num, peer_num) for peer_num in range(10)] incoming_query = Query() incoming_query.rpctype = "get_peers" incoming_query._from = 555 incoming_query._transaction_id = 15 # We have this target id in our routing table incoming_query.target_id = 77 expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = 15 expected_response.peers = peers expected_response.rpctype = "get_peers" ds = kresponder._datastore for peer in peers: ds[incoming_query.target_id].add(peer) kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response # Grab the autogenerated token and sort the peers to # match our expected order expected_response.token = actual_response.token ap = actual_response ap.peers = sorted(ap.peers, key=lambda (ip,port): port) actual_response.peers.sort(key = lambda (ip, port) : port) self.assertEquals(expected_response, actual_response)
def find_node(self, address, node_id, timeout=None): log.msg("make a find_node request to node(%s:%s)" % address) timeout = timeout or constants.rpctimeout query = Query() query.rpctype = "find_node" query.target_id = node_id return self.sendQuery(query, address, timeout)
def get_peers(self, address, target_id, timeout=None): log.msg("make a get_peers request to node(%s:%s)" % address) timeout = timeout or constants.rpctimeout query = Query() query.rpctype = "get_peers" query.target_id = target_id return self.sendQuery(query, address, timeout)
def setUp(self): _swap_out_reactor() q = Query() q._transaction_id = 50 q._from = 58 q.rpctype = "ping" self.query = q
def test_errback_InvalidKRPCError(self): # Make an invalid query query = Query() query.rpctype = "pingpong" d = self.k_messenger.sendQuery(query, address, timeout) self.assertFalse(self.query._transaction_id in self.k_messenger._transactions) # Cleanup the error d.addErrback(lambda failure: failure.trap(krpc_coder.InvalidKRPCError))
def test_errback_InvalidKRPCError(self): # Make an invalid query query = Query() query.rpctype = "pingpong" d = self.k_messenger.sendQuery(query, address, timeout) self.assertFalse( self.query._transaction_id in self.k_messenger._transactions) # Cleanup the error d.addErrback(lambda failure: failure.trap(krpc_coder.InvalidKRPCError))
class QueryTestCase(unittest.TestCase): def setUp(self): self.q = Query() self.q._transaction_id = 500 self.q._from = 27 self.q.rpctype = "ping" def test_build_response(self): nodes = None token = 8192 peers = None r = self.q.build_response(nodes, token, peers) q = self.q expected_r = Response(_transaction_id=q._transaction_id, rpctype=q.rpctype, nodes=nodes, token=token, peers=peers) self.assertEquals(expected_r, r) def test_build_error(self): code = 203 message = "Oops, error" e = self.q.build_error(code, message) q = self.q expected_e = Error(_transaction_id=q._transaction_id, code=code, message=message) self.assertEquals(expected_e, e) def test_repr(self): expected_repr = "<Query: _transaction_id=500 rpctype=ping _from=27>" self.assertEquals(expected_repr, repr(self.q)) def test__eq__(self): q1, q2 = self._gen_equal_announce_peers() self.assertEquals(q1, q2) def test__ne___(self): q1, q2 = self._gen_equal_announce_peers() q1._transaction_id = 88 q2._transaction_id = 66 self.assertNotEquals(q1, q2) def _gen_equal_announce_peers(self): q1 = Query() q2 = Query() q1._transaction_id = q2._transaction_id = 99 q1._from = q2._from = 55 q1.rpctype = q2.rpctype = "announce_peer" q1.token = q2.token = 13 q1.port = q2.port = 123 q1.target_id = q2.target_id = 66 self.assertEquals(q1, q2) return (q1, q2)
def _gen_equal_announce_peers(self): q1 = Query() q2 = Query() q1._transaction_id = q2._transaction_id = 99 q1._from = q2._from = 55 q1.rpctype = q2.rpctype = "announce_peer" q1.token = q2.token = 13 q1.port = q2.port = 123 q1.target_id = q2.target_id = 66 self.assertEquals(q1, q2) return (q1, q2)
def setUp(self): self.clock = Clock() monkey_patcher.addPatch(krpc_responder, "time", self.clock) monkey_patcher.patch() self.address = ("127.0.0.1", 5555) # Attach a standard test query query = Query() query._from = 15125 query.rpctype = "get_peers" query.target_id = 90809 self.query = query # The token generator that will be tested self.tgen = _TokenGenerator()
def test_get_peers_Received_sendsValidResponseWithNodes(self): # Create the protocol and populate its # routing table with nodes # We need a node_id close to 'target_id' so that our kbuckets split # in a way that we will have the target id target_id = 76 our_id = target_id - 1 kresponder = Patched_KRPC_Responder(node_id=our_id) node_list = [] node_gen = lambda num: contact.Node(num, ("127.0.0.%d" % num, num)) for i in range(100): if i != our_id: n = node_gen(i) if kresponder.routing_table.offer_node(n): node_list.append(n) # simulate that a get_peers query has been # received by making a fake get_peers query # and feeding it into "datagramReceived()" querying_node = contact.Node(123, test_address) incoming_query = Query() incoming_query.rpctype = "get_peers" incoming_query._from = querying_node.node_id incoming_query._transaction_id = 15 # We have this target id in our routing table incoming_query.target_id = target_id # Create a response object and ensure # and the response (that the node sends) # matches what we made expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = incoming_query._transaction_id expected_response.rpctype = "get_peers" # the specification calls for the resulting # nodes to be sorted by distance node_list.sort(key = lambda node: node.distance(incoming_query.target_id)) node_list = node_list[:constants.k] expected_response.nodes = node_list # simulating the incoming query and capture # the outgoing response kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response # Grab the autogenerated token expected_response.token = actual_response.token self.assertEquals(expected_response, actual_response)
def test_ping_Received_sendsValidResponse(self): kresponder = Patched_KRPC_Responder() incoming_query = Query() incoming_query.rpctype = "ping" incoming_query._from = 123 incoming_query._transaction_id = 15 expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = 15 expected_response.rpctype = "ping" kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response self.assertEquals(expected_response, actual_response)
def _query_decoder(rpc_dict): """ Decode the given KRPC dictionary into a valid Query @see decode @return krpc_types.Query """ q = Query() q._from = basic_coder.decode_network_id(rpc_dict['a']['id']) q.rpctype = rpctype = rpc_dict['q'] if rpctype == 'ping': pass elif rpctype == 'find_node': q.target_id = basic_coder.decode_network_id(rpc_dict['a']['target']) elif rpctype == 'get_peers': q.target_id = basic_coder.decode_network_id(rpc_dict['a']['info_hash']) elif rpctype == 'announce_peer': q.target_id = basic_coder.decode_network_id(rpc_dict['a']['info_hash']) # Try encoding the port (to ensure it is within range) basic_coder.encode_port(rpc_dict['a']['port']) q.port = rpc_dict['a']['port'] q.token = basic_coder.btol(rpc_dict['a']['token']) else: raise _ProtocolFormatError() return q
def test_responseReceived(self): # Make a query that we will "send" query = Query() query.rpctype = "ping" # Make the protocol and patch in our counter, transport, and reactor counter = Counter() k_messenger = KRPC_Sender(TreeRoutingTable, 2**50) k_messenger.transport = HollowTransport() k_messenger.responseReceived = counter # Send the query and receive the response k_messenger.sendQuery(query, address, timeout) self.assertTrue(query._transaction_id in k_messenger._transactions) # Make a response that we will "receive" response = query.build_response() response._from = 9 k_messenger.datagramReceived(krpc_coder.encode(response), address) _restore_reactor() self.assertEquals(1, counter.count)
def test_find_node_Received_sendsValidResponseWithTargetNode(self): # Create the protocol and populate its # routing table with nodes # We need a node_id close to 'target_id' so that our kbuckets split # in a way that we will have the target id target_id = 76 our_id = target_id - 1 kresponder = Patched_KRPC_Responder(node_id=our_id) node_list = [] node_gen = lambda num: contact.Node(num, ("127.0.0.%d" % num, num)) for i in range(100): if i != our_id: n = node_gen(i) node_was_accepted = kresponder.routing_table.offer_node(n) if node_was_accepted: node_list.append(n) querying_node = contact.Node(123, test_address) incoming_query = Query() incoming_query.rpctype = "find_node" incoming_query._from = querying_node.node_id incoming_query._transaction_id = 15 # We have this target id in our routing table incoming_query.target_id = target_id expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = 15 expected_response.rpctype = "find_node" # The response node_list should contain only the target node node_list = filter(lambda node: node.node_id == target_id, node_list) expected_response.nodes = node_list if len(node_list) != 1: self.fail("Too many or too few nodes!") kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response self.assertEquals(expected_response, actual_response)
def test_get_peers_Received_sendsValidResponseWithPeers(self): # Create the protocol and populate its # routing table with nodes kresponder = Patched_KRPC_Responder() peers = [("127.0.0.%d" % peer_num, peer_num) for peer_num in range(10)] incoming_query = Query() incoming_query.rpctype = "get_peers" incoming_query._from = 555 incoming_query._transaction_id = 15 # We have this target id in our routing table incoming_query.target_id = 77 expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = 15 expected_response.peers = peers expected_response.rpctype = "get_peers" ds = kresponder._datastore for peer in peers: ds[incoming_query.target_id].add(peer) kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response # Grab the autogenerated token and sort the peers to # match our expected order expected_response.token = actual_response.token ap = actual_response ap.peers = sorted(ap.peers, key=lambda (ip, port): port) actual_response.peers.sort(key=lambda (ip, port): port) self.assertEquals(expected_response, actual_response)
def test_find_node_Received_sendsValidResponseMultipleNodes(self): # Create the protocol and populate its # routing table with nodes kresponder = Patched_KRPC_Responder() node_list = [] node_gen = lambda num: contact.Node(num, ("127.0.0.%d" % num, num)) for i in range(100): n = node_gen(i) if kresponder.routing_table.offer_node(n): node_list.append(n) querying_node = contact.Node(123, test_address) incoming_query = Query() incoming_query.rpctype = "find_node" incoming_query._from = querying_node.node_id incoming_query._transaction_id = 15 incoming_query.target_id = 777777 expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = 15 expected_response.rpctype = "find_node" node_list.sort( key=lambda node: node.distance(incoming_query.target_id)) node_list = node_list[:constants.k] expected_response.nodes = node_list kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response self.assertEquals(expected_response, actual_response)
def announce_peer(self, address, target_id, token, port, timeout=constants.rpctimeout): query = Query() query.rpctype = "announce_peer" query.target_id = target_id query.token = token query.port = port return self.sendQuery(query, address, timeout)
def announce_peer(self, address, target_id, token, port, timeout=None): log.msg("make a announce_peers request to node(%s:%s)" % address) timeout = timeout or constants.rpctimeout query = Query() query.rpctype = "announce_peer" query.target_id = target_id query.token = token query.port = port return self.sendQuery(query, address, timeout)
def test_get_peers_Received_sendsValidResponseWithNodes(self): # Create the protocol and populate its # routing table with nodes # We need a node_id close to 'target_id' so that our kbuckets split # in a way that we will have the target id target_id = 76 our_id = target_id - 1 kresponder = Patched_KRPC_Responder(node_id=our_id) node_list = [] node_gen = lambda num: contact.Node(num, ("127.0.0.%d" % num, num)) for i in range(100): if i != our_id: n = node_gen(i) if kresponder.routing_table.offer_node(n): node_list.append(n) # simulate that a get_peers query has been # received by making a fake get_peers query # and feeding it into "datagramReceived()" querying_node = contact.Node(123, test_address) incoming_query = Query() incoming_query.rpctype = "get_peers" incoming_query._from = querying_node.node_id incoming_query._transaction_id = 15 # We have this target id in our routing table incoming_query.target_id = target_id # Create a response object and ensure # and the response (that the node sends) # matches what we made expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = incoming_query._transaction_id expected_response.rpctype = "get_peers" # the specification calls for the resulting # nodes to be sorted by distance node_list.sort( key=lambda node: node.distance(incoming_query.target_id)) node_list = node_list[:constants.k] expected_response.nodes = node_list # simulating the incoming query and capture # the outgoing response kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response # Grab the autogenerated token expected_response.token = actual_response.token self.assertEquals(expected_response, actual_response)
def test_announce_peer_Received_invalidTokenDoesntAddPeer(self): kresponder = Patched_KRPC_Responder() # announce_peer queries need a token (the token value # comes in response to a get_peers query) # So first, we need to "receive" a get_peers query # get_peers creation and "receiving" query = Query() query.rpctype = "get_peers" query._from = 123 query._transaction_id = 150 query.target_id = 800 kresponder.datagramReceived(krpc_coder.encode(query), test_address) response = kresponder.sendResponse.response # announce_peer creation and "receiving" incoming_query = Query() incoming_query._transaction_id = 999 incoming_query._from = query._from incoming_query.rpctype = "announce_peer" incoming_query.token = 5858585858 # this is an invalid token incoming_query.port = 55 incoming_query.target_id = query.target_id # Test the announce_peer response expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = incoming_query._transaction_id # Reset the response grabber kresponder.sendResponse.response = None kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response # Make sure we didnt send a response self.assertEquals(None, actual_response) # Check to see if another get_peers query will return us # as a peer query = Query() query.rpctype = "get_peers" query._from = 123 query._transaction_id = 9809831 query.target_id = 800 kresponder.datagramReceived(krpc_coder.encode(query), test_address) response = kresponder.sendResponse.response # Make sure no peers were returned self.assertEquals(None, response.peers)
def setUp(self): self.q = Query() self.q._transaction_id = 500 self.q._from = 27 self.q.rpctype = "ping"
def get_peers(self, address, target_id, timeout=constants.rpctimeout): query = Query() query.rpctype = "get_peers" query.target_id = target_id return self.sendQuery(query, address, timeout)
def find_node(self, address, node_id, timeout=constants.rpctimeout): query = Query() query.rpctype = "find_node" query.target_id = node_id return self.sendQuery(query, address, timeout)
def ping(self, address, timeout=constants.rpctimeout): query = Query() query.rpctype = "ping" return self.sendQuery(query, address, timeout)
def ping(self, address, timeout=None): timeout = timeout or constants.rpctimeout query = Query() query.rpctype = "ping" return self.sendQuery(query, address, timeout)
def test_announce_peer_Received_sendsValidResponse(self): kresponder = Patched_KRPC_Responder() # announce_peer queries need a token (the token value # comes in response to a get_peers query) # So first, we need to "receive" a get_peers query # get_peers creation and "receiving" query = Query() query.rpctype = "get_peers" query._from = 123 query._transaction_id = 150 query.target_id = 800 kresponder.datagramReceived(krpc_coder.encode(query), test_address) response = kresponder.sendResponse.response # announce_peer creation and "receiving" incoming_query = Query() incoming_query._transaction_id = 999 incoming_query._from = query._from incoming_query.rpctype = "announce_peer" incoming_query.token = response.token incoming_query.port = 55 incoming_query.target_id = query.target_id # Test the announce_peer response expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = incoming_query._transaction_id expected_response.rpctype = "announce_peer" # Reset the response grabber kresponder.sendResponse.response = None kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response self.assertEquals(expected_response, actual_response)
def test_announce_peer_Received_validTokenAddsPeer(self): kresponder = Patched_KRPC_Responder() # announce_peer queries need a token (the token value # comes in response to a get_peers query) # So first, we need to "receive" a get_peers query # get_peers creation and "receiving" query = Query() query.rpctype = "get_peers" query._from = 123 query._transaction_id = 150 query.target_id = 800 kresponder.datagramReceived(krpc_coder.encode(query), test_address) response = kresponder.sendResponse.response # announce_peer creation and "receiving" incoming_query = Query() incoming_query._transaction_id = 999 incoming_query._from = query._from incoming_query.rpctype = "announce_peer" incoming_query.token = response.token incoming_query.port = 55 incoming_query.target_id = query.target_id # Test the announce_peer response expected_response = Response() expected_response._from = kresponder.node_id expected_response._transaction_id = incoming_query._transaction_id expected_response.rpctype = "announce_peer" # Reset the response grabber kresponder.sendResponse.response = None kresponder.datagramReceived(krpc_coder.encode(incoming_query), test_address) actual_response = kresponder.sendResponse.response self.assertEquals(expected_response, actual_response) # Check to see if another get_peers query will return us # as a peer query = Query() query.rpctype = "get_peers" query._from = 123 query._transaction_id = 9809831 query.target_id = 800 kresponder.datagramReceived(krpc_coder.encode(query), test_address) response = kresponder.sendResponse.response self.assertEquals(1, len(response.peers)) test_ip, test_port = test_address returned_peer = list(response.peers)[0] self.assertEquals((test_ip, incoming_query.port), returned_peer)
def setUp(self): _swap_out_reactor() self.k_messenger = KRPC_Sender(TreeRoutingTable, 2**50) self.k_messenger.transport = HollowTransport() self.query = Query() self.query.rpctype = "ping"
class KRPC_Sender_DeferredTestCase(unittest.TestCase): def setUp(self): _swap_out_reactor() self.k_messenger = KRPC_Sender(TreeRoutingTable, 2**50) self.k_messenger.transport = HollowTransport() self.query = Query() self.query.rpctype = "ping" def tearDown(self): _restore_reactor() def _response_equality(self, response, expected_response): self.assertEquals(expected_response._transaction_id, response._transaction_id) self.assertEquals(expected_response._from, response._from) return response def test_callback(self): counter = Counter() d = self.k_messenger.sendQuery(self.query, address, timeout) self.assertTrue(self.query._transaction_id in self.k_messenger._transactions) # Build the response we will "receive" response = self.query.build_response() response._from = 9 d.addCallback(self._response_equality, response) d.addCallback(counter) encoded_response = krpc_coder.encode(response) self.k_messenger.datagramReceived(encoded_response, address) self.assertEquals(1, counter.count) self.assertFalse(self.query._transaction_id in self.k_messenger._transactions) def _error_equality(self, error, expected_error): self.assertEquals(expected_error._transaction_id, error._transaction_id) self.assertEquals(expected_error.code, error.code) return error def test_errback_KRPCError(self): counter = Counter() d = self.k_messenger.sendQuery(self.query, address, timeout) self.assertTrue(self.query._transaction_id in self.k_messenger._transactions) # Build the response we will "receive" error = self.query.build_error() d.addErrback(self._error_equality, error) d.addErrback(counter) encoded_error = krpc_coder.encode(error) self.k_messenger.datagramReceived(encoded_error, address) self.assertEquals(1, counter.count) self.assertFalse(self.query._transaction_id in self.k_messenger._transactions) def test_errback_InvalidKRPCError(self): # Make an invalid query query = Query() query.rpctype = "pingpong" d = self.k_messenger.sendQuery(query, address, timeout) self.assertFalse(self.query._transaction_id in self.k_messenger._transactions) # Cleanup the error d.addErrback(lambda failure: failure.trap(krpc_coder.InvalidKRPCError)) def test_errback_TimeoutError(self): d = self.k_messenger.sendQuery(self.query, address, timeout) self.assertTrue(self.query._transaction_id in self.k_messenger._transactions) d.errback(TimeoutError()) self.assertFalse(self.query._transaction_id in self.k_messenger._transactions) # Cleanup the error d.addErrback(lambda failure: failure.trap(TimeoutError))
def setUp(self): q = self.q = Query() q._transaction_id = 15 q._from = 2**120
def ping(self, address, timeout=None): log.msg("make a ping request to node (%s:%s)" % address) timeout = timeout or constants.rpctimeout query = Query() query.rpctype = "ping" return self.sendQuery(query, address, timeout)
class KRPC_Sender_DeferredTestCase(unittest.TestCase): def setUp(self): _swap_out_reactor() self.k_messenger = KRPC_Sender(TreeRoutingTable, 2**50) self.k_messenger.transport = HollowTransport() self.query = Query() self.query.rpctype = "ping" def tearDown(self): _restore_reactor() def _response_equality(self, response, expected_response): self.assertEquals(expected_response._transaction_id, response._transaction_id) self.assertEquals(expected_response._from, response._from) return response def test_callback(self): counter = Counter() d = self.k_messenger.sendQuery(self.query, address, timeout) self.assertTrue( self.query._transaction_id in self.k_messenger._transactions) # Build the response we will "receive" response = self.query.build_response() response._from = 9 d.addCallback(self._response_equality, response) d.addCallback(counter) encoded_response = krpc_coder.encode(response) self.k_messenger.datagramReceived(encoded_response, address) self.assertEquals(1, counter.count) self.assertFalse( self.query._transaction_id in self.k_messenger._transactions) def _error_equality(self, error, expected_error): self.assertEquals(expected_error._transaction_id, error._transaction_id) self.assertEquals(expected_error.code, error.code) return error def test_errback_KRPCError(self): counter = Counter() d = self.k_messenger.sendQuery(self.query, address, timeout) self.assertTrue( self.query._transaction_id in self.k_messenger._transactions) # Build the response we will "receive" error = self.query.build_error() d.addErrback(self._error_equality, error) d.addErrback(counter) encoded_error = krpc_coder.encode(error) self.k_messenger.datagramReceived(encoded_error, address) self.assertEquals(1, counter.count) self.assertFalse( self.query._transaction_id in self.k_messenger._transactions) def test_errback_InvalidKRPCError(self): # Make an invalid query query = Query() query.rpctype = "pingpong" d = self.k_messenger.sendQuery(query, address, timeout) self.assertFalse( self.query._transaction_id in self.k_messenger._transactions) # Cleanup the error d.addErrback(lambda failure: failure.trap(krpc_coder.InvalidKRPCError)) def test_errback_TimeoutError(self): d = self.k_messenger.sendQuery(self.query, address, timeout) self.assertTrue( self.query._transaction_id in self.k_messenger._transactions) d.errback(TimeoutError()) self.assertFalse( self.query._transaction_id in self.k_messenger._transactions) # Cleanup the error d.addErrback(lambda failure: failure.trap(TimeoutError))