From dc9b711a3fa494e6d363657eeb8c2049585d5976 Mon Sep 17 00:00:00 2001 From: Ben Nemec Date: Mon, 3 Jun 2019 17:59:08 +0000 Subject: [PATCH] Add unit tests for validator We need to bump our minimum version for mock to 3.0.0 in order for mocking of 'open' to work correctly with the ConfigParser. From the mock changelog: "Issue #32933: unittest.mock.mock_open() now supports iteration over the file contents." Change-Id: I9522083b7b0f785fe0e9cbdf8a9042112820bed4 --- lower-constraints.txt | 2 +- oslo_config/tests/test_validator.py | 114 ++++++++++++++++++++++++++++ oslo_config/validator.py | 10 ++- test-requirements.txt | 2 +- 4 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 oslo_config/tests/test_validator.py diff --git a/lower-constraints.txt b/lower-constraints.txt index a68ae4fe..ccfe33b7 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -20,7 +20,7 @@ keystoneauth1==3.4.0 linecache2==1.0.0 MarkupSafe==1.0 mccabe==0.2.1 -mock==2.0.0 +mock==3.0.0 mox3==0.20.0 netaddr==0.7.18 openstackdocstheme==1.18.1 diff --git a/oslo_config/tests/test_validator.py b/oslo_config/tests/test_validator.py new file mode 100644 index 00000000..9d4aef8c --- /dev/null +++ b/oslo_config/tests/test_validator.py @@ -0,0 +1,114 @@ +# Copyright 2019 Red Hat, 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. + +import mock +from oslotest import base +import six + +from oslo_config import cfg +from oslo_config import fixture +from oslo_config import validator + + +OPT_DATA = {'options': {'foo': {'opts': [{'name': 'opt'}]}, + 'bar': {'opts': [{'name': 'opt'}]}, + }, + 'deprecated_options': {'bar': [{'name': 'opt'}]}} +VALID_CONF = """ +[foo] +opt = value +""" +DEPRECATED_CONF = """ +[bar] +opt = value +""" +INVALID_CONF = """ +[foo] +opts = value +""" +MISSING_GROUP_CONF = """ +[oo] +opt = value +""" + + +class TestValidator(base.BaseTestCase): + def setUp(self): + super(TestValidator, self).setUp() + self.conf = cfg.ConfigOpts() + self.conf_fixture = self.useFixture(fixture.Config(self.conf)) + validator._register_cli_opts(self.conf) + if six.PY2: + self.open_name = '__builtin__.open' + else: + self.open_name = 'builtins.open' + + @mock.patch('oslo_config.validator.load_opt_data') + def test_passing(self, mock_lod): + mock_lod.return_value = OPT_DATA + self.conf_fixture.config(opt_data='mocked.yaml', + input_file='mocked.conf') + m = mock.mock_open(read_data=VALID_CONF) + with mock.patch(self.open_name, m): + self.assertEqual(0, validator._validate(self.conf)) + + @mock.patch('oslo_config.validator.load_opt_data') + def test_deprecated(self, mock_lod): + mock_lod.return_value = OPT_DATA + self.conf_fixture.config(opt_data='mocked.yaml', + input_file='mocked.conf') + m = mock.mock_open(read_data=DEPRECATED_CONF) + with mock.patch(self.open_name, m): + self.assertEqual(0, validator._validate(self.conf)) + + @mock.patch('oslo_config.validator.load_opt_data') + def test_deprecated_fatal_warnings(self, mock_lod): + mock_lod.return_value = OPT_DATA + self.conf_fixture.config(opt_data='mocked.yaml', + input_file='mocked.conf', + fatal_warnings=True) + m = mock.mock_open(read_data=DEPRECATED_CONF) + with mock.patch(self.open_name, m): + self.assertEqual(1, validator._validate(self.conf)) + + @mock.patch('oslo_config.validator.load_opt_data') + def test_missing(self, mock_lod): + mock_lod.return_value = OPT_DATA + self.conf_fixture.config(opt_data='mocked.yaml', + input_file='mocked.conf') + m = mock.mock_open(read_data=INVALID_CONF) + with mock.patch(self.open_name, m): + self.assertEqual(1, validator._validate(self.conf)) + + @mock.patch('oslo_config.validator.load_opt_data') + def test_missing_group(self, mock_lod): + mock_lod.return_value = OPT_DATA + self.conf_fixture.config(opt_data='mocked.yaml', + input_file='mocked.conf') + m = mock.mock_open(read_data=MISSING_GROUP_CONF) + with mock.patch(self.open_name, m): + self.assertEqual(1, validator._validate(self.conf)) + + @mock.patch('oslo_config.validator.load_opt_data') + def test_exclude_groups(self, mock_lod): + mock_lod.return_value = OPT_DATA + self.conf_fixture.config(opt_data='mocked.yaml', + input_file='mocked.conf', + exclude_group=['oo']) + m = mock.mock_open(read_data=MISSING_GROUP_CONF) + with mock.patch(self.open_name, m): + self.assertEqual(0, validator._validate(self.conf)) + + def test_invalid_options(self): + self.assertRaises(RuntimeError, validator._validate, self.conf) diff --git a/oslo_config/validator.py b/oslo_config/validator.py index 6f8771e2..268c672c 100644 --- a/oslo_config/validator.py +++ b/oslo_config/validator.py @@ -85,17 +85,21 @@ def _validate_opt(group, option, opt_data): return option in name_data +def load_opt_data(conf): + with open(conf.opt_data) as f: + return yaml.safe_load(f) + + def _validate(conf): conf.register_opts(_validator_opts) if conf.namespace: groups = generator._get_groups(generator._list_opts(conf.namespace)) opt_data = generator._generate_machine_readable_data(groups, conf) elif conf.opt_data: - with open(conf.opt_data) as f: - opt_data = yaml.safe_load(f) + opt_data = load_opt_data(conf) else: # TODO(bnemec): Implement this logic with group? - raise RuntimeError('Neither namespace or opt-data provided.') + raise RuntimeError('Neither namespace nor opt-data provided.') sections = {} parser = cfg.ConfigParser(conf.input_file, sections) parser.parse() diff --git a/test-requirements.txt b/test-requirements.txt index dab06dda..ce22df63 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -24,7 +24,7 @@ sphinx!=1.6.6,!=1.6.7,>=1.6.2,<2.0.0;python_version=='2.7' # BSD sphinx!=1.6.6,!=1.6.7,>=1.6.2;python_version>='3.4' # BSD # mocking framework -mock>=2.0.0 # BSD +mock>=3.0.0 # BSD requests_mock>=1.5.0 # Apache-2.0 # Bandit security code scanner