From fd59720b1bfae9fe5a579a00ce6433b42a67472e Mon Sep 17 00:00:00 2001 From: Ekaterina Chernova Date: Thu, 3 Dec 2015 17:22:20 +0300 Subject: [PATCH] Add MockContextManager It is used in murano-test-runner. Mocks are inserted into new context, that is created from the current context: If mock for the current object exist, new linked context (``murano.dsl.linked_context.LinkedContext``) will be returned. It links existing context with the new context, where mock definition is presented. So if mocked function will be called, context will contain two definitions with that function: mock and original one, but mock will have higher priority. If there is no mock for the current object or class, existing context will be returned. If there is no existing context, *None* will be returned. Targets blueprint mock-context-manager Depends-On: I9eccdf3af1802c731bfdfb93df92c4ad902a4d34 Change-Id: I9a55d07188ff06bdf98248f011a700c297e33417 --- murano/cmd/test_runner.py | 7 +- murano/engine/mock_context_manager.py | 70 +++++++++++++++++++ .../unit/engine/test_mock_context_manager.py | 56 +++++++++++++++ 3 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 murano/engine/mock_context_manager.py create mode 100644 murano/tests/unit/engine/test_mock_context_manager.py diff --git a/murano/cmd/test_runner.py b/murano/cmd/test_runner.py index 434ecce4e..29c68023f 100755 --- a/murano/cmd/test_runner.py +++ b/murano/cmd/test_runner.py @@ -34,8 +34,10 @@ from murano.dsl import executor from murano.dsl import helpers from murano.engine import client_manager from murano.engine import environment +from murano.engine import mock_context_manager from murano.engine import package_loader + CONF = cfg.CONF LOG = logging.getLogger(__name__) options.set_defaults(CONF) @@ -220,12 +222,13 @@ class MuranoTestRunner(object): murano_client_factory, client.tenant_id) as pkg_loader: engine.get_plugin_loader().register_in_loader(pkg_loader) exc = executor.MuranoDslExecutor( - pkg_loader, engine.ContextManager(), test_env) + pkg_loader, + mock_context_manager.MockContextManager(), + test_env) package = self._load_package(pkg_loader, provided_pkg_name) class_to_methods, class_to_obj = self._get_all_test_methods( exc, package) - run_set = self._get_methods_to_run(package, tests_to_run, class_to_methods) diff --git a/murano/engine/mock_context_manager.py b/murano/engine/mock_context_manager.py new file mode 100644 index 000000000..13cbaf45d --- /dev/null +++ b/murano/engine/mock_context_manager.py @@ -0,0 +1,70 @@ +# Copyright (c) 2015 Mirantis Inc. +# +# 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 murano.common import engine +from murano.dsl import linked_context +from murano.dsl import yaql_integration + + +class MockContextManager(engine.ContextManager): + + def __init__(self): + # { object_id: [mock_function_definitions] } + self.obj_mock_ctx = {} + + # { class_name: [mock_function_definitions] } + self.class_mock_ctx = {} + + def _create_new_ctx(self, mock_funcs): + mock_context = yaql_integration.create_empty_context() + for mock_func in mock_funcs: + mock_context.register_function(mock_func) + return mock_context + + def _create_new_ctx_for_class(self, name): + new_context = None + if name in self.class_mock_ctx: + new_context = self._create_new_ctx(self.class_mock_ctx[name]) + return new_context + + def _create_new_ctx_for_obj(self, obj_id): + new_context = None + if obj_id in self.obj_mock_ctx: + new_context = self._create_new_ctx(self.obj_mock_ctx[obj_id]) + return new_context + + def create_class_context(self, murano_class): + original_context = super(MockContextManager, + self).create_class_context(murano_class) + + mock_context = self._create_new_ctx_for_class(murano_class.name) + if mock_context: + result_context = linked_context.link( + original_context, mock_context).create_child_context() + else: + result_context = original_context + return result_context + + def create_object_context(self, murano_obj): + original_context = super(MockContextManager, + self).create_object_context(murano_obj) + + mock_context = self._create_new_ctx_for_obj(murano_obj.type.name) + if mock_context: + result_context = linked_context.link( + original_context, mock_context).create_child_context() + else: + result_context = original_context + return result_context diff --git a/murano/tests/unit/engine/test_mock_context_manager.py b/murano/tests/unit/engine/test_mock_context_manager.py new file mode 100644 index 000000000..a6cdd6315 --- /dev/null +++ b/murano/tests/unit/engine/test_mock_context_manager.py @@ -0,0 +1,56 @@ +# 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. + +import mock +from yaql import contexts +from yaql import specs + +from murano.dsl import murano_class +from murano.engine import mock_context_manager +from murano.tests.unit import base + +FIXTURE_CLASS = 'io.murano.system.Agent' +FIXTURE_FUNC = 'call' + + +def _get_fd(set_to_extract): + return list(set_to_extract)[0] + + +class TestMockManager(base.MuranoTestCase): + + def test_create_class_context(self): + mock_manager = mock_context_manager.MockContextManager() + mock_murano_class = mock.MagicMock(spec=murano_class.MuranoClass) + mock_murano_class.name = FIXTURE_CLASS + original_function = mock.MagicMock(spec=specs.FunctionDefinition) + original_function.is_method = True + original_function.name = FIXTURE_FUNC + original_context = contexts.Context() + p = mock.patch("inspect.getargspec", new=mock.MagicMock()) + p.start() + original_context.register_function(original_function) + mock_murano_class.context = original_context + p.stop() + + mock_function = mock.MagicMock(spec=specs.FunctionDefinition) + mock_function.is_method = True + mock_function.name = FIXTURE_FUNC + + mock_manager.class_mock_ctx[FIXTURE_CLASS] = [mock_function] + + result_context = mock_manager.create_class_context(mock_murano_class) + all_functions = result_context.collect_functions(FIXTURE_FUNC) + + # Mock function should go first, but result context should contain both + self.assertIs(mock_function, _get_fd(all_functions[0])) + self.assertIs(original_function, _get_fd(all_functions[1]))