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 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_error(self): """ The _handle_error method cleanly deals with the fallout of encountering an error generated from an interaction with a peer node. """ patcher = mock.patch('drogulus.dht.lookup.log.info') mock_info = patcher.start() lookup = Lookup(FindNode, self.target, self.node, self.event_loop) lookup._lookup = mock.MagicMock() uuid = [uuid for uuid in lookup.pending_requests.keys()][0] pending_task = lookup.pending_requests[uuid] contact = lookup.shortlist[0] lookup._handle_error(uuid, contact, Exception('Foo')) self.assertNotIn(contact, lookup.shortlist) self.assertNotIn(uuid, lookup.pending_requests) self.assertTrue(pending_task.cancelled()) # Log the error and associated exception (2 calls) self.assertEqual(mock_info.call_count, 2) self.assertEqual(lookup._lookup.call_count, 1) patcher.stop()
def test_handle_error(self): """ The _handle_error method cleanly deals with the fallout of encountering an error generated from an interaction with a peer node. """ patcher = mock.patch('drogulus.dht.lookup.log.info') mock_info = patcher.start() lookup = Lookup(FindNode, self.target, self.node, self.event_loop) lookup._lookup = mock.MagicMock() uuid = [uuid for uuid in lookup.pending_requests.keys()][0] pending_task = lookup.pending_requests[uuid] contact = lookup.shortlist[0] lookup.event_loop.call_soon = mock.MagicMock() lookup._handle_error(uuid, contact, Exception('Foo')) self.assertNotIn(contact, lookup.shortlist) self.assertNotIn(uuid, lookup.pending_requests) lookup.event_loop.call_soon.assert_called_once_with( pending_task.cancel) # Log the error and associated exception (2 calls) self.assertEqual(mock_info.call_count, 2) self.assertEqual(lookup._lookup.call_count, 1) patcher.stop()
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))
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))