Esempio n. 1
0
 def test_handle_response_all_shortlist_contacted_value_not_found(self):
     """
     If there are no more pending requests and all the nodes in the
     shortlist have been contacted then return the shortlist of nearest
     peer nodes to the target if the lookup is a FindNode.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     # Only one item in pending_requests
     for i in range(1, len(uuids)):
         del lookup.pending_requests[uuids[i]]
     self.assertEqual(1, len(lookup.pending_requests))
     # Add K items from shortlist to the contacted set.
     for contact in lookup.shortlist:
         lookup.contacted.add(contact)
     # Cause the lookup to fire.
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.contacts)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     # The _lookup method should not be called.
     self.assertEqual(lookup._lookup.call_count, 0)
     # The lookup task has fired.
     self.assertTrue(lookup.done())
     with self.assertRaises(ValueNotFound) as result:
         lookup.result()
     self.assertIsInstance(result.exception, ValueNotFound)
     self.assertEqual(result.exception.args[0],
                      "Unable to find value for key: {}"
                      .format(self.target))
Esempio n. 2
0
 def test_handle_response_all_shortlist_contacted_value_not_found(self):
     """
     If there are no more pending requests and all the nodes in the
     shortlist have been contacted then return the shortlist of nearest
     peer nodes to the target if the lookup is a FindNode.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     # Only one item in pending_requests
     for i in range(1, len(uuids)):
         del lookup.pending_requests[uuids[i]]
     self.assertEqual(1, len(lookup.pending_requests))
     # Add K items from shortlist to the contacted set.
     for contact in lookup.shortlist:
         lookup.contacted.add(contact)
     # Cause the lookup to fire.
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.contacts)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     # The _lookup method should not be called.
     self.assertEqual(lookup._lookup.call_count, 0)
     # The lookup task has fired.
     self.assertTrue(lookup.done())
     with self.assertRaises(ValueNotFound) as result:
         lookup.result()
     self.assertIsInstance(result.exception, ValueNotFound)
     self.assertEqual(result.exception.args[0],
                      "Unable to find value for key: {}"
                      .format(self.target))
Esempio n. 3
0
 def test_handle_response_still_nodes_uncontacted_in_shortlist(self):
     """
     Ensure that if there are no more pending requests but there are still
     uncontacted nodes in the shortlist then restart the lookup.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     # Only one item in pending_requests
     for i in range(1, len(uuids)):
         del lookup.pending_requests[uuids[i]]
     self.assertEqual(1, len(lookup.pending_requests))
     # Add K-1 items from shortlist to the contacted set.
     for i in range(K - 1):
         lookup.contacted.add(lookup.shortlist[i])
     # Ensure lookup is called with the 20th (uncontacted) contact.
     not_contacted = lookup.shortlist[K - 1]
     self.assertNotIn(not_contacted, lookup.contacted)
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.contacts)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup._lookup.call_count, 1)
     self.node.send_find.called_once_with(not_contacted, self.target,
                                          FindNode)
Esempio n. 4
0
 def test_handle_response_wrong_value_for_findnode_message(self):
     """
     Ensures that if a Value message is returned for a FindNode request
     then the misbehaving peer is blacklisted and the error is handled
     correctly.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     uuid = [uuid for uuid in lookup.pending_requests.keys()][0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), time.time() + 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._blacklist = mock.MagicMock()
     lookup._handle_error = mock.MagicMock()
     lookup._handle_response(uuid, contact, response)
     lookup._blacklist.assert_called_once_with(contact)
     self.assertEqual(lookup._handle_error.call_count, 1)
     args = lookup._handle_error.call_args[0]
     self.assertEqual(args[0], uuid)
     self.assertEqual(args[1], contact)
     self.assertIsInstance(args[2], TypeError)
     self.assertEqual(args[2].args[0],
                      "Unexpected response type from {}".format(contact))
Esempio n. 5
0
 def test_handle_response_value_message_wrong_key(self):
     """
     If a valid Value response is received but the key doesn't match the
     one being requested then the misbehaving node is blacklisted and
     appropriately dealt with.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, 'f00baa',
                 'value', time.time(), time.time() + 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._blacklist = mock.MagicMock()
     lookup._handle_error = mock.MagicMock()
     lookup._handle_response(uuid, contact, response)
     lookup._blacklist.assert_called_once_with(contact)
     self.assertEqual(lookup._handle_error.call_count, 1)
     args = lookup._handle_error.call_args[0]
     self.assertEqual(args[0], uuid)
     self.assertEqual(args[1], contact)
     self.assertIsInstance(args[2], ValueError)
     self.assertEqual(args[2].args[0],
                      "Value with wrong key returned by {}"
                      .format(contact))
Esempio n. 6
0
 def test_handle_response_value_results_in_node_lookup_callback(self):
     """
     Tests that if a valid Value message is handled then all the other
     pending requests for the lookup are cancelled and the lookup has its
     set_result method called with the Value.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     other_request1 = lookup.pending_requests[uuids[1]]
     other_request2 = lookup.pending_requests[uuids[2]]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), time.time() + 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.event_loop.run_until_complete(blip())
     # Check the lookup has fired correctly.
     self.assertTrue(lookup.done())
     self.assertEqual(lookup.result(), msg)
     # Check the other requests are cancelled.
     self.assertTrue(other_request1.cancelled())
     self.assertTrue(other_request2.cancelled())
     # Make sure the pending_requests dict is empty.
     self.assertEqual(0, len(lookup.pending_requests))
     # Ensure the contact that provided the result is NOT in the shortlist.
     self.assertNotIn(contact, lookup.shortlist)
Esempio n. 7
0
 def test_handle_response_still_nodes_uncontacted_in_shortlist(self):
     """
     Ensure that if there are no more pending requests but there are still
     uncontacted nodes in the shortlist then restart the lookup.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     # Only one item in pending_requests
     for i in range(1, len(uuids)):
         del lookup.pending_requests[uuids[i]]
     self.assertEqual(1, len(lookup.pending_requests))
     # Add K-1 items from shortlist to the contacted set.
     for i in range(K - 1):
         lookup.contacted.add(lookup.shortlist[i])
     # Ensure lookup is called with the 20th (uncontacted) contact.
     not_contacted = lookup.shortlist[K - 1]
     self.assertNotIn(not_contacted, lookup.contacted)
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.contacts)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup._lookup.call_count, 1)
     self.node.send_find.called_once_with(not_contacted, self.target,
                                          FindNode)
Esempio n. 8
0
 def test_handle_response_value_message_wrong_key(self):
     """
     If a valid Value response is received but the key doesn't match the
     one being requested then the misbehaving node is blacklisted and
     appropriately dealt with.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, 'f00baa',
                 'value', time.time(), time.time() + 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._blacklist = mock.MagicMock()
     lookup._handle_error = mock.MagicMock()
     lookup._handle_response(uuid, contact, response)
     lookup._blacklist.assert_called_once_with(contact)
     self.assertEqual(lookup._handle_error.call_count, 1)
     args = lookup._handle_error.call_args[0]
     self.assertEqual(args[0], uuid)
     self.assertEqual(args[1], contact)
     self.assertIsInstance(args[2], ValueError)
     self.assertEqual(args[2].args[0],
                      "Value with wrong key returned by {}"
                      .format(contact))
Esempio n. 9
0
 def test_handle_response_value_results_in_node_lookup_callback(self):
     """
     Tests that if a valid Value message is handled then all the other
     pending requests for the lookup are cancelled and the lookup has its
     set_result method called with the Value.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     other_request1 = lookup.pending_requests[uuids[1]]
     other_request2 = lookup.pending_requests[uuids[2]]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), time.time() + 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.event_loop.run_until_complete(blip())
     # Check the lookup has fired correctly.
     self.assertTrue(lookup.done())
     self.assertEqual(lookup.result(), msg)
     # Check the other requests are cancelled.
     self.assertTrue(other_request1.cancelled())
     self.assertTrue(other_request2.cancelled())
     # Make sure the pending_requests dict is empty.
     self.assertEqual(0, len(lookup.pending_requests))
     # Ensure the contact that provided the result is NOT in the shortlist.
     self.assertNotIn(contact, lookup.shortlist)
Esempio n. 10
0
 def test_handle_response_wrong_value_for_findnode_message(self):
     """
     Ensures that if a Value message is returned for a FindNode request
     then the misbehaving peer is blacklisted and the error is handled
     correctly.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     uuid = [uuid for uuid in lookup.pending_requests.keys()][0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), time.time() + 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._blacklist = mock.MagicMock()
     lookup._handle_error = mock.MagicMock()
     lookup._handle_response(uuid, contact, response)
     lookup._blacklist.assert_called_once_with(contact)
     self.assertEqual(lookup._handle_error.call_count, 1)
     args = lookup._handle_error.call_args[0]
     self.assertEqual(args[0], uuid)
     self.assertEqual(args[1], contact)
     self.assertIsInstance(args[2], TypeError)
     self.assertEqual(args[2].args[0],
                      "Unexpected response type from {}".format(contact))
Esempio n. 11
0
 def test_lookup_adds_callback(self):
     """
     Ensure the _lookup method add the expected callback to the Future that
     represents the request to the remote node in the DHT.
     """
     # Reset event_loop so we start in a clean state.
     loop = asyncio.new_event_loop()
     asyncio.set_event_loop(loop)
     self.event_loop = asyncio.get_event_loop()
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._handle_response = mock.MagicMock()
     keys = []
     for k, v in lookup.pending_requests.items():
         keys.append(k)
         v.set_result('foo')
         self.event_loop.run_until_complete(v)
     self.assertEqual(lookup._handle_response.call_count, 3)
     for i, key in enumerate(keys):
         # check the callback called _handle_response with the correct
         # arguments.
         arg_key = lookup._handle_response.call_args_list[i][0][0]
         self.assertEqual(arg_key, key)
         arg_contact = lookup._handle_response.call_args_list[i][0][1]
         self.assertIn(arg_contact, lookup.contacted)
         arg_future = lookup._handle_response.call_args_list[i][0][2]
         self.assertEqual(arg_future.result(), 'foo')
Esempio n. 12
0
 def test_handle_response_value_never_expires(self):
     """
     Ensures an expired Value is handled correctly.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), 0.0, self.version, PUBLIC_KEY,
                 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup.result(), msg)
Esempio n. 13
0
 def test_handle_response_value_never_expires(self):
     """
     Ensures an expired Value is handled correctly.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), 0.0, self.version, PUBLIC_KEY,
                 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup.result(), msg)
Esempio n. 14
0
 def test_lookup_adds_callback(self):
     """
     Ensure the _lookup method add the expected callback to the Future that
     represents the request to the remote node in the DHT.
     """
     # Reset event_loop so we start in a clean state.
     loop = asyncio.new_event_loop()
     asyncio.set_event_loop(loop)
     self.event_loop = asyncio.get_event_loop()
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._handle_response = mock.MagicMock()
     keys = []
     for k, v in lookup.pending_requests.items():
         keys.append(k)
         v.set_result('foo')
         self.event_loop.run_until_complete(v)
     self.assertEqual(lookup._handle_response.call_count, 3)
     for i, key in enumerate(keys):
         # check the callback called _handle_response with the correct
         # arguments.
         arg_key = lookup._handle_response.call_args_list[i][0][0]
         self.assertEqual(arg_key, key)
         arg_contact = lookup._handle_response.call_args_list[i][0][1]
         self.assertIn(arg_contact, lookup.contacted)
         arg_future = lookup._handle_response.call_args_list[i][0][2]
         self.assertEqual(arg_future.result(), 'foo')
Esempio n. 15
0
 def test_handle_response_nodes_no_duplicates_in_shortlist(self):
     """
     If the response contains peer nodes that are already found in the
     lookup's shortlist they are not duplicated.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     shortlist = tuple([(p.public_key, p.version, p.uri) for p
                        in lookup.shortlist])
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, shortlist)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup.shortlist, [PeerNode(*n) for n in shortlist])
Esempio n. 16
0
 def test_handle_response_remove_request_from_pending(self):
     """
     Ensure the pending request that triggered the response being handled
     by the _handle_response callback is removed from the pending_requests
     dict.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     uuid = [uuid for uuid in lookup.pending_requests.keys()][0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), time.time() + 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertNotIn(uuid, lookup.pending_requests.keys())
Esempio n. 17
0
 def test_handle_response_nodes_no_duplicates_in_shortlist(self):
     """
     If the response contains peer nodes that are already found in the
     lookup's shortlist they are not duplicated.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     shortlist = tuple([(p.public_key, p.version, p.uri) for p
                        in lookup.shortlist])
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, shortlist)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup.shortlist, [PeerNode(*n) for n in shortlist])
Esempio n. 18
0
 def test_handle_response_remove_request_from_pending(self):
     """
     Ensure the pending request that triggered the response being handled
     by the _handle_response callback is removed from the pending_requests
     dict.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     uuid = [uuid for uuid in lookup.pending_requests.keys()][0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), time.time() + 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertNotIn(uuid, lookup.pending_requests.keys())
Esempio n. 19
0
 def test_handle_response_nodes_adds_closest_nodes_to_shortlist(self):
     """
     Ensures a Nodes message causes the referenced peer nodes to be added
     to the shortlist in the correct order (closest to the target at the
     head of the list).
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.remote_nodes)
     response = asyncio.Future()
     response.set_result(msg)
     self.assertNotEqual(lookup.shortlist, list(self.nodes))
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup.shortlist, list(self.nodes))
Esempio n. 20
0
 def test_handle_response_nodes_adds_closest_nodes_to_shortlist(self):
     """
     Ensures a Nodes message causes the referenced peer nodes to be added
     to the shortlist in the correct order (closest to the target at the
     head of the list).
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.remote_nodes)
     response = asyncio.Future()
     response.set_result(msg)
     self.assertNotEqual(lookup.shortlist, list(self.nodes))
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup.shortlist, list(self.nodes))
Esempio n. 21
0
 def test_handle_response_nodes_update_nearest_node(self):
     """
     If the response contains peer nodes that are nearer to the target then
     the nearest_node variable is updated to reflect this change of state
     and a new lookup call is kicked off.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     old_nearest_node = lookup.nearest_node
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.remote_nodes)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertNotEqual(lookup.nearest_node, old_nearest_node)
     self.assertEqual(lookup.nearest_node, lookup.shortlist[0])
     self.assertEqual(lookup._lookup.call_count, 1)
Esempio n. 22
0
 def test_handle_response_nodes_update_nearest_node(self):
     """
     If the response contains peer nodes that are nearer to the target then
     the nearest_node variable is updated to reflect this change of state
     and a new lookup call is kicked off.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     old_nearest_node = lookup.nearest_node
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.remote_nodes)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertNotEqual(lookup.nearest_node, old_nearest_node)
     self.assertEqual(lookup.nearest_node, lookup.shortlist[0])
     self.assertEqual(lookup._lookup.call_count, 1)
Esempio n. 23
0
 def test_handle_response_nodes_do_not_update_nearest_node(self):
     """
     If the response contains peer nodes that are NOT closer to the target
     than the current nearest known node then nearest_node is NOT
     updated and a new lookup is NOT triggered.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     old_nearest_node = lookup.nearest_node
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     shortlist = tuple([(p.public_key, p.version, p.uri) for p
                        in lookup.shortlist])
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, shortlist)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup.nearest_node, old_nearest_node)
     self.assertEqual(lookup.nearest_node, lookup.shortlist[0])
     self.assertEqual(lookup._lookup.call_count, 0)
Esempio n. 24
0
 def test_handle_response_nodes_do_not_update_nearest_node(self):
     """
     If the response contains peer nodes that are NOT closer to the target
     than the current nearest known node then nearest_node is NOT
     updated and a new lookup is NOT triggered.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     old_nearest_node = lookup.nearest_node
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     shortlist = tuple([(p.public_key, p.version, p.uri) for p
                        in lookup.shortlist])
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, shortlist)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup.nearest_node, old_nearest_node)
     self.assertEqual(lookup.nearest_node, lookup.shortlist[0])
     self.assertEqual(lookup._lookup.call_count, 0)
Esempio n. 25
0
 def test_handle_response_all_shortlist_contacted_return_nodes(self):
     """
     If there are no more pending requests and all the nodes in the
     shortlist have been contacted then return the shortlist of nearest
     peer nodes to the target if the lookup is a FindNode.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     # Only one item in pending_requests
     for i in range(1, len(uuids)):
         del lookup.pending_requests[uuids[i]]
     self.assertEqual(1, len(lookup.pending_requests))
     # Add K items from shortlist to the contacted set.
     for contact in lookup.shortlist:
         lookup.contacted.add(contact)
     # Cause the lookup to fire.
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.contacts)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     # The _lookup method should not be called.
     self.assertEqual(lookup._lookup.call_count, 0)
     # The lookup task has fired.
     self.assertTrue(lookup.done())
     # Check the result is the ordered shortlist of contacts that are
     # closest to the target.
     # It should be a list...
     self.assertIsInstance(lookup.result(), list)
     # It should be a list that's the lookup's shortlist...
     self.assertEqual(lookup.result(), lookup.shortlist)
     # It should be a list that's the lookup's shortlist in order.
     ordered = sort_peer_nodes(lookup.shortlist, self.target)
     self.assertEqual(lookup.result(), ordered)
Esempio n. 26
0
 def test_handle_response_all_shortlist_contacted_return_nodes(self):
     """
     If there are no more pending requests and all the nodes in the
     shortlist have been contacted then return the shortlist of nearest
     peer nodes to the target if the lookup is a FindNode.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     lookup._lookup = mock.MagicMock()
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     # Only one item in pending_requests
     for i in range(1, len(uuids)):
         del lookup.pending_requests[uuids[i]]
     self.assertEqual(1, len(lookup.pending_requests))
     # Add K items from shortlist to the contacted set.
     for contact in lookup.shortlist:
         lookup.contacted.add(contact)
     # Cause the lookup to fire.
     msg = Nodes(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal,
                 self.contacts)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_response(uuid, contact, response)
     # The _lookup method should not be called.
     self.assertEqual(lookup._lookup.call_count, 0)
     # The lookup task has fired.
     self.assertTrue(lookup.done())
     # Check the result is the ordered shortlist of contacts that are
     # closest to the target.
     # It should be a list...
     self.assertIsInstance(lookup.result(), list)
     # It should be a list that's the lookup's shortlist...
     self.assertEqual(lookup.result(), lookup.shortlist)
     # It should be a list that's the lookup's shortlist in order.
     ordered = sort_peer_nodes(lookup.shortlist, self.target)
     self.assertEqual(lookup.result(), ordered)
Esempio n. 27
0
 def test_handle_response_value_expired(self):
     """
     Ensures an expired Value is handled correctly.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), time.time() - 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_error = mock.MagicMock()
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup._handle_error.call_count, 1)
     args = lookup._handle_error.call_args[0]
     self.assertEqual(args[0], uuid)
     self.assertEqual(args[1], contact)
     self.assertIsInstance(args[2], ValueError)
     self.assertEqual(args[2].args[0],
                      "Expired value returned by {}".format(contact))
Esempio n. 28
0
 def test_handle_response_value_expired(self):
     """
     Ensures an expired Value is handled correctly.
     """
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     uuids = [uuid for uuid in lookup.pending_requests.keys()]
     uuid = uuids[0]
     contact = lookup.shortlist[0]
     msg = Value(uuid, self.node.network_id, self.node.network_id,
                 self.reply_port, self.version, self.seal, self.target,
                 'value', time.time(), time.time() - 99999, self.version,
                 PUBLIC_KEY, 'name', 'signature')
     response = asyncio.Future()
     response.set_result(msg)
     lookup._handle_error = mock.MagicMock()
     lookup._handle_response(uuid, contact, response)
     self.assertEqual(lookup._handle_error.call_count, 1)
     args = lookup._handle_error.call_args[0]
     self.assertEqual(args[0], uuid)
     self.assertEqual(args[1], contact)
     self.assertIsInstance(args[2], ValueError)
     self.assertEqual(args[2].args[0],
                      "Expired value returned by {}".format(contact))
Esempio n. 29
0
 def test_handle_response_wrong_message_type(self):
     """
     Ensure that a response that isn't a Nodes or Value message results in
     the responding peer node being blacklisted and the error being
     correctly handled.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     uuid = [uuid for uuid in lookup.pending_requests.keys()][0]
     contact = lookup.shortlist[0]
     msg = OK(uuid, self.node.network_id, self.node.network_id,
              self.reply_port, self.version, self.seal)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._blacklist = mock.MagicMock()
     lookup._handle_error = mock.MagicMock()
     lookup._handle_response(uuid, contact, response)
     lookup._blacklist.assert_called_once_with(contact)
     self.assertEqual(lookup._handle_error.call_count, 1)
     args = lookup._handle_error.call_args[0]
     self.assertEqual(args[0], uuid)
     self.assertEqual(args[1], contact)
     self.assertIsInstance(args[2], TypeError)
     self.assertEqual(args[2].args[0],
                      "Unexpected response type from {}".format(contact))
Esempio n. 30
0
 def test_handle_response_wrong_message_type(self):
     """
     Ensure that a response that isn't a Nodes or Value message results in
     the responding peer node being blacklisted and the error being
     correctly handled.
     """
     lookup = Lookup(FindNode, self.target, self.node, self.event_loop)
     uuid = [uuid for uuid in lookup.pending_requests.keys()][0]
     contact = lookup.shortlist[0]
     msg = OK(uuid, self.node.network_id, self.node.network_id,
              self.reply_port, self.version, self.seal)
     response = asyncio.Future()
     response.set_result(msg)
     lookup._blacklist = mock.MagicMock()
     lookup._handle_error = mock.MagicMock()
     lookup._handle_response(uuid, contact, response)
     lookup._blacklist.assert_called_once_with(contact)
     self.assertEqual(lookup._handle_error.call_count, 1)
     args = lookup._handle_error.call_args[0]
     self.assertEqual(args[0], uuid)
     self.assertEqual(args[1], contact)
     self.assertIsInstance(args[2], TypeError)
     self.assertEqual(args[2].args[0],
                      "Unexpected response type from {}".format(contact))
Esempio n. 31
0
 def test_lookup_added_callbacks_work_when_cancelled(self):
     """
     Ensures that the callback added to pending requests by the _lookup
     method handles cancelled results. This may happen if the lookup is
     finished because a suitable value has been found (so everything else
     can be stopped ASAP).
     """
     # Reset event_loop so we start in a clean state.
     loop = asyncio.new_event_loop()
     asyncio.set_event_loop(loop)
     self.event_loop = asyncio.get_event_loop()
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._handle_response = mock.MagicMock()
     lookup._cancel_pending_requests()
     for k, v in lookup.pending_requests.items():
         v.set_result('foo')
         self.event_loop.run_until_complete(v)
     self.assertEqual(lookup._handle_response.call_count, 0)
Esempio n. 32
0
 def test_lookup_added_callbacks_work_when_cancelled(self):
     """
     Ensures that the callback added to pending requests by the _lookup
     method handles cancelled results. This may happen if the lookup is
     finished because a suitable value has been found (so everything else
     can be stopped ASAP).
     """
     # Reset event_loop so we start in a clean state.
     loop = asyncio.new_event_loop()
     asyncio.set_event_loop(loop)
     self.event_loop = asyncio.get_event_loop()
     lookup = Lookup(FindValue, self.target, self.node, self.event_loop)
     lookup._handle_response = mock.MagicMock()
     lookup._cancel_pending_requests()
     for k, v in lookup.pending_requests.items():
         v.set_result('foo')
         self.event_loop.run_until_complete(v)
     self.assertEqual(lookup._handle_response.call_count, 0)