Merge "Make NovaException format errors fatal for tests"

This commit is contained in:
Jenkins
2017-05-17 00:26:21 +00:00
committed by Gerrit Code Review
4 changed files with 58 additions and 6 deletions

View File

@@ -86,17 +86,21 @@ class NovaException(Exception):
message = self.msg_fmt % kwargs
except Exception:
# 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 kwargs.items():
LOG.error("%s: %s" % (name, value)) # noqa
# NOTE(melwitt): This is done in a separate method so it can be
# monkey-patched during testing to make it a hard failure.
self._log_exception()
message = self.msg_fmt
self.message = 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):
# NOTE(mrodden): use the first argument to the python Exception object
# which should be our full NovaException message, (see __init__)

View File

@@ -31,6 +31,7 @@ import datetime
import inspect
import os
import pprint
import sys
import fixtures
import mock
@@ -49,6 +50,7 @@ import testtools
from nova import context
from nova import db
from nova import exception
from nova.network import manager as network_manager
from nova.network.security_group import openstack_driver
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()
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):
"""Test case base class for all unit tests.

View File

@@ -16,6 +16,7 @@
import inspect
import fixtures
import mock
import six
from webob.util import status_reasons
@@ -211,6 +212,13 @@ class NovaExceptionTestCase(test.NoDBTestCase):
self.assertEqual("some message", exc.format_message())
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):
msg_fmt = "some message %(somearg)s"

View File

@@ -21,6 +21,7 @@ import oslo_messaging as messaging
import six
import nova.conf
from nova import exception
from nova import rpc
from nova import test
from nova.tests import fixtures
@@ -283,3 +284,20 @@ class ContainKeyValueTestCase(test.NoDBTestCase):
# Raise KeyError
self.assertNotEqual(matcher, {1: 2, '3': 4, 5: '6'})
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))