Add Marconi Smoke Tests
Add smoke tests that check the existence of queues.
Add test that checks list queues.
Add test that gets queue statistics.
Add test that sets and gets queue metadata.
Tests for List Queues and Queue Stats use JSON Schema
validation.
Change-Id: I084d1ae0de4a729a913a7084f14c0d3172af29d3
Implements: blueprint add-basic-marconi-tests
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 28a4d1c..ac96a4a 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -825,6 +825,10 @@
# Catalog type of the Queuing service. (string value)
#catalog_type=queuing
+# The maximum number of queue records per page when listing
+# queues (integer value)
+#max_queues_per_page=20
+
[scenario]
diff --git a/tempest/api/queuing/base.py b/tempest/api/queuing/base.py
index 6c22719..5649619 100644
--- a/tempest/api/queuing/base.py
+++ b/tempest/api/queuing/base.py
@@ -50,6 +50,42 @@
@classmethod
def delete_queue(cls, queue_name):
- """Wrapper utility that returns a test queue."""
+ """Wrapper utility that deletes a test queue."""
resp, body = cls.client.delete_queue(queue_name)
return resp, body
+
+ @classmethod
+ def check_queue_exists(cls, queue_name):
+ """Wrapper utility that checks the existence of a test queue."""
+ resp, body = cls.client.get_queue(queue_name)
+ return resp, body
+
+ @classmethod
+ def check_queue_exists_head(cls, queue_name):
+ """Wrapper utility checks the head of a queue via http HEAD."""
+ resp, body = cls.client.head_queue(queue_name)
+ return resp, body
+
+ @classmethod
+ def list_queues(cls):
+ """Wrapper utility that lists queues."""
+ resp, body = cls.client.list_queues()
+ return resp, body
+
+ @classmethod
+ def get_queue_stats(cls, queue_name):
+ """Wrapper utility that returns the queue stats."""
+ resp, body = cls.client.get_queue_stats(queue_name)
+ return resp, body
+
+ @classmethod
+ def get_queue_metadata(cls, queue_name):
+ """Wrapper utility that gets a queue metadata."""
+ resp, body = cls.client.get_queue_metadata(queue_name)
+ return resp, body
+
+ @classmethod
+ def set_queue_metadata(cls, queue_name, rbody):
+ """Wrapper utility that sets the metadata of a queue."""
+ resp, body = cls.client.set_queue_metadata(queue_name, rbody)
+ return resp, body
diff --git a/tempest/api/queuing/test_queues.py b/tempest/api/queuing/test_queues.py
index 4d03f7e..e43178a 100644
--- a/tempest/api/queuing/test_queues.py
+++ b/tempest/api/queuing/test_queues.py
@@ -14,6 +14,8 @@
# limitations under the License.
import logging
+from six import moves
+from testtools import matchers
from tempest.api.queuing import base
from tempest.common.utils import data_utils
@@ -43,18 +45,86 @@
@classmethod
def setUpClass(cls):
super(TestManageQueue, cls).setUpClass()
- cls.queue_name = data_utils.rand_name('Queues-Test')
- # Create Queue
- cls.client.create_queue(cls.queue_name)
+ 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)
@test.attr(type='smoke')
def test_delete_queue(self):
# Delete Queue
- resp, body = self.delete_queue(self.queue_name)
+ queue_name = self.queues.pop()
+ resp, body = self.delete_queue(queue_name)
self.assertEqual('204', resp['status'])
self.assertEqual('', body)
+ @test.attr(type='smoke')
+ def test_check_queue_existence(self):
+ # Checking Queue Existence
+ for queue_name in self.queues:
+ resp, body = self.check_queue_exists(queue_name)
+ self.assertEqual('204', resp['status'])
+ self.assertEqual('', body)
+
+ @test.attr(type='smoke')
+ def test_check_queue_head(self):
+ # Checking Queue Existence by calling HEAD
+ for queue_name in self.queues:
+ resp, body = self.check_queue_exists_head(queue_name)
+ self.assertEqual('204', resp['status'])
+ self.assertEqual('', body)
+
+ @test.attr(type='smoke')
+ def test_list_queues(self):
+ # Listing queues
+ resp, body = self.list_queues()
+ self.assertEqual(len(body['queues']), len(self.queues))
+ for item in body['queues']:
+ self.assertIn(item['name'], self.queues)
+
+ @test.attr(type='smoke')
+ 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
+ resp, 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)
+
+ @test.attr(type='smoke')
+ 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
+ resp, body = self.get_queue_metadata(queue_name)
+ self.assertEqual('200', resp['status'])
+ 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
+ resp, body = self.set_queue_metadata(queue_name, req_body)
+ self.assertEqual('204', resp['status'])
+ self.assertEqual('', body)
+ # Get Queue Metadata
+ resp, body = self.get_queue_metadata(queue_name)
+ self.assertEqual('200', resp['status'])
+ self.assertThat(body, matchers.Equals(req_body))
+
@classmethod
def tearDownClass(cls):
- cls.client.delete_queue(cls.queue_name)
+ for queue_name in cls.queues:
+ cls.client.delete_queue(queue_name)
super(TestManageQueue, cls).tearDownClass()
diff --git a/tempest/api_schema/queuing/__init__.py b/tempest/api_schema/queuing/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/queuing/__init__.py
diff --git a/tempest/api_schema/queuing/v1/__init__.py b/tempest/api_schema/queuing/v1/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/queuing/v1/__init__.py
diff --git a/tempest/api_schema/queuing/v1/queues.py b/tempest/api_schema/queuing/v1/queues.py
new file mode 100644
index 0000000..4630e1c
--- /dev/null
+++ b/tempest/api_schema/queuing/v1/queues.py
@@ -0,0 +1,98 @@
+
+# Copyright (c) 2014 Rackspace, 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']
+ }
+}
+
+message_link = {
+ 'type': 'object',
+ 'properties': {
+ 'href': {
+ 'type': 'string',
+ 'format': 'uri'
+ },
+ 'age': {'type': 'number'},
+ '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']
+ }
+}
diff --git a/tempest/config.py b/tempest/config.py
index f9be90d..c732fe0 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -436,6 +436,10 @@
cfg.StrOpt('catalog_type',
default='queuing',
help='Catalog type of the Queuing service.'),
+ cfg.IntOpt('max_queues_per_page',
+ default=20,
+ help='The maximum number of queue records per page when '
+ 'listing queues'),
]
volume_group = cfg.OptGroup(name='volume',
diff --git a/tempest/services/queuing/json/queuing_client.py b/tempest/services/queuing/json/queuing_client.py
index 4a0c495..e5978f5 100644
--- a/tempest/services/queuing/json/queuing_client.py
+++ b/tempest/services/queuing/json/queuing_client.py
@@ -15,6 +15,7 @@
import json
+from tempest.api_schema.queuing.v1 import queues as queues_schema
from tempest.common import rest_client
from tempest import config
@@ -33,6 +34,7 @@
uri = '{0}/queues'.format(self.uri_prefix)
resp, body = self.get(uri)
body = json.loads(body)
+ self.validate_response(queues_schema.list_queues, resp, body)
return resp, body
def create_queue(self, queue_name):
@@ -43,16 +45,32 @@
def get_queue(self, queue_name):
uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
resp, body = self.get(uri)
- body = json.loads(body)
return resp, body
def head_queue(self, queue_name):
uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
resp, body = self.head(uri)
- body = json.loads(body)
return resp, body
def delete_queue(self, queue_name):
uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
resp = self.delete(uri)
return resp
+
+ def get_queue_stats(self, queue_name):
+ uri = '{0}/queues/{1}/stats'.format(self.uri_prefix, queue_name)
+ resp, body = self.get(uri)
+ body = json.loads(body)
+ self.validate_response(queues_schema.queue_stats, resp, body)
+ return resp, body
+
+ def get_queue_metadata(self, queue_name):
+ uri = '{0}/queues/{1}/metadata'.format(self.uri_prefix, queue_name)
+ resp, body = self.get(uri)
+ 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))
+ return resp, body