def test_better_than_oneFreshOneOld(self): self.testclock.set(0) n_old = contact.Node(2**1, ("127.0.0.1", 1111)) n_fresh = contact.Node(2**2, ("127.0.0.1", 2222)) self.testclock.set(constants.node_timeout + 1) n_fresh.successful_query(10) self.assertTrue(n_fresh.better_than(n_old))
def test_find_node_Received_sendsValidResponseMultipleNodes(self): # Create the protocol and populate its # routing table with nodes kresponder = self._patched_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_better_than_bothOldWithNoQueries(self): self.testclock.set(0) n1 = contact.Node(2**1, ("127.0.0.1", 1111)) n2 = contact.Node(2**2, ("127.0.0.1", 2222)) self.testclock.set(constants.node_timeout + 1) self.assertFalse(n1.better_than(n2)) self.assertFalse(n2.better_than(n1))
def test_better_than_oneBetterRTT(self): self.testclock.set(0) n_slow = contact.Node(2**1, ("127.0.0.1", 1111)) n_fast = contact.Node(2**2, ("127.0.0.1", 2222)) self.testclock.set(10) n_slow.successful_query(0) n_fast.successful_query(5) self.assertTrue(n_fast.better_than(n_slow))
def test_distance(self): node_ids1 = [0, 1024, 2**150, 2**159 + 124, 2**34 - 58] node_ids2 = [0, 857081, 6**7, 8**9 + 7**3, 4**8 + 9**10 + 18] for id1 in node_ids1: for id2 in node_ids2: n = contact.Node(id1, ("127.0.0.1", 8000)) self.assertEqual(id1 ^ id2, n.distance(id2)) n = contact.Node(id2, ("127.0.0.1", 8000)) self.assertEqual(id2 ^ id1, n.distance(id1))
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 = self._patched_responder(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_fresh(self): n = contact.Node(2**17, ("127.0.0.1", 8012)) self.assertTrue(n.fresh()) # Simulate that `constants.node_timeout' time has passed self.testclock.set(constants.node_timeout + 1) self.assertFalse(n.fresh()) # Refresh the node with a new query n.successful_query(10) self.assertTrue(n.fresh())
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 = self._patched_responder(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 _query_success_callback(self, response, address, transaction): """ Handle a valid Response to an outstanding Query This callback records changes to the statistics for the node behind the address/response (ie, it updates its RTT and makes sures it is in the routing table) """ # Pull the node corresponding to this response out # of our routing table, or create it if it doesn't exist rt_node = self.routing_table.get_node(response._from) responsenode = (rt_node if rt_node is not None else contact.Node( response._from, address)) responsenode.successful_query(transaction.time) self.routing_table.offer_node(responsenode) # Pass the response further down the callback chain return response