Merge "Make NovaException format errors fatal for tests"
This commit is contained in:
@@ -86,17 +86,21 @@ class NovaException(Exception):
|
|||||||
message = self.msg_fmt % kwargs
|
message = self.msg_fmt % kwargs
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
# kwargs doesn't match a variable in the message
|
# NOTE(melwitt): This is done in a separate method so it can be
|
||||||
# log the issue and the kwargs
|
# monkey-patched during testing to make it a hard failure.
|
||||||
LOG.exception(_LE('Exception in string format operation'))
|
self._log_exception()
|
||||||
for name, value in kwargs.items():
|
|
||||||
LOG.error("%s: %s" % (name, value)) # noqa
|
|
||||||
|
|
||||||
message = self.msg_fmt
|
message = self.msg_fmt
|
||||||
|
|
||||||
self.message = message
|
self.message = message
|
||||||
super(NovaException, self).__init__(message)
|
super(NovaException, self).__init__(message)
|
||||||
|
|
||||||
|
def _log_exception(self):
|
||||||
|
# kwargs doesn't match a variable in the message
|
||||||
|
# log the issue and the kwargs
|
||||||
|
LOG.exception(_LE('Exception in string format operation'))
|
||||||
|
for name, value in self.kwargs.items():
|
||||||
|
LOG.error("%s: %s" % (name, value)) # noqa
|
||||||
|
|
||||||
def format_message(self):
|
def format_message(self):
|
||||||
# NOTE(mrodden): use the first argument to the python Exception object
|
# NOTE(mrodden): use the first argument to the python Exception object
|
||||||
# which should be our full NovaException message, (see __init__)
|
# which should be our full NovaException message, (see __init__)
|
||||||
|
22
nova/test.py
22
nova/test.py
@@ -31,6 +31,7 @@ import datetime
|
|||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
import pprint
|
import pprint
|
||||||
|
import sys
|
||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
import mock
|
import mock
|
||||||
@@ -49,6 +50,7 @@ import testtools
|
|||||||
|
|
||||||
from nova import context
|
from nova import context
|
||||||
from nova import db
|
from nova import db
|
||||||
|
from nova import exception
|
||||||
from nova.network import manager as network_manager
|
from nova.network import manager as network_manager
|
||||||
from nova.network.security_group import openstack_driver
|
from nova.network.security_group import openstack_driver
|
||||||
from nova import objects
|
from nova import objects
|
||||||
@@ -169,6 +171,26 @@ def _patch_mock_to_raise_for_invalid_assert_calls():
|
|||||||
_patch_mock_to_raise_for_invalid_assert_calls()
|
_patch_mock_to_raise_for_invalid_assert_calls()
|
||||||
|
|
||||||
|
|
||||||
|
class NovaExceptionReraiseFormatError(object):
|
||||||
|
real_log_exception = exception.NovaException._log_exception
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def patch(cls):
|
||||||
|
exception.NovaException._log_exception = cls._wrap_log_exception
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _wrap_log_exception(self):
|
||||||
|
exc_info = sys.exc_info()
|
||||||
|
NovaExceptionReraiseFormatError.real_log_exception(self)
|
||||||
|
six.reraise(*exc_info)
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE(melwitt) This needs to be done at import time in order to also catch
|
||||||
|
# NovaException format errors that are in mock decorators. In these cases, the
|
||||||
|
# errors will be raised during test listing, before tests actually run.
|
||||||
|
NovaExceptionReraiseFormatError.patch()
|
||||||
|
|
||||||
|
|
||||||
class TestCase(testtools.TestCase):
|
class TestCase(testtools.TestCase):
|
||||||
"""Test case base class for all unit tests.
|
"""Test case base class for all unit tests.
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
|
import fixtures
|
||||||
import mock
|
import mock
|
||||||
import six
|
import six
|
||||||
from webob.util import status_reasons
|
from webob.util import status_reasons
|
||||||
@@ -211,6 +212,13 @@ class NovaExceptionTestCase(test.NoDBTestCase):
|
|||||||
self.assertEqual("some message", exc.format_message())
|
self.assertEqual("some message", exc.format_message())
|
||||||
|
|
||||||
def test_format_message_remote_error(self):
|
def test_format_message_remote_error(self):
|
||||||
|
# NOTE(melwitt): This test checks that errors are formatted as expected
|
||||||
|
# in a real environment where format errors are caught and not
|
||||||
|
# reraised, so we patch in the real implementation.
|
||||||
|
self.useFixture(fixtures.MonkeyPatch(
|
||||||
|
'nova.exception.NovaException._log_exception',
|
||||||
|
test.NovaExceptionReraiseFormatError.real_log_exception))
|
||||||
|
|
||||||
class FakeNovaException_Remote(exception.NovaException):
|
class FakeNovaException_Remote(exception.NovaException):
|
||||||
msg_fmt = "some message %(somearg)s"
|
msg_fmt = "some message %(somearg)s"
|
||||||
|
|
||||||
|
@@ -21,6 +21,7 @@ import oslo_messaging as messaging
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
import nova.conf
|
import nova.conf
|
||||||
|
from nova import exception
|
||||||
from nova import rpc
|
from nova import rpc
|
||||||
from nova import test
|
from nova import test
|
||||||
from nova.tests import fixtures
|
from nova.tests import fixtures
|
||||||
@@ -283,3 +284,20 @@ class ContainKeyValueTestCase(test.NoDBTestCase):
|
|||||||
# Raise KeyError
|
# Raise KeyError
|
||||||
self.assertNotEqual(matcher, {1: 2, '3': 4, 5: '6'})
|
self.assertNotEqual(matcher, {1: 2, '3': 4, 5: '6'})
|
||||||
self.assertNotEqual(matcher, {'bar': 'foo'})
|
self.assertNotEqual(matcher, {'bar': 'foo'})
|
||||||
|
|
||||||
|
|
||||||
|
class NovaExceptionReraiseFormatErrorTestCase(test.NoDBTestCase):
|
||||||
|
"""Test that format errors are reraised in tests."""
|
||||||
|
def test_format_error_in_nova_exception(self):
|
||||||
|
class FakeImageException(exception.NovaException):
|
||||||
|
msg_fmt = 'Image %(image_id)s has wrong type %(type)s.'
|
||||||
|
# wrong kwarg
|
||||||
|
ex = self.assertRaises(KeyError, FakeImageException,
|
||||||
|
bogus='wrongkwarg')
|
||||||
|
self.assertIn('image_id', six.text_type(ex))
|
||||||
|
# no kwarg
|
||||||
|
ex = self.assertRaises(KeyError, FakeImageException)
|
||||||
|
self.assertIn('image_id', six.text_type(ex))
|
||||||
|
# not enough kwargs
|
||||||
|
ex = self.assertRaises(KeyError, FakeImageException, image_id='image')
|
||||||
|
self.assertIn('type', six.text_type(ex))
|
||||||
|
Reference in New Issue
Block a user