From ba02fdc1df58eb530b0d86bfa3daed8af23aff59 Mon Sep 17 00:00:00 2001 From: Ilya Tyaptin Date: Wed, 29 Apr 2015 14:30:25 +0300 Subject: [unittest] Increase client and shell modules cover Add tests to increase unittest coverage of ceilometerclient.client, ceilometerclient.shell, ceilometerclient.v2.shell. Change-Id: I83a64ee31d6068a5903ef85ec85d5780828a24d7 --- ceilometerclient/tests/unit/test_client.py | 151 ++++++++++++++++++++++++ ceilometerclient/tests/unit/test_shell.py | 32 +++-- ceilometerclient/tests/unit/v2/test_shell.py | 169 ++++++++++++++++++++++++++- 3 files changed, 339 insertions(+), 13 deletions(-) diff --git a/ceilometerclient/tests/unit/test_client.py b/ceilometerclient/tests/unit/test_client.py index adfacc5..568af05 100644 --- a/ceilometerclient/tests/unit/test_client.py +++ b/ceilometerclient/tests/unit/test_client.py @@ -12,10 +12,15 @@ import types +from keystoneclient.auth.identity import v2 as v2_auth +from keystoneclient.auth.identity import v3 as v3_auth +from keystoneclient import exceptions as ks_exc from keystoneclient import session as ks_session import mock from ceilometerclient import client +from ceilometerclient import exc +from ceilometerclient.openstack.common.apiclient import exceptions from ceilometerclient.tests.unit import fakes from ceilometerclient.tests.unit import utils from ceilometerclient.v1 import client as v1client @@ -179,3 +184,149 @@ class ClientTest2(ClientTest): # Run the same tests with direct instantiation of the Client return client.Client(api_version, endpoint, **env) + + +class ClientAuthTest(utils.BaseTestCase): + + @staticmethod + def create_client(env, api_version=2, endpoint=None, exclude=[]): + env = dict((k, v) for k, v in env.items() + if k not in exclude) + + return client.get_client(api_version, **env) + + @mock.patch('keystoneclient.discover.Discover') + @mock.patch('keystoneclient.session.Session') + def test_discover_auth_versions(self, session, discover_mock): + env = FAKE_ENV.copy() + env.pop('auth_plugin', None) + + mock_session_instance = mock.MagicMock() + session.return_value = mock_session_instance + + client = self.create_client(env) + client.auth_plugin.opts.pop('token', None) + client.auth_plugin._do_authenticate(mock.MagicMock()) + + discover_mock.assert_called(auth_url='http://no.where', + session=mock_session_instance) + self.assertIsInstance(mock_session_instance.auth, v3_auth.Password) + + @mock.patch('keystoneclient.discover.Discover') + @mock.patch('keystoneclient.session.Session') + def test_discover_auth_versions_v2_only(self, session, discover): + env = FAKE_ENV.copy() + env.pop('auth_plugin', None) + env.pop('user_domain_name', None) + env.pop('user_domain_id', None) + env.pop('project_domain_name', None) + env.pop('project_domain_id', None) + + session_instance_mock = mock.MagicMock() + session.return_value = session_instance_mock + + discover_instance_mock = mock.MagicMock() + discover_instance_mock.url_for.side_effect = (lambda v: v + if v == '2.0' else None) + discover.return_value = discover_instance_mock + + client = self.create_client(env) + client.auth_plugin.opts.pop('token', None) + client.auth_plugin._do_authenticate(mock.MagicMock()) + + discover.assert_called(auth_url='http://no.where', + session=session_instance_mock) + self.assertIsInstance(session_instance_mock.auth, v2_auth.Password) + + @mock.patch('keystoneclient.discover.Discover') + @mock.patch('keystoneclient.session.Session') + def test_discover_auth_versions_raise_discovery_failure(self, + session, + discover): + env = FAKE_ENV.copy() + env.pop('auth_plugin', None) + + session_instance_mock = mock.MagicMock() + session.return_value = session_instance_mock + + discover_instance_mock = mock.MagicMock() + discover_instance_mock.url_for.side_effect = (lambda v: v + if v == '2.0' else None) + discover.side_effect = ks_exc.DiscoveryFailure + + client = self.create_client(env) + client.auth_plugin.opts.pop('token', None) + + self.assertRaises(ks_exc.DiscoveryFailure, + client.auth_plugin._do_authenticate, + mock.Mock()) + discover.assert_called(auth_url='http://no.where', + session=session_instance_mock) + + @mock.patch('keystoneclient.discover.Discover') + @mock.patch('keystoneclient.session.Session') + def test_discover_auth_versions_raise_command_err(self, session, discover): + env = FAKE_ENV.copy() + env.pop('auth_plugin', None) + + session_instance_mock = mock.MagicMock() + session.return_value = session_instance_mock + + discover.side_effect = exceptions.ClientException + + client = self.create_client(env) + client.auth_plugin.opts.pop('token', None) + + self.assertRaises(exc.CommandError, + client.auth_plugin._do_authenticate, + mock.Mock()) + + @mock.patch('ceilometerclient.client._get_keystone_session') + def test_get_endpoint(self, session): + env = FAKE_ENV.copy() + env.pop('auth_plugin', None) + env.pop('endpoint', None) + + session_instance_mock = mock.MagicMock() + session.return_value = session_instance_mock + + client = self.create_client(env) + client.auth_plugin.opts.pop('token', None) + client.auth_plugin.opts.pop('endpoint') + client.auth_plugin._do_authenticate(mock.MagicMock()) + session_instance_mock.get_endpoint.assert_called_with( + region_name=None, interface='publicURL', service_type='metering') + + @mock.patch('ceilometerclient.client._get_keystone_session') + def test_get_different_endpoint_type(self, session): + env = FAKE_ENV.copy() + env.pop('auth_plugin', None) + env.pop('endpoint', None) + env['endpoint_type'] = 'internal' + + session_instance_mock = mock.MagicMock() + session.return_value = session_instance_mock + + client = self.create_client(env) + client.auth_plugin.opts.pop('token', None) + client.auth_plugin.opts.pop('endpoint') + client.auth_plugin._do_authenticate(mock.MagicMock()) + session_instance_mock.get_endpoint.assert_called_with( + region_name=None, interface='internal', service_type='metering') + + @mock.patch('ceilometerclient.client._get_keystone_session') + def test_get_sufficient_options_missing(self, session): + env = FAKE_ENV.copy() + env.pop('auth_plugin', None) + env.pop('password', None) + env.pop('endpoint', None) + env.pop('auth_token', None) + env.pop('tenant_name', None) + env.pop('username', None) + + session_instance_mock = mock.MagicMock() + session.return_value = session_instance_mock + client = self.create_client(env) + client.auth_plugin.opts.pop('endpoint', None) + self.assertRaises(exceptions.AuthPluginOptionsMissing, + client.auth_plugin.sufficient_options) diff --git a/ceilometerclient/tests/unit/test_shell.py b/ceilometerclient/tests/unit/test_shell.py index 6dd1157..4f8dd4f 100644 --- a/ceilometerclient/tests/unit/test_shell.py +++ b/ceilometerclient/tests/unit/test_shell.py @@ -39,15 +39,6 @@ FAKE_V3_ENV = {'OS_USERNAME': 'username', class ShellTestBase(utils.BaseTestCase): - # Patch os.environ to avoid required auth info. - def make_env(self, env_version, exclude=None): - env = dict((k, v) for k, v in env_version.items() if k != exclude) - self.useFixture(fixtures.MonkeyPatch('os.environ', env)) - - -class ShellHelpTest(ShellTestBase): - RE_OPTIONS = re.DOTALL | re.MULTILINE - @mock.patch('sys.stdout', new=six.StringIO()) @mock.patch.object(ks_session, 'Session', mock.MagicMock()) @mock.patch.object(v2client.client.HTTPClient, @@ -62,6 +53,15 @@ class ShellHelpTest(ShellTestBase): return sys.stdout.getvalue() + # Patch os.environ to avoid required auth info. + def make_env(self, env_version, exclude=None): + env = dict((k, v) for k, v in env_version.items() if k != exclude) + self.useFixture(fixtures.MonkeyPatch('os.environ', env)) + + +class ShellHelpTest(ShellTestBase): + RE_OPTIONS = re.DOTALL | re.MULTILINE + def test_help_unknown_command(self): self.assertRaises(exc.CommandError, self.shell, 'help foofoo') @@ -98,6 +98,18 @@ class ShellHelpTest(ShellTestBase): self.assertEqual(600, parser.get_default('timeout')) +class ShellBashCompletionTest(ShellTestBase): + + def test_bash_completion(self): + completion_commands = self.shell("bash-completion") + options = completion_commands.split(' ') + self.assertNotIn('bash-completion', options) + self.assertNotIn('bash_completion', options) + for option in options: + self.assertThat(option, + matchers.MatchesRegex(r'[a-z0-9-]')) + + class ShellKeystoneV2Test(ShellTestBase): @mock.patch.object(ks_session, 'Session') @@ -177,7 +189,7 @@ class ShellTimeoutTest(ShellTestBase): self._test_timeout('0', expected_msg) @mock.patch.object(ks_session, 'Session') - def test_timeout_kesytone_session(self, mocked_session): + def test_timeout_keystone_session(self, mocked_session): mocked_session.side_effect = exc.HTTPUnauthorized("FAIL") self.make_env(FAKE_V2_ENV) args = ['--debug', '--timeout', '5', 'alarm-list'] diff --git a/ceilometerclient/tests/unit/v2/test_shell.py b/ceilometerclient/tests/unit/v2/test_shell.py index a49029d..109cb56 100644 --- a/ceilometerclient/tests/unit/v2/test_shell.py +++ b/ceilometerclient/tests/unit/v2/test_shell.py @@ -28,10 +28,14 @@ from ceilometerclient.tests.unit import test_shell from ceilometerclient.tests.unit import utils from ceilometerclient.v2 import alarms from ceilometerclient.v2 import capabilities +from ceilometerclient.v2 import event_types from ceilometerclient.v2 import events +from ceilometerclient.v2 import meters from ceilometerclient.v2 import samples from ceilometerclient.v2 import shell as ceilometer_shell from ceilometerclient.v2 import statistics +from ceilometerclient.v2 import trait_descriptions +from ceilometerclient.v2 import traits class ShellAlarmStateCommandsTest(utils.BaseTestCase): @@ -505,6 +509,13 @@ class ShellSampleShowCommandTest(utils.BaseTestCase): +-------------+--------------------------------------+ ''', sys.stdout.getvalue()) + @mock.patch('sys.stdout', new=six.StringIO()) + def test_sample_show_raises_command_err(self): + self.cc.new_samples.get.return_value = None + + self.assertRaises(exc.CommandError, ceilometer_shell.do_sample_show, + self.cc, self.args) + class ShellSampleCreateCommandTest(utils.BaseTestCase): @@ -523,8 +534,8 @@ class ShellSampleCreateCommandTest(utils.BaseTestCase): u'counter_unit': u'instance', u'counter_volume': 1.0, u'project_id': u'384260c6987b451d8290e66e1f108082', - u'resource_metadata': {}, - u'counter_type': u'gauge' + u'counter_type': u'gauge', + u'resource_metadata': {u'display_name': u'test_name'} }] def setUp(self): @@ -554,7 +565,7 @@ class ShellSampleCreateCommandTest(utils.BaseTestCase): | name | instance | | project_id | 384260c6987b451d8290e66e1f108082 | | resource_id | 0564c64c-3545-4e34-abfb-9d18e5f2f2f9 | -| resource_metadata | {} | +| resource_metadata | {"display_name": "test_name"} | | source | 384260c6987b451d8290e66e1f108082: openstack | | timestamp | 2014-01-10T03: 05: 33.951170 | | type | gauge | @@ -615,6 +626,14 @@ class ShellQuerySamplesCommandTest(utils.BaseTestCase): -+----------------------------+ ''', sys.stdout.getvalue()) + @mock.patch('sys.stdout', new=six.StringIO()) + def test_query_raises_command_error(self): + self.cc.query_samples.query.side_effect = exc.HTTPNotFound + + self.assertRaises(exc.CommandError, + ceilometer_shell.do_query_samples, + self.cc, self.args) + class ShellQueryAlarmsCommandTest(utils.BaseTestCase): @@ -719,6 +738,13 @@ class ShellQueryAlarmsCommandTest(utils.BaseTestCase): -----------------------------------------------+------------------+ ''', sys.stdout.getvalue()) + @mock.patch('sys.stdout', new=six.StringIO()) + def test_query_raises_command_err(self): + self.cc.query_alarms.query.side_effect = exc.HTTPNotFound + self.assertRaises(exc.CommandError, + ceilometer_shell.do_query_alarms, + self.cc, self.args) + class ShellQueryAlarmHistoryCommandTest(utils.BaseTestCase): @@ -772,6 +798,13 @@ rule change | {"threshold": 42.0, "evaluation_periods": 4} | 2014-03-11T16:0\ ------------+ ''', sys.stdout.getvalue()) + @mock.patch('sys.stdout', new=six.StringIO()) + def test_query_raises_command_err(self): + self.cc.query_alarm_history.query.side_effect = exc.HTTPNotFound + self.assertRaises(exc.CommandError, + ceilometer_shell.do_query_alarm_history, + self.cc, self.args) + class ShellStatisticsTest(utils.BaseTestCase): def setUp(self): @@ -1222,3 +1255,133 @@ class ShellCapabilityShowTest(utils.BaseTestCase): | storage | "storage:production_ready": true | +---------------+----------------------------------+ ''', sys.stdout.getvalue()) + + +class ShellMeterListCommandTest(utils.BaseTestCase): + + METER = { + "name": 'image', + "resource_id": "resource-id", + "meter": "image", + "project_id": "project", + "type": "gauge", + "unit": "image", + } + + def setUp(self): + super(ShellMeterListCommandTest, self).setUp() + self.cc = mock.Mock() + self.cc.meters.list = mock.Mock() + self.args = mock.MagicMock() + + @mock.patch('sys.stdout', new=six.StringIO()) + def test_meter_list(self): + meter = meters.Meter(mock.Mock(), self.METER) + self.cc.meters.list.return_value = [meter] + + ceilometer_shell.do_meter_list(self.cc, self.args) + self.cc.meters.list.assert_called_once_with(q=[]) + + self.assertEqual('''\ ++-------+-------+-------+-------------+---------+------------+ +| Name | Type | Unit | Resource ID | User ID | Project ID | ++-------+-------+-------+-------------+---------+------------+ +| image | gauge | image | resource-id | | project | ++-------+-------+-------+-------------+---------+------------+ +''', sys.stdout.getvalue()) + + +class ShellEventTypeListCommandTest(utils.BaseTestCase): + + EVENT_TYPE = { + "event_type": "test_event" + } + + def setUp(self): + super(ShellEventTypeListCommandTest, self).setUp() + self.cc = mock.Mock() + self.cc.event_types.list = mock.Mock() + self.args = mock.Mock() + + @mock.patch('sys.stdout', new=six.StringIO()) + def test_sample_show(self): + event_type = event_types.EventType(mock.Mock(), self.EVENT_TYPE) + self.cc.event_types.list.return_value = [event_type] + + ceilometer_shell.do_event_type_list(self.cc, self.args) + self.cc.event_types.list.assert_called_once_with() + + self.assertEqual('''\ ++------------+ +| Event Type | ++------------+ +| test_event | ++------------+ +''', sys.stdout.getvalue()) + + +class ShellTraitsListCommandTest(utils.BaseTestCase): + + TRAIT = { + "name": "test", + "value": "test", + "type": "string", + } + + def setUp(self): + super(ShellTraitsListCommandTest, self).setUp() + self.cc = mock.Mock() + self.cc.traits.list = mock.Mock() + self.args = mock.Mock() + self.args.event_type = "test" + self.args.trait_name = "test" + + @mock.patch('sys.stdout', new=six.StringIO()) + def test_trait_list(self): + trait = traits.Trait(mock.Mock(), self.TRAIT) + self.cc.traits.list.return_value = [trait] + + ceilometer_shell.do_trait_list(self.cc, self.args) + self.cc.traits.list.assert_called_once_with(self.args.event_type, + self.args.trait_name) + + self.assertEqual('''\ ++------------+-------+-----------+ +| Trait Name | Value | Data Type | ++------------+-------+-----------+ +| test | test | string | ++------------+-------+-----------+ +''', sys.stdout.getvalue()) + + +class ShellTraitsDescriptionListCommandTest(utils.BaseTestCase): + + TRAIT_DESCRIPTION = { + "name": "test", + "type": "string", + } + + def setUp(self): + super(ShellTraitsDescriptionListCommandTest, self).setUp() + self.cc = mock.Mock() + self.cc.trait_descriptions.list = mock.Mock() + self.args = mock.Mock() + self.args.event_type = "test" + + @mock.patch('sys.stdout', new=six.StringIO()) + def test_traits_description_list(self): + trait_desc = trait_descriptions.TraitDescription( + mock.Mock(), self.TRAIT_DESCRIPTION) + self.cc.trait_descriptions.list.return_value = [trait_desc] + + ceilometer_shell.do_trait_description_list(self.cc, self.args) + self.cc.trait_descriptions.list.assert_called_once_with( + self.args.event_type) + + self.assertEqual('''\ ++------------+-----------+ +| Trait Name | Data Type | ++------------+-----------+ +| test | string | ++------------+-----------+ +''', sys.stdout.getvalue()) -- cgit v1.2.1