Update ExpectedException handling

Catch expected exceptions in a way that supports subclasses also being
seen as "expected."

Log a little more detail about unexpected exceptions in the ExecutorBase
so it is easier to add them to the list of expected exceptions.

Change-Id: I1bdd628eba717308f0afe1a889efd8711bad6296
Closes-bug: #1276163
This commit is contained in:
Doug Hellmann 2014-02-04 09:18:35 -08:00
parent 84298bd041
commit 7b13bc1888
3 changed files with 27 additions and 7 deletions

View File

@ -38,12 +38,16 @@ class ExecutorBase(object):
_LOG.debug('Expected exception during message handling (%s)' %
e.exc_info[1])
incoming.reply(failure=e.exc_info, log_failure=False)
except Exception:
except Exception as e:
# sys.exc_info() is deleted by LOG.exception().
exc_info = sys.exc_info()
_LOG.error('Exception during message handling',
_LOG.error('Exception during message handling: %s', e,
exc_info=exc_info)
incoming.reply(failure=exc_info)
# NOTE(dhellmann): Remove circular object reference
# between the current stack frame and the traceback in
# exc_info.
del exc_info
@abc.abstractmethod
def start(self):

View File

@ -151,10 +151,13 @@ def expected_exceptions(*exceptions):
def inner(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
if type(e) in exceptions:
raise ExpectedException()
else:
raise
# Take advantage of the fact that we can catch
# multiple exception types using a tuple of
# exception classes, with subclass detection
# for free. Any exception that is not in or
# derived from the args passed to us will be
# ignored and thrown as normal.
except exceptions:
raise ExpectedException()
return inner
return outer

View File

@ -43,6 +43,19 @@ class TestExpectedExceptions(test_utils.BaseTestCase):
self.assertRaises(messaging.ExpectedException, naughty)
def test_decorator_expected_subclass(self):
class FooException(Exception):
pass
class BarException(FooException):
pass
@messaging.expected_exceptions(FooException)
def naughty():
raise BarException()
self.assertRaises(messaging.ExpectedException, naughty)
def test_decorator_unexpected(self):
class FooException(Exception):
pass