summaryrefslogtreecommitdiff
path: root/nova/tests/unit/test_hooks.py
diff options
context:
space:
mode:
Diffstat (limited to 'nova/tests/unit/test_hooks.py')
-rw-r--r--nova/tests/unit/test_hooks.py205
1 files changed, 205 insertions, 0 deletions
diff --git a/nova/tests/unit/test_hooks.py b/nova/tests/unit/test_hooks.py
new file mode 100644
index 0000000000..9017787151
--- /dev/null
+++ b/nova/tests/unit/test_hooks.py
@@ -0,0 +1,205 @@
+# Copyright (c) 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+# 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.
+
+"""Tests for hook customization."""
+
+import stevedore
+
+from nova import hooks
+from nova import test
+
+
+class SampleHookA(object):
+ name = "a"
+
+ def _add_called(self, op, kwargs):
+ called = kwargs.get('called', None)
+ if called is not None:
+ called.append(op + self.name)
+
+ def pre(self, *args, **kwargs):
+ self._add_called("pre", kwargs)
+
+
+class SampleHookB(SampleHookA):
+ name = "b"
+
+ def post(self, rv, *args, **kwargs):
+ self._add_called("post", kwargs)
+
+
+class SampleHookC(SampleHookA):
+ name = "c"
+
+ def pre(self, f, *args, **kwargs):
+ self._add_called("pre" + f.__name__, kwargs)
+
+ def post(self, f, rv, *args, **kwargs):
+ self._add_called("post" + f.__name__, kwargs)
+
+
+class SampleHookExceptionPre(SampleHookA):
+ name = "epre"
+ exception = Exception()
+
+ def pre(self, f, *args, **kwargs):
+ raise self.exception
+
+
+class SampleHookExceptionPost(SampleHookA):
+ name = "epost"
+ exception = Exception()
+
+ def post(self, f, rv, *args, **kwargs):
+ raise self.exception
+
+
+class MockEntryPoint(object):
+
+ def __init__(self, cls):
+ self.cls = cls
+
+ def load(self):
+ return self.cls
+
+
+class MockedHookTestCase(test.BaseHookTestCase):
+ def _mock_load_plugins(self, iload, *iargs, **ikwargs):
+ return []
+
+ def setUp(self):
+ super(MockedHookTestCase, self).setUp()
+
+ hooks.reset()
+
+ self.stubs.Set(stevedore.extension.ExtensionManager, '_load_plugins',
+ self._mock_load_plugins)
+
+
+class HookTestCase(MockedHookTestCase):
+ def _mock_load_plugins(self, iload, *iargs, **ikwargs):
+ return [
+ stevedore.extension.Extension('test_hook',
+ MockEntryPoint(SampleHookA), SampleHookA, SampleHookA()),
+ stevedore.extension.Extension('test_hook',
+ MockEntryPoint(SampleHookB), SampleHookB, SampleHookB()),
+ ]
+
+ def setUp(self):
+ super(HookTestCase, self).setUp()
+
+ hooks.reset()
+
+ self.stubs.Set(stevedore.extension.ExtensionManager, '_load_plugins',
+ self._mock_load_plugins)
+
+ @hooks.add_hook('test_hook')
+ def _hooked(self, a, b=1, c=2, called=None):
+ return 42
+
+ def test_basic(self):
+ self.assertEqual(42, self._hooked(1))
+
+ mgr = hooks._HOOKS['test_hook']
+ self.assert_has_hook('test_hook', self._hooked)
+ self.assertEqual(2, len(mgr.extensions))
+ self.assertEqual(SampleHookA, mgr.extensions[0].plugin)
+ self.assertEqual(SampleHookB, mgr.extensions[1].plugin)
+
+ def test_order_of_execution(self):
+ called_order = []
+ self._hooked(42, called=called_order)
+ self.assertEqual(['prea', 'preb', 'postb'], called_order)
+
+
+class HookTestCaseWithFunction(MockedHookTestCase):
+ def _mock_load_plugins(self, iload, *iargs, **ikwargs):
+ return [
+ stevedore.extension.Extension('function_hook',
+ MockEntryPoint(SampleHookC), SampleHookC, SampleHookC()),
+ ]
+
+ @hooks.add_hook('function_hook', pass_function=True)
+ def _hooked(self, a, b=1, c=2, called=None):
+ return 42
+
+ def test_basic(self):
+ self.assertEqual(42, self._hooked(1))
+ mgr = hooks._HOOKS['function_hook']
+
+ self.assert_has_hook('function_hook', self._hooked)
+ self.assertEqual(1, len(mgr.extensions))
+ self.assertEqual(SampleHookC, mgr.extensions[0].plugin)
+
+ def test_order_of_execution(self):
+ called_order = []
+ self._hooked(42, called=called_order)
+ self.assertEqual(['pre_hookedc', 'post_hookedc'], called_order)
+
+
+class HookFailPreTestCase(MockedHookTestCase):
+ def _mock_load_plugins(self, iload, *iargs, **ikwargs):
+ return [
+ stevedore.extension.Extension('fail_pre',
+ MockEntryPoint(SampleHookExceptionPre),
+ SampleHookExceptionPre, SampleHookExceptionPre()),
+ ]
+
+ @hooks.add_hook('fail_pre', pass_function=True)
+ def _hooked(self, a, b=1, c=2, called=None):
+ return 42
+
+ def test_hook_fail_should_still_return(self):
+ self.assertEqual(42, self._hooked(1))
+
+ mgr = hooks._HOOKS['fail_pre']
+ self.assert_has_hook('fail_pre', self._hooked)
+ self.assertEqual(1, len(mgr.extensions))
+ self.assertEqual(SampleHookExceptionPre, mgr.extensions[0].plugin)
+
+ def test_hook_fail_should_raise_fatal(self):
+ self.stubs.Set(SampleHookExceptionPre, 'exception',
+ hooks.FatalHookException())
+
+ self.assertRaises(hooks.FatalHookException,
+ self._hooked, 1)
+
+
+class HookFailPostTestCase(MockedHookTestCase):
+ def _mock_load_plugins(self, iload, *iargs, **ikwargs):
+ return [
+ stevedore.extension.Extension('fail_post',
+ MockEntryPoint(SampleHookExceptionPost),
+ SampleHookExceptionPost, SampleHookExceptionPost()),
+ ]
+
+ @hooks.add_hook('fail_post', pass_function=True)
+ def _hooked(self, a, b=1, c=2, called=None):
+ return 42
+
+ def test_hook_fail_should_still_return(self):
+ self.assertEqual(42, self._hooked(1))
+
+ mgr = hooks._HOOKS['fail_post']
+ self.assert_has_hook('fail_post', self._hooked)
+ self.assertEqual(1, len(mgr.extensions))
+ self.assertEqual(SampleHookExceptionPost, mgr.extensions[0].plugin)
+
+ def test_hook_fail_should_raise_fatal(self):
+ self.stubs.Set(SampleHookExceptionPost, 'exception',
+ hooks.FatalHookException())
+
+ self.assertRaises(hooks.FatalHookException,
+ self._hooked, 1)