def test_hex_to_long(self): """ Ensure a valid hex value produces the correct result. """ raw = 'abcdef0123456789' result = hex_to_long(raw) self.assertEqual(raw, long_to_hex(result))
def test_long_to_hex(self): """ Ensure a long number produces the correct result. """ raw = 123456789L result = long_to_hex(raw) self.assertEqual(raw, long(result.encode('hex'), 16))
def _random_key_in_bucket_range(self, bucket_index): """ Returns a random key in the specified k-bucket's range. """ # Get a random integer within the required range. keyValue = random.randrange(self._buckets[bucket_index].range_min, self._buckets[bucket_index].range_max) return long_to_hex(keyValue)
def test_sort_contacts_no_longer_than_k(self): """ Ensure that no more than constants.K contacts are returned from the sort_contacts function despite a longer list being passed in. """ contacts = [] for i in range(512): contact = Contact(2 ** i, "192.168.0.%d" % i, 9999, self.version, 0) contacts.append(contact) target_key = long_to_hex(2 ** 256) result = sort_contacts(contacts, target_key) self.assertEqual(constants.K, len(result))
def test_find_close_nodes_multiple_buckets(self): """ Ensures that nodes are returned from neighbouring k-buckets if the k-bucket containing the referenced ID doesn't contain K entries. """ parent_node_id = 'abc' r = RoutingTable(parent_node_id) # Fill up the bucket and replacement cache for i in range(512): contact = Contact(2 ** i, "192.168.0.%d" % i, 9999, self.version, 0) r.add_contact(contact) result = r.find_close_nodes(long_to_hex(2 ** 256)) self.assertEqual(constants.K, len(result))
def __init__(self, id, address, port, version, last_seen=0): """ Initialises the contact object with its unique id within the DHT, IP address, port, the Drogulus version the contact is running and a timestamp when the last connection was made with the contact (defaults to 0). The id, if passed in as a numeric value, will be converted into a hexadecimal string. """ if isinstance(id, long) or isinstance(id, int): self.id = long_to_hex(id) else: self.id = id self.address = address self.port = port self.version = version self.last_seen = last_seen # failed_RPCs keeps track of the number of failed RPCs to this contact. # If this number reaches a threshold then it is evicted from the # kbucket and replaced with a contact that is more reliable. self.failed_RPCs = 0
def test_sort_contacts(self): """ Ensures that the sort_contacts function returns the list ordered in such a way that the contacts closest to the target key are at the head of the list. """ contacts = [] for i in range(512): contact = Contact(2 ** i, "192.168.0.%d" % i, 9999, self.version, 0) contacts.append(contact) target_key = long_to_hex(2 ** 256) result = sort_contacts(contacts, target_key) # Ensure results are in the correct order. def key(node): return distance(node.id, target_key) sorted_nodes = sorted(result, key=key) self.assertEqual(sorted_nodes, result) # Ensure the order is from lowest to highest in terms of distance distances = [distance(x.id, target_key) for x in result] self.assertEqual(sorted(distances), distances)
def test_find_close_nodes_in_correct_order(self): """ Ensures that the nearest nodes are returned in the correct order: from the node closest to the target key to the node furthest away. """ parent_node_id = 'abc' r = RoutingTable(parent_node_id) # Fill up the bucket and replacement cache for i in range(512): contact = Contact(2 ** i, "192.168.0.%d" % i, 9999, self.version, 0) r.add_contact(contact) target_key = long_to_hex(2 ** 256) result = r.find_close_nodes(target_key) self.assertEqual(constants.K, len(result)) # Ensure results are in the correct order. def key(node): return distance(node.id, target_key) sorted_nodes = sorted(result, key=key) self.assertEqual(sorted_nodes, result) # Ensure the order is from lowest to highest in terms of distance distances = [distance(x.id, target_key) for x in result] self.assertEqual(sorted(distances), distances)