From 0c3199f93d4aceedae4959a8cdcb60ac3a76db8c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 29 Jul 2015 15:15:19 +0200 Subject: [PATCH] Fix error handling in the exception module on py3 * Replace dict.iteritems() with dict.items() in code handling errors in the exception module to fix Python 3 support. * Add new unit tests on the exception module Change-Id: Ib958421dbdd73fb442e17a8d0654c9eab8b7b70e --- oslo_versionedobjects/exception.py | 4 +- oslo_versionedobjects/tests/test_exception.py | 75 +++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 oslo_versionedobjects/tests/test_exception.py diff --git a/oslo_versionedobjects/exception.py b/oslo_versionedobjects/exception.py index c777aeb7..2eb41dcc 100644 --- a/oslo_versionedobjects/exception.py +++ b/oslo_versionedobjects/exception.py @@ -55,7 +55,7 @@ class ConvertedException(webob.exc.WSGIHTTPException): def _cleanse_dict(original): """Strip all admin_password, new_pass, rescue_pass keys from a dict.""" - return dict([(k, v) for k, v in original.iteritems() if "_pass" not in k]) + return dict([(k, v) for k, v in original.items() if "_pass" not in k]) def wrap_exception(notifier=None, get_notifier=None): @@ -124,7 +124,7 @@ class VersionedObjectsException(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.iteritems(): + for name, value in kwargs.items(): LOG.error("%s: %s" % (name, value)) # noqa if CONF.oslo_versionedobjects.fatal_exception_format_errors: diff --git a/oslo_versionedobjects/tests/test_exception.py b/oslo_versionedobjects/tests/test_exception.py new file mode 100644 index 00000000..7c1b2b61 --- /dev/null +++ b/oslo_versionedobjects/tests/test_exception.py @@ -0,0 +1,75 @@ +# Copyright 2011 Justin Santa Barbara +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_versionedobjects import exception +from oslo_versionedobjects import test + +import mock + + +notifier = mock.Mock() + + +class TestWrapper(object): + @exception.wrap_exception(notifier=notifier) + def raise_exc(self, context, exc, admin_password): + raise exc + + +class ExceptionTestCase(test.TestCase): + def test_wrap_exception_wrapped(self): + test = TestWrapper() + # Ensure that the original function is available in + # the __wrapped__ attribute + self.assertTrue(hasattr(test.raise_exc, '__wrapped__')) + + def test_wrap_exception(self): + context = "context" + exc = ValueError() + + test = TestWrapper() + notifier.reset_mock() + + # wrap_exception() must reraise the exception + self.assertRaises(ValueError, + test.raise_exc, context, exc, admin_password="xxx") + + # wrap_exception() strips admin_password from args + payload = {'args': {'self': None, 'context': context, 'exc': exc}, + 'exception': exc} + notifier.error.assert_called_once_with(context, 'raise_exc', payload) + + def test_vo_exception(self): + exc = exception.VersionedObjectsException() + self.assertEqual('An unknown exception occurred.', str(exc)) + self.assertEqual({'code': 500}, exc.kwargs) + + def test_object_action_error(self): + exc = exception.ObjectActionError(action='ACTION', reason='REASON', + code=123) + self.assertEqual('Object action ACTION failed because: REASON', + str(exc)) + self.assertEqual({'code': 123, 'action': 'ACTION', 'reason': 'REASON'}, + exc.kwargs) + + def test_constructor_format_error(self): + # Test error handling on formatting exception message in the + # VersionedObjectsException constructor + with mock.patch.object(exception, 'LOG') as log: + exc = exception.ObjectActionError() + + log.error.assert_called_with('code: 500') + + # Formatting failed: the message is the original format string + self.assertEqual(exception.ObjectActionError.msg_fmt, str(exc))