diff options
| author | Steve Martinelli <s.martinelli@gmail.com> | 2016-09-05 22:14:33 -0700 |
|---|---|---|
| committer | Steve Martinelli <s.martinelli@gmail.com> | 2016-09-08 15:19:50 -0700 |
| commit | 39839def2e356e8d145be89380c73a71423cf06d (patch) | |
| tree | f53c090b7ded46554866436e9d687492d2cef487 /openstackclient/tests/unit/api | |
| parent | 7d1a5d0854c732681a130255ddc6abb2e9721a7a (diff) | |
| download | python-openstackclient-39839def2e356e8d145be89380c73a71423cf06d.tar.gz | |
move unit tests to new "unit" test module
this will better isolate the unit tests from the functional tests.
unfortunately, the "integration" tests had to be lumped into the
"unit" tests since we need the separation in testr.conf
Change-Id: Ifd12198c1f90e4e3c951c73bfa1884ab300d8ded
Diffstat (limited to 'openstackclient/tests/unit/api')
| -rw-r--r-- | openstackclient/tests/unit/api/__init__.py | 0 | ||||
| -rw-r--r-- | openstackclient/tests/unit/api/fakes.py | 56 | ||||
| -rw-r--r-- | openstackclient/tests/unit/api/test_api.py | 326 | ||||
| -rw-r--r-- | openstackclient/tests/unit/api/test_image_v1.py | 98 | ||||
| -rw-r--r-- | openstackclient/tests/unit/api/test_image_v2.py | 98 | ||||
| -rw-r--r-- | openstackclient/tests/unit/api/test_object_store_v1.py | 337 | ||||
| -rw-r--r-- | openstackclient/tests/unit/api/test_utils.py | 115 |
7 files changed, 1030 insertions, 0 deletions
diff --git a/openstackclient/tests/unit/api/__init__.py b/openstackclient/tests/unit/api/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/openstackclient/tests/unit/api/__init__.py diff --git a/openstackclient/tests/unit/api/fakes.py b/openstackclient/tests/unit/api/fakes.py new file mode 100644 index 00000000..26213a2f --- /dev/null +++ b/openstackclient/tests/unit/api/fakes.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. +# + +"""API Test Fakes""" + +from keystoneauth1 import session +from requests_mock.contrib import fixture + +from openstackclient.tests.unit import utils + + +RESP_ITEM_1 = { + 'id': '1', + 'name': 'alpha', + 'status': 'UP', + 'props': {'a': 1, 'b': 2}, +} +RESP_ITEM_2 = { + 'id': '2', + 'name': 'beta', + 'status': 'DOWN', + 'props': {'a': 2, 'b': 2}, +} +RESP_ITEM_3 = { + 'id': '3', + 'name': 'delta', + 'status': 'UP', + 'props': {'a': 3, 'b': 1}, +} + +LIST_RESP = [RESP_ITEM_1, RESP_ITEM_2] + +LIST_BODY = { + 'p1': 'xxx', + 'p2': 'yyy', +} + + +class TestSession(utils.TestCase): + + BASE_URL = 'https://api.example.com:1234/vX' + + def setUp(self): + super(TestSession, self).setUp() + self.sess = session.Session() + self.requests_mock = self.useFixture(fixture.Fixture()) diff --git a/openstackclient/tests/unit/api/test_api.py b/openstackclient/tests/unit/api/test_api.py new file mode 100644 index 00000000..5f4a0c1a --- /dev/null +++ b/openstackclient/tests/unit/api/test_api.py @@ -0,0 +1,326 @@ +# 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. +# + +"""Base API Library Tests""" + +from osc_lib import exceptions + +from openstackclient.api import api +from openstackclient.tests.unit.api import fakes as api_fakes + + +class TestKeystoneSession(api_fakes.TestSession): + + def setUp(self): + super(TestKeystoneSession, self).setUp() + self.api = api.KeystoneSession( + session=self.sess, + endpoint=self.BASE_URL, + ) + + def test_session_request(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz', + json=api_fakes.RESP_ITEM_1, + status_code=200, + ) + ret = self.api._request('GET', '/qaz') + self.assertEqual(api_fakes.RESP_ITEM_1, ret.json()) + + +class TestBaseAPI(api_fakes.TestSession): + + def setUp(self): + super(TestBaseAPI, self).setUp() + self.api = api.BaseAPI( + session=self.sess, + endpoint=self.BASE_URL, + ) + + def test_create_post(self): + self.requests_mock.register_uri( + 'POST', + self.BASE_URL + '/qaz', + json=api_fakes.RESP_ITEM_1, + status_code=202, + ) + ret = self.api.create('qaz') + self.assertEqual(api_fakes.RESP_ITEM_1, ret) + + def test_create_put(self): + self.requests_mock.register_uri( + 'PUT', + self.BASE_URL + '/qaz', + json=api_fakes.RESP_ITEM_1, + status_code=202, + ) + ret = self.api.create('qaz', method='PUT') + self.assertEqual(api_fakes.RESP_ITEM_1, ret) + + def test_delete(self): + self.requests_mock.register_uri( + 'DELETE', + self.BASE_URL + '/qaz', + status_code=204, + ) + ret = self.api.delete('qaz') + self.assertEqual(204, ret.status_code) + + # find tests + + def test_find_attr_by_id(self): + + # All first requests (by name) will fail in this test + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?name=1', + json={'qaz': []}, + status_code=200, + ) + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?id=1', + json={'qaz': [api_fakes.RESP_ITEM_1]}, + status_code=200, + ) + ret = self.api.find_attr('qaz', '1') + self.assertEqual(api_fakes.RESP_ITEM_1, ret) + + # value not found + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?name=0', + json={'qaz': []}, + status_code=200, + ) + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?id=0', + json={'qaz': []}, + status_code=200, + ) + self.assertRaises( + exceptions.CommandError, + self.api.find_attr, + 'qaz', + '0', + ) + + # Attribute other than 'name' + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?status=UP', + json={'qaz': [api_fakes.RESP_ITEM_1]}, + status_code=200, + ) + ret = self.api.find_attr('qaz', 'UP', attr='status') + self.assertEqual(api_fakes.RESP_ITEM_1, ret) + ret = self.api.find_attr('qaz', value='UP', attr='status') + self.assertEqual(api_fakes.RESP_ITEM_1, ret) + + def test_find_attr_by_name(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?name=alpha', + json={'qaz': [api_fakes.RESP_ITEM_1]}, + status_code=200, + ) + ret = self.api.find_attr('qaz', 'alpha') + self.assertEqual(api_fakes.RESP_ITEM_1, ret) + + # value not found + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?name=0', + json={'qaz': []}, + status_code=200, + ) + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?id=0', + json={'qaz': []}, + status_code=200, + ) + self.assertRaises( + exceptions.CommandError, + self.api.find_attr, + 'qaz', + '0', + ) + + # Attribute other than 'name' + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?status=UP', + json={'qaz': [api_fakes.RESP_ITEM_1]}, + status_code=200, + ) + ret = self.api.find_attr('qaz', 'UP', attr='status') + self.assertEqual(api_fakes.RESP_ITEM_1, ret) + ret = self.api.find_attr('qaz', value='UP', attr='status') + self.assertEqual(api_fakes.RESP_ITEM_1, ret) + + def test_find_attr_path_resource(self): + + # Test resource different than path + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/wsx?name=1', + json={'qaz': []}, + status_code=200, + ) + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/wsx?id=1', + json={'qaz': [api_fakes.RESP_ITEM_1]}, + status_code=200, + ) + ret = self.api.find_attr('wsx', '1', resource='qaz') + self.assertEqual(api_fakes.RESP_ITEM_1, ret) + + def test_find_bulk_none(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz', + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.find_bulk('qaz') + self.assertEqual(api_fakes.LIST_RESP, ret) + + def test_find_bulk_one(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz', + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.find_bulk('qaz', id='1') + self.assertEqual([api_fakes.LIST_RESP[0]], ret) + + ret = self.api.find_bulk('qaz', id='0') + self.assertEqual([], ret) + + ret = self.api.find_bulk('qaz', name='beta') + self.assertEqual([api_fakes.LIST_RESP[1]], ret) + + ret = self.api.find_bulk('qaz', error='bogus') + self.assertEqual([], ret) + + def test_find_bulk_two(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz', + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.find_bulk('qaz', id='1', name='alpha') + self.assertEqual([api_fakes.LIST_RESP[0]], ret) + + ret = self.api.find_bulk('qaz', id='1', name='beta') + self.assertEqual([], ret) + + ret = self.api.find_bulk('qaz', id='1', error='beta') + self.assertEqual([], ret) + + def test_find_bulk_dict(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz', + json={'qaz': api_fakes.LIST_RESP}, + status_code=200, + ) + ret = self.api.find_bulk('qaz', id='1') + self.assertEqual([api_fakes.LIST_RESP[0]], ret) + + # list tests + + def test_list_no_body(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL, + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.list('') + self.assertEqual(api_fakes.LIST_RESP, ret) + + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz', + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.list('qaz') + self.assertEqual(api_fakes.LIST_RESP, ret) + + def test_list_params(self): + params = {'format': 'json'} + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '?format=json', + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.list('', **params) + self.assertEqual(api_fakes.LIST_RESP, ret) + + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?format=json', + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.list('qaz', **params) + self.assertEqual(api_fakes.LIST_RESP, ret) + + def test_list_body(self): + self.requests_mock.register_uri( + 'POST', + self.BASE_URL + '/qaz', + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.list('qaz', body=api_fakes.LIST_BODY) + self.assertEqual(api_fakes.LIST_RESP, ret) + + def test_list_detailed(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz/details', + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.list('qaz', detailed=True) + self.assertEqual(api_fakes.LIST_RESP, ret) + + def test_list_filtered(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?attr=value', + json=api_fakes.LIST_RESP, + status_code=200, + ) + ret = self.api.list('qaz', attr='value') + self.assertEqual(api_fakes.LIST_RESP, ret) + + def test_list_wrapped(self): + self.requests_mock.register_uri( + 'GET', + self.BASE_URL + '/qaz?attr=value', + json={'responses': api_fakes.LIST_RESP}, + status_code=200, + ) + ret = self.api.list('qaz', attr='value') + self.assertEqual({'responses': api_fakes.LIST_RESP}, ret) diff --git a/openstackclient/tests/unit/api/test_image_v1.py b/openstackclient/tests/unit/api/test_image_v1.py new file mode 100644 index 00000000..e02ef381 --- /dev/null +++ b/openstackclient/tests/unit/api/test_image_v1.py @@ -0,0 +1,98 @@ +# 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. +# + +"""Image v1 API Library Tests""" + +from keystoneauth1 import session +from requests_mock.contrib import fixture + +from openstackclient.api import image_v1 +from openstackclient.tests.unit import utils + + +FAKE_PROJECT = 'xyzpdq' +FAKE_URL = 'http://gopher.com' + + +class TestImageAPIv1(utils.TestCase): + + def setUp(self): + super(TestImageAPIv1, self).setUp() + + sess = session.Session() + self.api = image_v1.APIv1(session=sess, endpoint=FAKE_URL) + self.requests_mock = self.useFixture(fixture.Fixture()) + + +class TestImage(TestImageAPIv1): + + PUB_PROT = { + 'id': '1', + 'name': 'pub1', + 'is_public': True, + 'protected': True, + } + PUB_NOPROT = { + 'id': '2', + 'name': 'pub2-noprot', + 'is_public': True, + 'protected': False, + } + NOPUB_PROT = { + 'id': '3', + 'name': 'priv3', + 'is_public': False, + 'protected': True, + } + NOPUB_NOPROT = { + 'id': '4', + 'name': 'priv4-noprot', + 'is_public': False, + 'protected': False, + } + LIST_IMAGE_RESP = [ + PUB_PROT, + PUB_NOPROT, + NOPUB_PROT, + NOPUB_NOPROT, + ] + + def test_image_list_no_options(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/v1/images', + json={'images': self.LIST_IMAGE_RESP}, + status_code=200, + ) + ret = self.api.image_list() + self.assertEqual(self.LIST_IMAGE_RESP, ret) + + def test_image_list_public(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/v1/images/detail', + json={'images': self.LIST_IMAGE_RESP}, + status_code=200, + ) + ret = self.api.image_list(public=True) + self.assertEqual([self.PUB_PROT, self.PUB_NOPROT], ret) + + def test_image_list_private(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/v1/images/detail', + json={'images': self.LIST_IMAGE_RESP}, + status_code=200, + ) + ret = self.api.image_list(private=True) + self.assertEqual([self.NOPUB_PROT, self.NOPUB_NOPROT], ret) diff --git a/openstackclient/tests/unit/api/test_image_v2.py b/openstackclient/tests/unit/api/test_image_v2.py new file mode 100644 index 00000000..5dbb51e0 --- /dev/null +++ b/openstackclient/tests/unit/api/test_image_v2.py @@ -0,0 +1,98 @@ +# 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. +# + +"""Image v2 API Library Tests""" + +from keystoneauth1 import session +from requests_mock.contrib import fixture + +from openstackclient.api import image_v2 +from openstackclient.tests.unit import utils + + +FAKE_PROJECT = 'xyzpdq' +FAKE_URL = 'http://gopher.com' + + +class TestImageAPIv2(utils.TestCase): + + def setUp(self): + super(TestImageAPIv2, self).setUp() + + sess = session.Session() + self.api = image_v2.APIv2(session=sess, endpoint=FAKE_URL) + self.requests_mock = self.useFixture(fixture.Fixture()) + + +class TestImage(TestImageAPIv2): + + PUB_PROT = { + 'id': '1', + 'name': 'pub1', + 'visibility': 'public', + 'protected': True, + } + PUB_NOPROT = { + 'id': '2', + 'name': 'pub2-noprot', + 'visibility': 'public', + 'protected': False, + } + NOPUB_PROT = { + 'id': '3', + 'name': 'priv3', + 'visibility': 'private', + 'protected': True, + } + NOPUB_NOPROT = { + 'id': '4', + 'name': 'priv4-noprot', + 'visibility': 'private', + 'protected': False, + } + LIST_IMAGE_RESP = [ + PUB_PROT, + PUB_NOPROT, + NOPUB_PROT, + NOPUB_NOPROT, + ] + + def test_image_list_no_options(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/v2/images', + json={'images': self.LIST_IMAGE_RESP}, + status_code=200, + ) + ret = self.api.image_list() + self.assertEqual(self.LIST_IMAGE_RESP, ret) + + def test_image_list_public(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/v2/images', + json={'images': [self.PUB_PROT, self.PUB_NOPROT]}, + status_code=200, + ) + ret = self.api.image_list(public=True) + self.assertEqual([self.PUB_PROT, self.PUB_NOPROT], ret) + + def test_image_list_private(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/v2/images', + json={'images': [self.NOPUB_PROT, self.NOPUB_NOPROT]}, + status_code=200, + ) + ret = self.api.image_list(public=True) + self.assertEqual([self.NOPUB_PROT, self.NOPUB_NOPROT], ret) diff --git a/openstackclient/tests/unit/api/test_object_store_v1.py b/openstackclient/tests/unit/api/test_object_store_v1.py new file mode 100644 index 00000000..acf95550 --- /dev/null +++ b/openstackclient/tests/unit/api/test_object_store_v1.py @@ -0,0 +1,337 @@ +# 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. +# + +"""Object Store v1 API Library Tests""" + +import mock + +from keystoneauth1 import session +from requests_mock.contrib import fixture + +from openstackclient.api import object_store_v1 as object_store +from openstackclient.tests.unit import utils + + +FAKE_ACCOUNT = 'q12we34r' +FAKE_AUTH = '11223344556677889900' +FAKE_URL = 'http://gopher.com/v1/' + FAKE_ACCOUNT + +FAKE_CONTAINER = 'rainbarrel' +FAKE_OBJECT = 'spigot' + +LIST_CONTAINER_RESP = [ + 'qaz', + 'fred', +] + +LIST_OBJECT_RESP = [ + {'name': 'fred', 'bytes': 1234, 'content_type': 'text'}, + {'name': 'wilma', 'bytes': 5678, 'content_type': 'text'}, +] + + +class TestObjectAPIv1(utils.TestCase): + + def setUp(self): + super(TestObjectAPIv1, self).setUp() + sess = session.Session() + self.api = object_store.APIv1(session=sess, endpoint=FAKE_URL) + self.requests_mock = self.useFixture(fixture.Fixture()) + + +class TestContainer(TestObjectAPIv1): + + def setUp(self): + super(TestContainer, self).setUp() + + def test_container_create(self): + headers = { + 'x-trans-id': '1qaz2wsx', + } + self.requests_mock.register_uri( + 'PUT', + FAKE_URL + '/qaz', + headers=headers, + status_code=201, + ) + ret = self.api.container_create(container='qaz') + data = { + 'account': FAKE_ACCOUNT, + 'container': 'qaz', + 'x-trans-id': '1qaz2wsx', + } + self.assertEqual(data, ret) + + def test_container_delete(self): + self.requests_mock.register_uri( + 'DELETE', + FAKE_URL + '/qaz', + status_code=204, + ) + ret = self.api.container_delete(container='qaz') + self.assertIsNone(ret) + + def test_container_list_no_options(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL, + json=LIST_CONTAINER_RESP, + status_code=200, + ) + ret = self.api.container_list() + self.assertEqual(LIST_CONTAINER_RESP, ret) + + def test_container_list_prefix(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '?prefix=foo%2f&format=json', + json=LIST_CONTAINER_RESP, + status_code=200, + ) + ret = self.api.container_list( + prefix='foo/', + ) + self.assertEqual(LIST_CONTAINER_RESP, ret) + + def test_container_list_marker_limit_end(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '?marker=next&limit=2&end_marker=stop&format=json', + json=LIST_CONTAINER_RESP, + status_code=200, + ) + ret = self.api.container_list( + marker='next', + limit=2, + end_marker='stop', + ) + self.assertEqual(LIST_CONTAINER_RESP, ret) + +# def test_container_list_full_listing(self): +# sess = self.app.client_manager.session +# +# def side_effect(*args, **kwargs): +# rv = sess.get().json.return_value +# sess.get().json.return_value = [] +# sess.get().json.side_effect = None +# return rv +# +# resp = [{'name': 'is-name'}] +# sess.get().json.return_value = resp +# sess.get().json.side_effect = side_effect +# +# data = lib_container.list_containers( +# self.app.client_manager.session, +# fake_url, +# full_listing=True, +# ) +# +# # Check expected values +# sess.get.assert_called_with( +# fake_url, +# params={ +# 'format': 'json', +# 'marker': 'is-name', +# } +# ) +# self.assertEqual(resp, data) + + def test_container_show(self): + headers = { + 'X-Container-Meta-Owner': FAKE_ACCOUNT, + 'x-container-object-count': '1', + 'x-container-bytes-used': '577', + } + resp = { + 'account': FAKE_ACCOUNT, + 'container': 'qaz', + 'object_count': '1', + 'bytes_used': '577', + 'properties': {'Owner': FAKE_ACCOUNT}, + } + self.requests_mock.register_uri( + 'HEAD', + FAKE_URL + '/qaz', + headers=headers, + status_code=204, + ) + ret = self.api.container_show(container='qaz') + self.assertEqual(resp, ret) + + +class TestObject(TestObjectAPIv1): + + def setUp(self): + super(TestObject, self).setUp() + + @mock.patch('openstackclient.api.object_store_v1.io.open') + def base_object_create(self, file_contents, mock_open): + mock_open.read.return_value = file_contents + + headers = { + 'etag': 'youreit', + 'x-trans-id': '1qaz2wsx', + } + # TODO(dtroyer): When requests_mock gains the ability to + # match against request.body add this check + # https://review.openstack.org/127316 + self.requests_mock.register_uri( + 'PUT', + FAKE_URL + '/qaz/counter.txt', + headers=headers, + # body=file_contents, + status_code=201, + ) + ret = self.api.object_create( + container='qaz', + object='counter.txt', + ) + data = { + 'account': FAKE_ACCOUNT, + 'container': 'qaz', + 'object': 'counter.txt', + 'etag': 'youreit', + 'x-trans-id': '1qaz2wsx', + } + self.assertEqual(data, ret) + + def test_object_create(self): + self.base_object_create('111\n222\n333\n') + self.base_object_create(bytes([0x31, 0x00, 0x0d, 0x0a, 0x7f, 0xff])) + + def test_object_delete(self): + self.requests_mock.register_uri( + 'DELETE', + FAKE_URL + '/qaz/wsx', + status_code=204, + ) + ret = self.api.object_delete( + container='qaz', + object='wsx', + ) + self.assertIsNone(ret) + + def test_object_list_no_options(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/qaz', + json=LIST_OBJECT_RESP, + status_code=200, + ) + ret = self.api.object_list(container='qaz') + self.assertEqual(LIST_OBJECT_RESP, ret) + + def test_object_list_delimiter(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/qaz?delimiter=%7C', + json=LIST_OBJECT_RESP, + status_code=200, + ) + ret = self.api.object_list( + container='qaz', + delimiter='|', + ) + self.assertEqual(LIST_OBJECT_RESP, ret) + + def test_object_list_prefix(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/qaz?prefix=foo%2f', + json=LIST_OBJECT_RESP, + status_code=200, + ) + ret = self.api.object_list( + container='qaz', + prefix='foo/', + ) + self.assertEqual(LIST_OBJECT_RESP, ret) + + def test_object_list_marker_limit_end(self): + self.requests_mock.register_uri( + 'GET', + FAKE_URL + '/qaz?marker=next&limit=2&end_marker=stop', + json=LIST_CONTAINER_RESP, + status_code=200, + ) + ret = self.api.object_list( + container='qaz', + marker='next', + limit=2, + end_marker='stop', + ) + self.assertEqual(LIST_CONTAINER_RESP, ret) + +# def test_list_objects_full_listing(self): +# sess = self.app.client_manager.session +# +# def side_effect(*args, **kwargs): +# rv = sess.get().json.return_value +# sess.get().json.return_value = [] +# sess.get().json.side_effect = None +# return rv +# +# resp = [{'name': 'is-name'}] +# sess.get().json.return_value = resp +# sess.get().json.side_effect = side_effect +# +# data = lib_object.list_objects( +# sess, +# fake_url, +# fake_container, +# full_listing=True, +# ) +# +# # Check expected values +# sess.get.assert_called_with( +# fake_url + '/' + fake_container, +# params={ +# 'format': 'json', +# 'marker': 'is-name', +# } +# ) +# self.assertEqual(resp, data) + + def test_object_show(self): + headers = { + 'content-type': 'text/alpha', + 'content-length': '577', + 'last-modified': '20130101', + 'etag': 'qaz', + 'x-container-meta-owner': FAKE_ACCOUNT, + 'x-object-meta-wife': 'Wilma', + 'x-object-meta-Husband': 'fred', + 'x-tra-header': 'yabba-dabba-do', + } + resp = { + 'account': FAKE_ACCOUNT, + 'container': 'qaz', + 'object': FAKE_OBJECT, + 'content-type': 'text/alpha', + 'content-length': '577', + 'last-modified': '20130101', + 'etag': 'qaz', + 'properties': {'wife': 'Wilma', + 'Husband': 'fred'}, + } + self.requests_mock.register_uri( + 'HEAD', + FAKE_URL + '/qaz/' + FAKE_OBJECT, + headers=headers, + status_code=204, + ) + ret = self.api.object_show( + container='qaz', + object=FAKE_OBJECT, + ) + self.assertEqual(resp, ret) diff --git a/openstackclient/tests/unit/api/test_utils.py b/openstackclient/tests/unit/api/test_utils.py new file mode 100644 index 00000000..1f528558 --- /dev/null +++ b/openstackclient/tests/unit/api/test_utils.py @@ -0,0 +1,115 @@ +# 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. +# + +"""API Utilities Library Tests""" + +import copy + +from openstackclient.api import api +from openstackclient.api import utils as api_utils +from openstackclient.tests.unit.api import fakes as api_fakes + + +class TestBaseAPIFilter(api_fakes.TestSession): + """The filters can be tested independently""" + + def setUp(self): + super(TestBaseAPIFilter, self).setUp() + self.api = api.BaseAPI( + session=self.sess, + endpoint=self.BASE_URL, + ) + + self.input_list = [ + api_fakes.RESP_ITEM_1, + api_fakes.RESP_ITEM_2, + api_fakes.RESP_ITEM_3, + ] + + def test_simple_filter_none(self): + output = api_utils.simple_filter( + ) + self.assertIsNone(output) + + def test_simple_filter_no_attr(self): + output = api_utils.simple_filter( + copy.deepcopy(self.input_list), + ) + self.assertEqual(self.input_list, output) + + def test_simple_filter_attr_only(self): + output = api_utils.simple_filter( + copy.deepcopy(self.input_list), + attr='status', + ) + self.assertEqual(self.input_list, output) + + def test_simple_filter_attr_value(self): + output = api_utils.simple_filter( + copy.deepcopy(self.input_list), + attr='status', + value='', + ) + self.assertEqual([], output) + + output = api_utils.simple_filter( + copy.deepcopy(self.input_list), + attr='status', + value='UP', + ) + self.assertEqual( + [api_fakes.RESP_ITEM_1, api_fakes.RESP_ITEM_3], + output, + ) + + output = api_utils.simple_filter( + copy.deepcopy(self.input_list), + attr='fred', + value='UP', + ) + self.assertEqual([], output) + + def test_simple_filter_prop_attr_only(self): + output = api_utils.simple_filter( + copy.deepcopy(self.input_list), + attr='b', + property_field='props', + ) + self.assertEqual(self.input_list, output) + + output = api_utils.simple_filter( + copy.deepcopy(self.input_list), + attr='status', + property_field='props', + ) + self.assertEqual(self.input_list, output) + + def test_simple_filter_prop_attr_value(self): + output = api_utils.simple_filter( + copy.deepcopy(self.input_list), + attr='b', + value=2, + property_field='props', + ) + self.assertEqual( + [api_fakes.RESP_ITEM_1, api_fakes.RESP_ITEM_2], + output, + ) + + output = api_utils.simple_filter( + copy.deepcopy(self.input_list), + attr='b', + value=9, + property_field='props', + ) + self.assertEqual([], output) |
