From 49063e5b7ac0dee98d67bcf6dfcead84a3786b69 Mon Sep 17 00:00:00 2001 From: wangxiyuan Date: Wed, 24 Feb 2016 17:10:30 +0800 Subject: [PATCH] Add tempest test for wsgi v2 This patch added the basic tempest test for wsgi v2. Change-Id: I530a13b0a68c3a8290cbcb2bb7ba05aaca993a92 --- .../api_schema/response/v2/__init__.py | 0 .../api_schema/response/v2/queues.py | 297 ++++++++++++++++++ .../messaging/json/messaging_client.py | 194 ++++++++++++ zaqar/tests/tempest_plugin/tests/base.py | 56 ++++ .../tests/tempest_plugin/tests/v2/__init__.py | 0 .../tempest_plugin/tests/v2/test_claims.py | 114 +++++++ .../tempest_plugin/tests/v2/test_messages.py | 121 +++++++ .../tempest_plugin/tests/v2/test_queues.py | 105 +++++++ .../tests/v2/test_subscriptions.py | 97 ++++++ 9 files changed, 984 insertions(+) create mode 100644 zaqar/tests/tempest_plugin/api_schema/response/v2/__init__.py create mode 100644 zaqar/tests/tempest_plugin/api_schema/response/v2/queues.py create mode 100644 zaqar/tests/tempest_plugin/tests/v2/__init__.py create mode 100644 zaqar/tests/tempest_plugin/tests/v2/test_claims.py create mode 100644 zaqar/tests/tempest_plugin/tests/v2/test_messages.py create mode 100644 zaqar/tests/tempest_plugin/tests/v2/test_queues.py create mode 100644 zaqar/tests/tempest_plugin/tests/v2/test_subscriptions.py diff --git a/zaqar/tests/tempest_plugin/api_schema/response/v2/__init__.py b/zaqar/tests/tempest_plugin/api_schema/response/v2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/zaqar/tests/tempest_plugin/api_schema/response/v2/queues.py b/zaqar/tests/tempest_plugin/api_schema/response/v2/queues.py new file mode 100644 index 000000000..4a10efe7e --- /dev/null +++ b/zaqar/tests/tempest_plugin/api_schema/response/v2/queues.py @@ -0,0 +1,297 @@ +# Copyright (c) 2016 HuaWei, 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. + + +list_link = { + 'type': 'object', + 'properties': { + 'rel': {'type': 'string'}, + 'href': { + 'type': 'string', + 'format': 'uri' + } + }, + 'required': ['href', 'rel'] +} + +list_queue = { + 'type': 'object', + 'properties': { + 'name': {'type': 'string'}, + 'href': { + 'type': 'string', + 'format': 'uri' + }, + 'metadata': {'type': 'object'} + }, + 'required': ['name', 'href'] +} + +list_queues = { + 'status_code': [200, 204], + 'response_body': { + 'type': 'object', + 'properties': { + 'links': { + 'type': 'array', + 'items': list_link, + 'maxItems': 1 + }, + 'queues': { + 'type': 'array', + 'items': list_queue + } + }, + 'required': ['links', 'queues'] + } +} + +age = { + 'type': 'number', + 'minimum': 0 +} + +message_link = { + 'type': 'object', + 'properties': { + 'href': { + 'type': 'string', + 'format': 'uri' + }, + 'age': age, + 'created': { + 'type': 'string', + 'format': 'date-time' + } + }, + 'required': ['href', 'age', 'created'] +} + +messages = { + 'type': 'object', + 'properties': { + 'free': {'type': 'number'}, + 'claimed': {'type': 'number'}, + 'total': {'type': 'number'}, + 'oldest': message_link, + 'newest': message_link + }, + 'required': ['free', 'claimed', 'total'] +} + +queue_stats = { + 'status_code': [200], + 'response_body': { + 'type': 'object', + 'properties': { + 'messages': messages + }, + 'required': ['messages'] + } +} + +resource_schema = { + 'type': 'array', + 'items': { + 'type': 'string' + }, + 'minItems': 1 +} + +post_messages = { + 'status_code': [201], + 'response_body': { + 'type': 'object', + 'properties': { + 'resources': resource_schema, + 'partial': {'type': 'boolean'} + } + }, + 'required': ['resources', 'partial'] +} + +message_ttl = { + 'type': 'number', + 'minimum': 1 +} + +list_messages_links = { + 'type': 'array', + 'maxItems': 1, + 'minItems': 1, + 'items': { + 'type': 'object', + 'properties': { + 'rel': {'type': 'string'}, + 'href': {'type': 'string'} + }, + 'required': ['rel', 'href'] + } +} + +list_messages_response = { + 'type': 'array', + 'minItems': 1, + 'items': { + 'type': 'object', + 'properties': { + 'href': {'type': 'string'}, + 'ttl': message_ttl, + 'age': age, + 'body': {'type': 'object'} + }, + 'required': ['href', 'ttl', 'age', 'body'] + } +} + +list_messages = { + 'status_code': [200, 204], + 'response_body': { + 'type': 'object', + 'properties': { + 'links': list_messages_links, + 'messages': list_messages_response + } + }, + 'required': ['links', 'messages'] +} + +single_message = { + 'type': 'object', + 'properties': { + 'href': {'type': 'string'}, + 'ttl': message_ttl, + 'age': age, + 'body': {'type': 'object'}, + 'id': {'type': 'string'} + }, + 'required': ['href', 'ttl', 'age', 'body', 'id'] +} + +get_single_message = { + 'status_code': [200], + 'response_body': single_message +} + +get_multiple_messages = { + 'status_code': [200], + 'response_body': { + 'type': 'object', + 'properties': { + 'messages': { + "type": "array", + "items": single_message, + "minItems": 1, + } + } + } +} + +messages_claimed = { + 'type': 'object', + 'properties': { + 'href': { + 'type': 'string', + 'format': 'uri' + }, + 'ttl': message_ttl, + 'age': {'type': 'number'}, + 'body': {'type': 'object'}, + 'id': {'type': 'string'} + }, + 'required': ['href', 'ttl', 'age', 'body', 'id'] +} + +claim_messages = { + 'status_code': [201, 204], + 'response_body': { + 'type': 'object', + 'properties': { + 'messages': { + "type": "array", + "items": single_message, + "minItems": 1, + } + } + } +} + +claim_ttl = { + 'type': 'number', + 'minimum': 1 +} + +query_claim = { + 'status_code': [200], + 'response_body': { + 'type': 'object', + 'properties': { + 'age': {'type': 'number'}, + 'ttl': claim_ttl, + 'messages': { + 'type': 'array', + 'minItems': 1 + } + }, + 'required': ['ttl', 'age', 'messages'] + } +} + +create_subscription = { + 'status_code': [201], + 'response_body': { + 'type': 'object', + 'properties': { + 'subscription_id': {'type': 'string'}, + }, + 'required': ['subscription_id'] + } +} + +single_subscription = { + 'type': 'object', + 'properties': { + 'subscriber': {'type': 'string'}, + 'source': {'type': 'string'}, + 'options': {'type': 'object'}, + 'id': {'type': 'string'}, + 'ttl': message_ttl, + }, + 'required': ['subscriber', 'source', 'options', 'id', 'ttl'] +} + +show_single_subscription = { + 'status_code': [200], + 'response_body': single_subscription +} + +list_subscriptions = { + 'status_code': [200], + 'response_body': { + 'type': 'object', + 'properties': { + 'subscriptions': { + "type": "array", + "items": single_subscription, + }, + 'links': { + 'type': 'array', + 'items': list_link, + 'maxItems': 1 + }, + }, + 'required': ['subscriptions', 'links'] + } +} diff --git a/zaqar/tests/tempest_plugin/services/messaging/json/messaging_client.py b/zaqar/tests/tempest_plugin/services/messaging/json/messaging_client.py index 411839989..14c3565a1 100644 --- a/zaqar/tests/tempest_plugin/services/messaging/json/messaging_client.py +++ b/zaqar/tests/tempest_plugin/services/messaging/json/messaging_client.py @@ -23,6 +23,8 @@ from zaqar.tests.tempest_plugin.api_schema.response.v1 \ import queues as v1schema from zaqar.tests.tempest_plugin.api_schema.response.v1_1 \ import queues as v11schema +from zaqar.tests.tempest_plugin.api_schema.response.v2 \ + import queues as v2schema class MessagingClient(rest_client.RestClient): @@ -344,3 +346,195 @@ class V11MessagingClient(MessagingClient): resp, body = self.delete(claim_uri, headers=self.headers) self.expected_success(204, resp.status) return resp, body + + +class V2MessagingClient(MessagingClient): + def __init__(self, auth_provider, service, region, + endpoint_type='publicURL', build_interval=1, build_timeout=60, + disable_ssl_certificate_validation=False, ca_certs=None, + trace_requests=''): + dscv = disable_ssl_certificate_validation + super(V2MessagingClient, self).__init__( + auth_provider, service, region, + endpoint_type=endpoint_type, + build_interval=build_interval, + build_timeout=build_timeout, + disable_ssl_certificate_validation=dscv, + ca_certs=ca_certs, + trace_requests=trace_requests) + + self.version = '2' + self.uri_prefix = 'v{0}'.format(self.version) + + client_id = uuid.uuid4().hex + self.headers = {'Client-ID': client_id} + + def list_queues(self): + uri = '{0}/queues'.format(self.uri_prefix) + resp, body = self.get(uri, headers=self.headers) + + if resp['status'] != '204': + body = json.loads(body) + self.validate_response(v2schema.list_queues, resp, body) + return resp, body + + def create_queue(self, queue_name): + uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name) + resp, body = self.put(uri, body=None, headers=self.headers) + self.expected_success(201, resp.status) + return resp, body + + def show_queue(self, queue_name): + uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name) + resp, body = self.get(uri, headers=self.headers) + self.expected_success(200, resp.status) + return resp, body + + def delete_queue(self, queue_name): + uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name) + resp, body = self.delete(uri, headers=self.headers) + self.expected_success(204, resp.status) + return resp, body + + def show_queue_stats(self, queue_name): + uri = '{0}/queues/{1}/stats'.format(self.uri_prefix, queue_name) + resp, body = self.get(uri, headers=self.headers) + body = json.loads(body) + self.validate_response(v2schema.queue_stats, resp, body) + return resp, body + + def show_queue_metadata(self, queue_name): + uri = '{0}/queues/{1}/metadata'.format(self.uri_prefix, queue_name) + resp, body = self.get(uri, headers=self.headers) + self.expected_success(200, resp.status) + body = json.loads(body) + return resp, body + + def set_queue_metadata(self, queue_name, rbody): + uri = '{0}/queues/{1}/metadata'.format(self.uri_prefix, queue_name) + resp, body = self.put(uri, body=json.dumps(rbody), + headers=self.headers) + self.expected_success(204, resp.status) + return resp, body + + def post_messages(self, queue_name, rbody): + uri = '{0}/queues/{1}/messages'.format(self.uri_prefix, queue_name) + resp, body = self.post(uri, body=json.dumps(rbody), + extra_headers=True, + headers=self.headers) + + body = json.loads(body) + self.validate_response(v2schema.post_messages, resp, body) + return resp, body + + def list_messages(self, queue_name): + uri = '{0}/queues/{1}/messages?echo=True'.format(self.uri_prefix, + queue_name) + resp, body = self.get(uri, extra_headers=True, headers=self.headers) + + if resp['status'] != '204': + body = json.loads(body) + self.validate_response(v2schema.list_messages, resp, body) + + return resp, body + + def show_single_message(self, message_uri): + resp, body = self.get(message_uri, extra_headers=True, + headers=self.headers) + if resp['status'] != '204': + body = json.loads(body) + self.validate_response(v2schema.get_single_message, resp, + body) + return resp, body + + def show_multiple_messages(self, message_uri): + resp, body = self.get(message_uri, extra_headers=True, + headers=self.headers) + + if resp['status'] != '404': + body = json.loads(body) + self.validate_response(v2schema.get_multiple_messages, + resp, + body) + + return resp, body + + def delete_messages(self, message_uri): + resp, body = self.delete(message_uri, headers=self.headers) + self.expected_success(204, resp.status) + return resp, body + + def post_claims(self, queue_name, rbody, url_params=False): + uri = '{0}/queues/{1}/claims'.format(self.uri_prefix, queue_name) + if url_params: + uri += '?%s' % urllib.urlencode(url_params) + + resp, body = self.post(uri, body=json.dumps(rbody), + extra_headers=True, + headers=self.headers) + + body = json.loads(body) + self.validate_response(v2schema.claim_messages, resp, body) + return resp, body + + def query_claim(self, claim_uri): + resp, body = self.get(claim_uri, headers=self.headers) + + if resp['status'] != '204': + body = json.loads(body) + self.validate_response(v2schema.query_claim, resp, body) + return resp, body + + def update_claim(self, claim_uri, rbody): + resp, body = self.patch(claim_uri, body=json.dumps(rbody), + headers=self.headers) + self.expected_success(204, resp.status) + return resp, body + + def delete_claim(self, claim_uri): + resp, body = self.delete(claim_uri, headers=self.headers) + self.expected_success(204, resp.status) + return resp, body + + def create_subscription(self, queue_name, rbody): + uri = '{0}/queues/{1}/subscriptions'.format(self.uri_prefix, + queue_name) + + resp, body = self.post(uri, body=json.dumps(rbody), + extra_headers=True, + headers=self.headers) + body = json.loads(body) + self.validate_response(v2schema.create_subscription, resp, body) + return resp, body + + def delete_subscription(self, queue_name, subscription_id): + uri = '{0}/queues/{1}/subscriptions/{2}'.format(self.uri_prefix, + queue_name, + subscription_id) + resp, body = self.delete(uri, headers=self.headers) + return resp, body + + def list_subscription(self, queue_name): + uri = '{0}/queues/{1}/subscriptions/'.format(self.uri_prefix, + queue_name) + resp, body = self.get(uri, headers=self.headers) + body = json.loads(body) + self.validate_response(v2schema.list_subscriptions, resp, body) + return resp, body + + def show_subscription(self, queue_name, subscription_id): + uri = '{0}/queues/{1}/subscriptions/{2}'.format(self.uri_prefix, + queue_name, + subscription_id) + resp, body = self.get(uri, headers=self.headers) + body = json.loads(body) + self.validate_response(v2schema.show_single_subscription, resp, body) + return resp, body + + def update_subscription(self, queue_name, subscription_id, rbody): + uri = '{0}/queues/{1}/subscriptions/{2}'.format(self.uri_prefix, + queue_name, + subscription_id) + resp, body = self.patch(uri, body=json.dumps(rbody), + headers=self.headers) + return resp, body diff --git a/zaqar/tests/tempest_plugin/tests/base.py b/zaqar/tests/tempest_plugin/tests/base.py index 40ed765f6..745a6b45f 100644 --- a/zaqar/tests/tempest_plugin/tests/base.py +++ b/zaqar/tests/tempest_plugin/tests/base.py @@ -195,3 +195,59 @@ class BaseV11MessagingTest(BaseMessagingTest): body = ([{'body': message_body, 'ttl': message_ttl}] * repeat) rbody = {'messages': body} return rbody + + +class BaseV2MessagingTest(BaseV11MessagingTest): + """Base class for the Messaging (Zaqar) v1.1 tests.""" + @classmethod + def setup_clients(cls): + super(BaseV2MessagingTest, cls).setup_clients() + cls.client = messaging_client.V2MessagingClient( + cls.os.auth_provider, + CONF.messaging.catalog_type, + CONF.identity.region, + **cls.os.default_params_with_timeout_values) + + @classmethod + def create_subscription(cls, queue_name, rbody): + resp, body = cls.client.create_subscription( + queue_name, rbody) + return resp, body + + @classmethod + def delete_subscription(cls, queue_name, subscription_id): + resp, body = cls.client.delete_subscription(queue_name, + subscription_id) + return resp, body + + @classmethod + def list_subscription(cls, queue_name): + resp, body = cls.client.list_subscription(queue_name) + return resp, body + + @classmethod + def show_subscription(cls, queue_name, subscription_id): + resp, body = cls.client.show_subscription(queue_name, subscription_id) + return resp, body + + @classmethod + def update_subscription(cls, queue_name, subscription_id, rbody): + resp, body = cls.client.update_subscription(queue_name, + subscription_id, + rbody) + return resp, body + + @classmethod + def generate_subscription_body(cls): + message_ttl = data_utils.\ + rand_int_id(start=60, end=CONF.messaging.max_message_ttl) + + key = data_utils.arbitrary_string(size=20, base_text='MessagingKey') + value = data_utils.arbitrary_string(size=20, + base_text='MessagingValue') + option_body = {key: value} + subscribers = ['http://fake:8080', 'https://fake:8080', + 'mailto:fake@123.com'] + rbody = [{'options': option_body, 'ttl': message_ttl, + 'subscriber': subscriber} for subscriber in subscribers] + return rbody diff --git a/zaqar/tests/tempest_plugin/tests/v2/__init__.py b/zaqar/tests/tempest_plugin/tests/v2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/zaqar/tests/tempest_plugin/tests/v2/test_claims.py b/zaqar/tests/tempest_plugin/tests/v2/test_claims.py new file mode 100644 index 000000000..52832296b --- /dev/null +++ b/zaqar/tests/tempest_plugin/tests/v2/test_claims.py @@ -0,0 +1,114 @@ +# Copyright (c) 2016 HuaWei, 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 six.moves.urllib import parse as urlparse +from tempest import config +from tempest_lib.common.utils import data_utils +from tempest_lib import decorators + +from zaqar.tests.tempest_plugin.tests import base + + +CONF = config.CONF + + +class TestClaims(base.BaseV2MessagingTest): + + @classmethod + def resource_setup(cls): + super(TestClaims, cls).resource_setup() + cls.queue_name = data_utils.rand_name('Queues-Test') + # Create Queue + cls.create_queue(cls.queue_name) + + def _post_and_claim_messages(self, queue_name, repeat=1): + # Post Messages + message_body = self.generate_message_body(repeat=repeat) + self.client.post_messages(queue_name=self.queue_name, + rbody=message_body) + + # Post Claim + claim_ttl = data_utils.rand_int_id(start=60, + end=CONF.messaging.max_claim_ttl) + claim_grace = data_utils.\ + rand_int_id(start=60, end=CONF.messaging.max_claim_grace) + claim_body = {"ttl": claim_ttl, "grace": claim_grace} + resp, body = self.client.post_claims(queue_name=self.queue_name, + rbody=claim_body) + + return resp, body + + @decorators.idempotent_id('3b839cac-d214-4fca-8c03-b8edbdcecb20') + def test_post_claim(self): + _, body = self._post_and_claim_messages(queue_name=self.queue_name) + claimed_message_uri = body['messages'][0]['href'] + + # Delete Claimed message + self.client.delete_messages(claimed_message_uri) + + @decorators.idempotent_id('e69d047c-b3f4-4216-990e-7953407084b7') + def test_query_claim(self): + # Post a Claim + resp, body = self._post_and_claim_messages(queue_name=self.queue_name) + + # Query Claim + claim_uri = resp['location'][resp['location'].find('/v2'):] + self.client.query_claim(claim_uri) + + # Delete Claimed message + claimed_message_uri = body['messages'][0]['href'] + self.delete_messages(claimed_message_uri) + + @decorators.idempotent_id('5e1e7559-77fc-4ea8-a817-cd43be23d692') + def test_update_claim(self): + # Post a Claim + resp, body = self._post_and_claim_messages(queue_name=self.queue_name) + + claim_uri = resp['location'][resp['location'].find('/v2'):] + claimed_message_uri = body['messages'][0]['href'] + + # Update Claim + claim_ttl = data_utils.rand_int_id(start=60, + end=CONF.messaging.max_claim_ttl) + update_rbody = {"ttl": claim_ttl} + + self.client.update_claim(claim_uri, rbody=update_rbody) + + # Verify claim ttl >= updated ttl value + _, body = self.client.query_claim(claim_uri) + updated_claim_ttl = body["ttl"] + self.assertTrue(updated_claim_ttl >= claim_ttl) + + # Delete Claimed message + self.client.delete_messages(claimed_message_uri) + + @decorators.idempotent_id('97c1ebcc-9d1e-463a-8673-6ec989ba3be7') + def test_release_claim(self): + # Post a Claim + resp, body = self._post_and_claim_messages(queue_name=self.queue_name) + claim_uri = resp['location'][resp['location'].find('/v2'):] + + # Release Claim + self.client.delete_claim(claim_uri) + + # Delete Claimed message + # This will implicitly verify that the claim is deleted. + message_uri = urlparse.urlparse(claim_uri).path + self.client.delete_messages(message_uri) + + @classmethod + def resource_cleanup(cls): + cls.delete_queue(cls.queue_name) + super(TestClaims, cls).resource_cleanup() diff --git a/zaqar/tests/tempest_plugin/tests/v2/test_messages.py b/zaqar/tests/tempest_plugin/tests/v2/test_messages.py new file mode 100644 index 000000000..d4431c2fa --- /dev/null +++ b/zaqar/tests/tempest_plugin/tests/v2/test_messages.py @@ -0,0 +1,121 @@ +# Copyright (c) 2016 HuaWei, 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 tempest import config +from tempest_lib.common.utils import data_utils +from tempest_lib import decorators +from tempest_lib import exceptions as lib_exc + +from zaqar.tests.tempest_plugin.tests import base + +CONF = config.CONF + + +class TestMessages(base.BaseV2MessagingTest): + + @classmethod + def resource_setup(cls): + super(TestMessages, cls).resource_setup() + cls.queue_name = data_utils.rand_name('Queues-Test') + # Create Queue + cls.client.create_queue(cls.queue_name) + + def _post_messages(self, repeat=CONF.messaging.max_messages_per_page): + message_body = self.generate_message_body(repeat=repeat) + resp, body = self.post_messages(queue_name=self.queue_name, + rbody=message_body) + return resp, body + + @decorators.idempotent_id('2e1a26c1-6d7b-4ae7-b510-d8e2abe9d831') + def test_post_messages(self): + # Post Messages + resp, _ = self._post_messages() + + # Get on the posted messages + message_uri = resp['location'][resp['location'].find('/v2'):] + resp, _ = self.client.show_multiple_messages(message_uri) + # The test has an assertion here, because the response cannot be 204 + # in this case (the client allows 200 or 204 for this API call). + self.assertEqual('200', resp['status']) + + @decorators.idempotent_id('f38cca63-55d7-41e7-8ff9-7254e9859aa7') + def test_list_messages(self): + # Post Messages + self._post_messages() + + # List Messages + resp, _ = self.list_messages(queue_name=self.queue_name) + # The test has an assertion here, because the response cannot be 204 + # in this case (the client allows 200 or 204 for this API call). + self.assertEqual('200', resp['status']) + + @decorators.idempotent_id('f9719398-8bb7-4660-acb6-ef87c47d726c') + def test_get_message(self): + # Post Messages + _, body = self._post_messages() + message_uri = body['resources'][0] + + # Get posted message + resp, _ = self.client.show_single_message(message_uri) + # The test has an assertion here, because the response cannot be 204 + # in this case (the client allows 200 or 204 for this API call). + self.assertEqual('200', resp['status']) + + @decorators.idempotent_id('a8fe2c0f-c3f2-4278-8bd9-2fca94356f2e') + def test_get_multiple_messages(self): + # Post Messages + resp, _ = self._post_messages() + message_uri = resp['location'][resp['location'].find('/v2'):] + + # Get posted messages + resp, _ = self.client.show_multiple_messages(message_uri) + # The test has an assertion here, because the response cannot be 204 + # in this case (the client allows 200 or 204 for this API call). + self.assertEqual('200', resp['status']) + + @decorators.idempotent_id('9654fb55-8cbd-4997-8c3e-8d388276a8d9') + def test_delete_single_message(self): + # Post Messages + _, body = self._post_messages() + message_uri = body['resources'][0] + + # Delete posted message & verify the delete operration + self.client.delete_messages(message_uri) + + message_uri = message_uri.replace('/messages/', '/messages?ids=') + # The test has an assertion here, because the response has to be 404 + # in this case(different from v1). + self.assertRaises(lib_exc.NotFound, + self.client.show_multiple_messages, + message_uri) + + @decorators.idempotent_id('e025555a-fa3f-4558-859a-42d69ccf66a6') + def test_delete_multiple_messages(self): + # Post Messages + resp, _ = self._post_messages() + message_uri = resp['location'][resp['location'].find('/v2'):] + + # Delete multiple messages + self.client.delete_messages(message_uri) + # The test has an assertion here, because the response has to be 404 + # in this case(different from v1). + self.assertRaises(lib_exc.NotFound, + self.client.show_multiple_messages, + message_uri) + + @classmethod + def resource_cleanup(cls): + cls.delete_queue(cls.queue_name) + super(TestMessages, cls).resource_cleanup() diff --git a/zaqar/tests/tempest_plugin/tests/v2/test_queues.py b/zaqar/tests/tempest_plugin/tests/v2/test_queues.py new file mode 100644 index 000000000..e0d5f13a6 --- /dev/null +++ b/zaqar/tests/tempest_plugin/tests/v2/test_queues.py @@ -0,0 +1,105 @@ +# Copyright (c) 2016 HuaWei, 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 six import moves +from tempest.common.utils import data_utils +from tempest_lib import decorators +from testtools import matchers + +from zaqar.tests.tempest_plugin.tests import base + + +class TestQueues(base.BaseV11MessagingTest): + + @decorators.idempotent_id('f2db96f3-fa02-426a-9b42-5806e12f14d4') + def test_create_delete_queue(self): + # Create & Delete Queue + queue_name = data_utils.rand_name('test') + _, body = self.create_queue(queue_name) + + self.addCleanup(self.client.delete_queue, queue_name) + # NOTE(gmann): create_queue returns response status code as 201 + # so specifically checking the expected empty response body as + # this is not going to be checked in response_checker(). + self.assertEqual('', body) + + self.delete_queue(queue_name) + # lazy queue + self.client.show_queue(queue_name) + + +class TestManageQueue(base.BaseV2MessagingTest): + + @classmethod + def resource_setup(cls): + super(TestManageQueue, cls).resource_setup() + cls.queues = list() + for _ in moves.xrange(5): + queue_name = data_utils.rand_name('Queues-Test') + cls.queues.append(queue_name) + # Create Queue + cls.client.create_queue(queue_name) + + @decorators.idempotent_id('8f1fec00-54fc-48b9-aa67-c10a824b768d') + def test_list_queues(self): + # Listing queues + _, body = self.list_queues() + self.assertEqual(len(body['queues']), len(self.queues)) + for item in body['queues']: + self.assertIn(item['name'], self.queues) + + @decorators.idempotent_id('e96466e7-d43f-48f9-bfe8-59e3d40f6868') + def test_get_queue_stats(self): + # Retrieve random queue + queue_name = self.queues[data_utils.rand_int_id(0, + len(self.queues) - 1)] + # Get Queue Stats for a newly created Queue + _, body = self.get_queue_stats(queue_name) + msgs = body['messages'] + for element in ('free', 'claimed', 'total'): + self.assertEqual(0, msgs[element]) + for element in ('oldest', 'newest'): + self.assertNotIn(element, msgs) + + @decorators.skip_because(bug='1543900') + @decorators.idempotent_id('dfb1e0b0-b481-4e2a-91ae-2c28b65e9c28') + def test_set_and_get_queue_metadata(self): + # Retrieve random queue + queue_name = self.queues[data_utils.rand_int_id(0, + len(self.queues) - 1)] + # Check the Queue has no metadata + _, body = self.get_queue_metadata(queue_name) + self.assertThat(body, matchers.HasLength(0)) + # Create metadata + key3 = [0, 1, 2, 3, 4] + key2 = data_utils.rand_name('value') + req_body1 = dict() + req_body1[data_utils.rand_name('key3')] = key3 + req_body1[data_utils.rand_name('key2')] = key2 + req_body = dict() + req_body[data_utils.rand_name('key1')] = req_body1 + # Set Queue Metadata + self.set_queue_metadata(queue_name, req_body) + + # Get Queue Metadata + _, body = self.get_queue_metadata(queue_name) + self.assertThat(body, matchers.Equals(req_body)) + + @classmethod + def resource_cleanup(cls): + for queue_name in cls.queues: + cls.client.delete_queue(queue_name) + super(TestManageQueue, cls).resource_cleanup() diff --git a/zaqar/tests/tempest_plugin/tests/v2/test_subscriptions.py b/zaqar/tests/tempest_plugin/tests/v2/test_subscriptions.py new file mode 100644 index 000000000..2ca6c7c46 --- /dev/null +++ b/zaqar/tests/tempest_plugin/tests/v2/test_subscriptions.py @@ -0,0 +1,97 @@ +# Copyright (c) 2016 HuaWei, 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 tempest.common.utils import data_utils +from tempest_lib import decorators + +from zaqar.tests.tempest_plugin.tests import base + + +class TestSubscriptions(base.BaseV2MessagingTest): + + @classmethod + def resource_setup(cls): + super(TestSubscriptions, cls).resource_setup() + cls.queue_name = data_utils.rand_name('Queues-Test') + # Create Queue + cls.client.create_queue(cls.queue_name) + + def _create_subscriptions(self): + bodys = self.generate_subscription_body() + results = [] + for body in bodys: + resp, body = self.create_subscription(queue_name=self.queue_name, + rbody=body) + results.append((resp, body)) + return results + + @decorators.idempotent_id('425d5afb-31d8-40ea-a23a-ef3f5554f7cc') + def test_create_delete_subscriptions(self): + # create all kinds of subscriptions + results = self._create_subscriptions() + # delete them + for result in results: + subscription_id = result[1]["subscription_id"] + self.delete_subscription(self.queue_name, subscription_id) + + @decorators.idempotent_id('a8776d93-895f-4947-a6b0-d0da50bfd5e8') + def test_list_subscriptions(self): + # create all kinds of subscriptions + results = self._create_subscriptions() + # list them + resp, body = self.list_subscription(self.queue_name) + self.assertEqual('200', resp['status']) + self.assertEqual(3, len(body['subscriptions'])) + # delete them + for result in results: + subscription_id = result[1]["subscription_id"] + self.delete_subscription(self.queue_name, subscription_id) + + @decorators.idempotent_id('de3d4a35-c5de-4f40-b6ad-7df187bf3831') + def test_show_subscriptions(self): + # create all kinds of subscriptions + results = self._create_subscriptions() + # get the first one + subscription_id = results[0][1]["subscription_id"] + resp, body = self.show_subscription(self.queue_name, subscription_id) + self.assertEqual('200', resp['status']) + self.assertEqual('http://fake:8080', body['subscriber']) + # delete them + for result in results: + subscription_id = result[1]["subscription_id"] + self.delete_subscription(self.queue_name, subscription_id) + + @decorators.idempotent_id('90489fa2-893d-4062-b2bd-29bdd06f54f3') + def test_update_subscriptions(self): + # create all kinds of subscriptions + results = self._create_subscriptions() + # update the first one + subscription_id = results[0][1]["subscription_id"] + rbody = {'options': {'test': 'updated'}} + self.update_subscription(self.queue_name, subscription_id, rbody) + # get the new one + resp, body = self.show_subscription(self.queue_name, subscription_id) + self.assertEqual('200', resp['status']) + self.assertEqual(rbody['options'], body['options']) + # delete them + for result in results: + subscription_id = result[1]["subscription_id"] + self.delete_subscription(self.queue_name, subscription_id) + + @classmethod + def resource_cleanup(cls): + cls.delete_queue(cls.queue_name) + super(TestSubscriptions, cls).resource_cleanup()