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))
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)
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))
def setUp(self): """ Gives us some messages to play with. """ self.uuid = str(uuid4()) self.node = PUBLIC_KEY self.recipient = PUBLIC_KEY self.sender = PUBLIC_KEY self.reply_port = 1908 self.value = 1.234 self.public_key = PUBLIC_KEY self.name = 'a_human_readable_key_name' self.key = construct_key(self.public_key, self.name) signed_dict = get_signed_item(self.key, self.value, self.public_key, PRIVATE_KEY, 1000) self.version = get_version() self.timestamp = signed_dict['timestamp'] self.expires = signed_dict['expires'] self.created_with = signed_dict['created_with'] self.signature = signed_dict['signature'] self.message = 'value' self.seal = 'afakesealthatwillnotwork' self.nodes = [[self.node, self.version, 'http://192.168.0.1:8080/'], ] self.mock_message = Value(self.uuid, self.node, self.node, self.reply_port, self.version, self.seal, self.key, self.value, self.timestamp, self.expires, self.created_with, self.public_key, self.name, self.signature)
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)
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())
def test_value(self): """ Expected behaviour of a value message. """ val = Value(self.uuid, self.recipient, self.sender, self.reply_port, self.version, self.seal, self.key, 'value', 1350544046.084875, 0.0, self.version, PUBLIC_KEY, 'name', 'signature') self.assertEqual(self.uuid, val.uuid) self.assertEqual(self.recipient, val.recipient) self.assertEqual(self.sender, val.sender) self.assertEqual(self.reply_port, val.reply_port) self.assertEqual(self.version, val.version) self.assertEqual(self.seal, val.seal) self.assertEqual(self.key, val.key) self.assertEqual('value', val.value) self.assertEqual(1350544046.084875, val.timestamp) self.assertEqual(0.0, val.expires) self.assertEqual(self.version, val.created_with) self.assertEqual(PUBLIC_KEY, val.public_key) self.assertEqual('name', val.name) self.assertEqual('signature', val.signature)
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))