# -*- coding: utf-8 -*- # Copyright 2014 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. try: from unittest.case import TestCase except ImportError: # Required for python 2.6 from unittest2.case import TestCase import mock from StringIO import StringIO from fuel_plugin_builder import errors class FakeFile(StringIO): """It's a fake file which returns StringIO when file opens with 'with' statement. NOTE(eli): We cannot use mock_open from mock library here, because it hangs when we use 'with' statement, and when we want to read file by chunks. """ def __enter__(self): return self def __exit__(self, *args): pass def writelines(self, lines): self.write(''.join(lines)) class BaseTestCase(TestCase): """Base class for test cases """ def method_was_not_called(self, method): """Checks that mocked method was not called """ self.assertEqual(method.call_count, 0) def called_times(self, method, count): """Checks that mocked method was called `count` times """ self.assertEqual(method.call_count, count) def mock_open(self, text, filename='some.yaml'): """Mocks builtin open function. Usage example: with mock.patch( '__builtin__.open', self.mock_open('file content') ): # call some methods that are used open() to read some # stuff internally """ fileobj = FakeFile(text) setattr(fileobj, 'name', filename) return mock.MagicMock(return_value=fileobj) def mock_methods(self, obj, methods): """Mocks methods for object :param obj: object for mocking :param methods: list of methods for mocking """ for method in methods: setattr(obj, method, mock.MagicMock()) @mock.patch('fuel_plugin_builder.validators.base.utils') class LegacyBaseValidatorTestCase(BaseTestCase): __test__ = False validator_class = None schema_class = None def setUp(self): self.plugin_path = '/tmp/plugin_path' self.validator = self.validator_class(self.plugin_path) def test_validate(self, _): mocked_methods = [ 'check_schemas', 'check_tasks', 'check_releases_paths', 'check_compatibility', ] self.check_validate(mocked_methods) def test_check_schemas(self, _): mocked_methods = [ 'check_env_config_attrs', 'validate_file_by_schema' ] self.mock_methods(self.validator, mocked_methods) self.validator.check_schemas() self.assertEqual( [mock.call(self.schema_class().metadata_schema, self.validator.meta_path), mock.call(self.schema_class().tasks_schema, self.validator.tasks_path)], self.validator.validate_file_by_schema.call_args_list) self.validator.check_env_config_attrs.assert_called_once_with() def test_check_releases_paths(self, utils_mock): utils_mock.parse_yaml.return_value = { 'releases': [{ 'deployment_scripts_path': '/tmp/deployment_scripts_path', 'repository_path': '/tmp/repository_path'}]} utils_mock.exists.return_value = True self.validator.check_releases_paths() self.assertEqual( utils_mock.exists.call_args_list, [mock.call('/tmp/deployment_scripts_path'), mock.call('/tmp/repository_path')]) def test_check_releases_paths_error(self, utils_mock): utils_mock.parse_yaml.return_value = { 'releases': [{ 'deployment_scripts_path': '/tmp/deployment_scripts_path', 'repository_path': '/tmp/repository_path'}]} utils_mock.exists.return_value = False with self.assertRaisesRegexp( errors.ReleasesDirectoriesError, 'Cannot find directories /tmp/deployment_scripts_path' ', /tmp/repository_path for release '): self.validator.check_releases_paths() def test_check_env_config_attrs_do_not_fail_if_empty(self, utils_mock): utils_mock.parse_yaml.return_value = None self.validator.check_env_config_attrs() def test_check_env_config_attrs_fail_if_none(self, utils_mock): utils_mock.parse_yaml.return_value = {'attributes': None} with self.assertRaisesRegexp( errors.ValidationError, "File '/tmp/plugin_path/environment_config.yaml', None " "is not of type 'object', value path 'attributes'"): self.validator.check_env_config_attrs() def test_check_env_config_attrs_checks_metadata(self, utils_mock): utils_mock.parse_yaml.return_value = { 'attributes': {'metadata': []}} with self.assertRaisesRegexp( errors.ValidationError, "File '/tmp/plugin_path/environment_config.yaml', \[\] is " "not of type 'object', value path 'attributes -> metadata'"): self.validator.check_env_config_attrs() def test_check_env_config_attrs_checks_attrs(self, utils_mock): utils_mock.parse_yaml.return_value = { 'attributes': { 'key1': { 'type': True, 'label': 'text', 'value': 'text', 'weight': 1}}} with self.assertRaisesRegexp( errors.ValidationError, "File '/tmp/plugin_path/environment_config.yaml', True is not " "of type 'string', value path 'attributes -> key1 -> type'"): self.validator.check_env_config_attrs() def test_check_env_config_attrs_generator_value(self, utils_mock): utils_mock.parse_yaml.return_value = { 'attributes': { 'key1': { 'type': 'hidden', 'label': '', 'value': {'generator': 'password'}, 'weight': 1}}} self.validator.check_env_config_attrs() def test_check_env_config_attrs_restriction_fails(self, utils_mock): utils_mock.parse_yaml.return_value = { 'attributes': { 'key1': { 'type': 'text', 'label': 'test', 'value': 'test', 'weight': 1, 'restrictions': [ { 'condition': 'false', 'action': 'disable' }, { 'condition': True, 'action': 'hide' } ] } } } with self.assertRaisesRegexp( errors.ValidationError, "File '/tmp/plugin_path/environment_config.yaml', True is not " "of type 'string', value path " "'attributes -> key1 -> restrictions -> 1 -> condition"): self.validator.check_env_config_attrs() def check_raised_exception(self, utils_mock, mock_data, err_msg, executed_method, err_type=errors.ValidationError): """Check if the given error with given type was raised. :param obj utils_mock: fuel_plugin_builder.utils mock :param List[dict] mock_data: mock data :param str err_msg: what error message is expected :param function executed_method: what method should be executed :param Exception err_type: what error type is expected """ utils_mock.parse_yaml.return_value = mock_data with self.assertRaisesRegexp(err_type, err_msg): executed_method() def check_validate(self, mocked_methods=[]): self.mock_methods(self.validator, mocked_methods) self.validator.validate() for method in mocked_methods: getattr(self.validator, method).assert_called_once_with()