V1.1 Functional Tests
Added tests for new V1.1 functions like pop and shard Updated existing tests for V1.1 return calls Added new json schemas Edited functional test base to support multiple schemas Change-Id: I35dfb92af22540609ecb50c1eb5c8fa65e6cadc8 Partially-Implements blueprint: api-v1.1-functional-tests
This commit is contained in:
parent
22584f484c
commit
c1715c6fb1
0
marconi/queues/api/v1_1/__init__.py
Normal file
0
marconi/queues/api/v1_1/__init__.py
Normal file
169
marconi/queues/api/v1_1/request.py
Normal file
169
marconi/queues/api/v1_1/request.py
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
# Copyright (c) 2013 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.
|
||||||
|
|
||||||
|
from marconi.common import api
|
||||||
|
|
||||||
|
|
||||||
|
class RequestSchema(api.Api):
|
||||||
|
|
||||||
|
schema = {
|
||||||
|
'queue_list': {
|
||||||
|
'ref': 'queues',
|
||||||
|
'method': 'GET',
|
||||||
|
'properties': {
|
||||||
|
'marker': {'type': 'string'},
|
||||||
|
'limit': {'type': 'integer'},
|
||||||
|
'detailed': {'type': 'boolean'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'queue_create': {
|
||||||
|
'ref': 'queues/{queue_name}',
|
||||||
|
'method': 'PUT',
|
||||||
|
'required': ['queue_name'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'queue_delete': {
|
||||||
|
'ref': 'queues/{queue_name}',
|
||||||
|
'method': 'DELETE',
|
||||||
|
'required': ['queue_name'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'queue_set_metadata': {
|
||||||
|
'ref': 'queues/{queue_name}/metadata',
|
||||||
|
'method': 'PUT',
|
||||||
|
'required': ['queue_name'],
|
||||||
|
'properties': {
|
||||||
|
# NOTE(flaper87): Metadata is part
|
||||||
|
# of the request content. No need to
|
||||||
|
# add it here.
|
||||||
|
'queue_name': {'type': 'string'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'queue_get_metadata': {
|
||||||
|
'ref': 'queues/{queue_name}/metadata',
|
||||||
|
'method': 'GET',
|
||||||
|
'required': ['queue_name'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'queue_get_stats': {
|
||||||
|
'ref': 'queues/{queue_name}/stats',
|
||||||
|
'method': 'GET',
|
||||||
|
'required': ['queue_name'],
|
||||||
|
'admin': True,
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'message_list': {
|
||||||
|
'ref': 'queues/{queue_name}/messages',
|
||||||
|
'method': 'GET',
|
||||||
|
'required': ['queue_name'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'},
|
||||||
|
'marker': {'type': 'string'},
|
||||||
|
'limit': {'type': 'integer'},
|
||||||
|
'echo': {'type': 'boolean'},
|
||||||
|
'include_claimed': {'type': 'boolean'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'message_post': {
|
||||||
|
'ref': 'queues/{queue_name}/messages',
|
||||||
|
'method': 'POST',
|
||||||
|
'required': ['queue_name'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'message_delete': {
|
||||||
|
'ref': 'queues/{queue_name}/messages/{message_id}',
|
||||||
|
'method': 'DELETE',
|
||||||
|
'required': ['queue_name', 'message_id'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'},
|
||||||
|
'message_id': {'type': 'string'},
|
||||||
|
'claim_id': {'type': 'string'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'message_delete_many': {
|
||||||
|
'ref': 'queues/{queue_name}/messages',
|
||||||
|
'method': 'DELETE',
|
||||||
|
'required': ['queue_name', 'ids'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'},
|
||||||
|
'ids': {'type': 'array'},
|
||||||
|
'pop': {'type': 'integer'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'claim_create': {
|
||||||
|
'ref': 'queues/{queue_name}/claims',
|
||||||
|
'method': 'POST',
|
||||||
|
'required': ['queue_name'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'},
|
||||||
|
'limit': {'type': 'integer'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'claim_get': {
|
||||||
|
'ref': 'queues/{queue_name}/claims/{claim_id}',
|
||||||
|
'method': 'GET',
|
||||||
|
'required': ['queue_name', 'claim_id'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'},
|
||||||
|
'claim_id': {'type': 'string'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'claim_update': {
|
||||||
|
'ref': 'queues/{queue_name}/claims/{claim_id}',
|
||||||
|
'method': 'PATCH',
|
||||||
|
'required': ['queue_name', 'claim_id'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'},
|
||||||
|
'claim_id': {'type': 'string'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'claim_delete': {
|
||||||
|
'ref': 'queues/{queue_name}/claims/{claim_id}',
|
||||||
|
'method': 'DELETE',
|
||||||
|
'required': ['queue_name', 'claim_id'],
|
||||||
|
'properties': {
|
||||||
|
'queue_name': {'type': 'string'},
|
||||||
|
'claim_id': {'type': 'string'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'check_node_health': {
|
||||||
|
'ref': '/v1/health',
|
||||||
|
'method': 'GET',
|
||||||
|
},
|
||||||
|
}
|
307
marconi/queues/api/v1_1/response.py
Normal file
307
marconi/queues/api/v1_1/response.py
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
# Copyright (c) 2013 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.
|
||||||
|
|
||||||
|
from marconi.common import api
|
||||||
|
|
||||||
|
|
||||||
|
class ResponseSchema(api.Api):
|
||||||
|
|
||||||
|
"""Define validation schema for json response."""
|
||||||
|
|
||||||
|
def __init__(self, limits):
|
||||||
|
self.limits = limits
|
||||||
|
|
||||||
|
age = {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
message = {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"href": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^(/v1\.1/queues/[a-zA-Z0-9_-]"
|
||||||
|
"{1,64}/messages/[a-zA-Z0-9_-]+)$"
|
||||||
|
},
|
||||||
|
"age": age,
|
||||||
|
"ttl": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": self.limits.max_message_ttl
|
||||||
|
},
|
||||||
|
|
||||||
|
"body": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["href", "ttl", "age", "body"],
|
||||||
|
"additionalProperties": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
claim_href = {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^(/v1\.1/queues/[a-zA-Z0-9_-]{1,64}"
|
||||||
|
"/messages/[a-zA-Z0-9_-]+)"
|
||||||
|
"\?claim_id=[a-zA-Z0-9_-]+$"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.schema = {
|
||||||
|
'message_get_many': {
|
||||||
|
"type": "array",
|
||||||
|
"items": message,
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": self.limits.max_messages_per_page
|
||||||
|
},
|
||||||
|
|
||||||
|
'queue_list': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'links': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'rel': {
|
||||||
|
'type': 'string',
|
||||||
|
'enum': ['next'],
|
||||||
|
},
|
||||||
|
'href': {
|
||||||
|
'type': 'string',
|
||||||
|
"pattern": "^/v1\.1/queues\?",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['rel', 'href'],
|
||||||
|
'additionalProperties': False,
|
||||||
|
},
|
||||||
|
'minItems': 1,
|
||||||
|
'maxItems': 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
'queues': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'name': {
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^[a-zA-Z0-9_-]{1,64}$'
|
||||||
|
},
|
||||||
|
'href': {
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^/v1\.1/queues/'
|
||||||
|
'[a-zA-Z0-9_-]{1,64}$',
|
||||||
|
},
|
||||||
|
'metadata': {
|
||||||
|
'type': 'object',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['name', 'href'],
|
||||||
|
'additionalProperties': False,
|
||||||
|
},
|
||||||
|
'minItems': 1,
|
||||||
|
'maxItems': self.limits.max_queues_per_page,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['links', 'queues'],
|
||||||
|
'additionalProperties': False,
|
||||||
|
},
|
||||||
|
|
||||||
|
'queue_stats': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'messages': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'free': {
|
||||||
|
'type': 'number',
|
||||||
|
'minimum': 0
|
||||||
|
},
|
||||||
|
'claimed': {
|
||||||
|
'type': 'number',
|
||||||
|
'minimum': 0
|
||||||
|
},
|
||||||
|
'total': {
|
||||||
|
'type': 'number',
|
||||||
|
'minimum': 0
|
||||||
|
},
|
||||||
|
'oldest': {
|
||||||
|
'type': 'object'
|
||||||
|
},
|
||||||
|
'newest': {
|
||||||
|
'type': 'object'
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
'required': ['free', 'claimed', 'total'],
|
||||||
|
'additionalProperties': False
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['messages'],
|
||||||
|
'additionalProperties': False
|
||||||
|
},
|
||||||
|
|
||||||
|
'shard-list': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'shards': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'href': {
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^/v1\.1/'
|
||||||
|
'shards/[a-zA-Z0-9_-]{1,64}$'
|
||||||
|
},
|
||||||
|
'weight': {
|
||||||
|
'type': 'number',
|
||||||
|
'minimum': -1
|
||||||
|
},
|
||||||
|
'uri': {
|
||||||
|
'type': 'string'
|
||||||
|
},
|
||||||
|
'options': {
|
||||||
|
'type': 'object',
|
||||||
|
'additionalProperties': True
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['href', 'weight', 'uri'],
|
||||||
|
'additionalProperties': False,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['shards'],
|
||||||
|
'additionalProperties': False
|
||||||
|
},
|
||||||
|
|
||||||
|
'message_list': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'links': {
|
||||||
|
'type': 'array',
|
||||||
|
'items': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'rel': {
|
||||||
|
'type': 'string'
|
||||||
|
},
|
||||||
|
'href': {
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^/v1\.1/queues/[a-zA-Z0-9_-]+'
|
||||||
|
'/messages\?(.)*$'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['rel', 'href'],
|
||||||
|
'additionalProperties': False
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'messages': {
|
||||||
|
"type": "array",
|
||||||
|
"items": message,
|
||||||
|
"minItems": 0,
|
||||||
|
"maxItems": self.limits.max_messages_per_claim
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'shard-detail': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'uri': {
|
||||||
|
'type': 'string'
|
||||||
|
},
|
||||||
|
'weight': {
|
||||||
|
'type': 'number',
|
||||||
|
'minimum': -1
|
||||||
|
},
|
||||||
|
'href': {
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^/v1\.1/shards/'
|
||||||
|
'[a-zA-Z0-9_\-]+$'
|
||||||
|
},
|
||||||
|
'options': {
|
||||||
|
'type': 'object',
|
||||||
|
'additionalProperties': True
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['uri', 'weight', 'href'],
|
||||||
|
'additionalProperties': False
|
||||||
|
},
|
||||||
|
|
||||||
|
'claim_create': {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"href": claim_href,
|
||||||
|
"ttl": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": self.limits.max_message_ttl
|
||||||
|
},
|
||||||
|
"age": age,
|
||||||
|
"body": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["href", "ttl", "age", "body"],
|
||||||
|
"additionalProperties": False,
|
||||||
|
},
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": self.limits.max_messages_per_page
|
||||||
|
},
|
||||||
|
|
||||||
|
'claim_get': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'age': age,
|
||||||
|
'ttl': {
|
||||||
|
'type': 'number',
|
||||||
|
'minimum': 0,
|
||||||
|
'maximum': self.limits.max_claim_ttl
|
||||||
|
},
|
||||||
|
'href': {
|
||||||
|
'type': 'string',
|
||||||
|
'pattern': '^/v1\.1/queues/[a-zA-Z0-9_-]+'
|
||||||
|
'/claims/[a-zA-Z0-9_-]+$'
|
||||||
|
},
|
||||||
|
'messages': {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"href": claim_href,
|
||||||
|
"ttl": {
|
||||||
|
"type": "number",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": self.limits.max_message_ttl
|
||||||
|
},
|
||||||
|
"age": age,
|
||||||
|
"body": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["href", "ttl", "age", "body"],
|
||||||
|
"additionalProperties": False,
|
||||||
|
},
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": self.limits.max_messages_per_page
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'required': ['age', 'ttl', 'messages', 'href'],
|
||||||
|
'additionalProperties': False
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,7 +22,8 @@ import jsonschema
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
from marconi.openstack.common import timeutils
|
from marconi.openstack.common import timeutils
|
||||||
from marconi.queues.api.v1 import response
|
from marconi.queues.api.v1 import response as response_v1
|
||||||
|
from marconi.queues.api.v1_1 import response as response_v1_1
|
||||||
from marconi.queues import bootstrap
|
from marconi.queues import bootstrap
|
||||||
# TODO(flaper87): This is necessary to register,
|
# TODO(flaper87): This is necessary to register,
|
||||||
# wsgi configs and won't be permanent. It'll be
|
# wsgi configs and won't be permanent. It'll be
|
||||||
@ -49,7 +50,6 @@ class FunctionalTestBase(testing.TestBase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(FunctionalTestBase, self).setUp()
|
super(FunctionalTestBase, self).setUp()
|
||||||
|
|
||||||
# NOTE(flaper87): Config can't be a class
|
# NOTE(flaper87): Config can't be a class
|
||||||
# attribute because it may be necessary to
|
# attribute because it may be necessary to
|
||||||
# modify it at runtime which will affect
|
# modify it at runtime which will affect
|
||||||
@ -63,8 +63,6 @@ class FunctionalTestBase(testing.TestBase):
|
|||||||
|
|
||||||
validator = validation.Validator(self.mconf)
|
validator = validation.Validator(self.mconf)
|
||||||
self.limits = validator._limits_conf
|
self.limits = validator._limits_conf
|
||||||
self.response = response.ResponseSchema(self.limits)
|
|
||||||
|
|
||||||
if _TEST_INTEGRATION:
|
if _TEST_INTEGRATION:
|
||||||
# TODO(kgriffs): This code should be replaced to use
|
# TODO(kgriffs): This code should be replaced to use
|
||||||
# an external wsgi server instance.
|
# an external wsgi server instance.
|
||||||
@ -118,20 +116,6 @@ class FunctionalTestBase(testing.TestBase):
|
|||||||
', actual count = {1}'.format(expectedCount, actualCount))
|
', actual count = {1}'.format(expectedCount, actualCount))
|
||||||
self.assertTrue(actualCount <= expectedCount, msg)
|
self.assertTrue(actualCount <= expectedCount, msg)
|
||||||
|
|
||||||
def assertSchema(self, response, expectedSchemaName):
|
|
||||||
"""Compares the json response with the expected schema
|
|
||||||
|
|
||||||
:param response: response json returned by the API.
|
|
||||||
:type response: dict
|
|
||||||
:param expectedSchema: expected schema definition for response.
|
|
||||||
:type expectedSchema: string
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
expectedSchema = self.response.get_schema(expectedSchemaName)
|
|
||||||
jsonschema.validate(response, expectedSchema)
|
|
||||||
except jsonschema.ValidationError as message:
|
|
||||||
assert False, message
|
|
||||||
|
|
||||||
def assertQueueStats(self, result_json, claimed):
|
def assertQueueStats(self, result_json, claimed):
|
||||||
"""Checks the Queue Stats results
|
"""Checks the Queue Stats results
|
||||||
|
|
||||||
@ -154,6 +138,20 @@ class FunctionalTestBase(testing.TestBase):
|
|||||||
newest_message = result_json['messages']['newest']
|
newest_message = result_json['messages']['newest']
|
||||||
self.verify_message_stats(newest_message)
|
self.verify_message_stats(newest_message)
|
||||||
|
|
||||||
|
def assertSchema(self, response, expectedSchemaName):
|
||||||
|
"""Compares the json response with the expected schema
|
||||||
|
|
||||||
|
:param response: response json returned by the API.
|
||||||
|
:type response: dict
|
||||||
|
:param expectedSchema: expected schema definition for response.
|
||||||
|
:type expectedSchema: string
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
expectedSchema = self.response.get_schema(expectedSchemaName)
|
||||||
|
jsonschema.validate(response, expectedSchema)
|
||||||
|
except jsonschema.ValidationError as message:
|
||||||
|
assert False, message
|
||||||
|
|
||||||
def verify_message_stats(self, message):
|
def verify_message_stats(self, message):
|
||||||
"""Verifies the oldest & newest message stats
|
"""Verifies the oldest & newest message stats
|
||||||
|
|
||||||
@ -276,3 +274,15 @@ class MarconiAdminServer(Server):
|
|||||||
server = bootstrap.Bootstrap(conf)
|
server = bootstrap.Bootstrap(conf)
|
||||||
conf.admin_mode = False
|
conf.admin_mode = False
|
||||||
return server.run
|
return server.run
|
||||||
|
|
||||||
|
|
||||||
|
class V1FunctionalTestBase(FunctionalTestBase):
|
||||||
|
def setUp(self):
|
||||||
|
super(V1FunctionalTestBase, self).setUp()
|
||||||
|
self.response = response_v1.ResponseSchema(self.limits)
|
||||||
|
|
||||||
|
|
||||||
|
class V1_1FunctionalTestBase(FunctionalTestBase):
|
||||||
|
def setUp(self):
|
||||||
|
super(V1_1FunctionalTestBase, self).setUp()
|
||||||
|
self.response = response_v1_1.ResponseSchema(self.limits)
|
||||||
|
@ -33,7 +33,6 @@ _AUTH_OPTIONS = (
|
|||||||
_MARCONI_OPTIONS = (
|
_MARCONI_OPTIONS = (
|
||||||
cfg.BoolOpt("run_server", default=True),
|
cfg.BoolOpt("run_server", default=True),
|
||||||
cfg.StrOpt("url", default="http://127.0.0.1:8888"),
|
cfg.StrOpt("url", default="http://127.0.0.1:8888"),
|
||||||
cfg.StrOpt("version", default="v1"),
|
|
||||||
cfg.StrOpt("config", default="functional-marconi.conf"),
|
cfg.StrOpt("config", default="functional-marconi.conf"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -99,3 +99,16 @@ def create_message_body(**kwargs):
|
|||||||
"""
|
"""
|
||||||
message_count = kwargs['messagecount']
|
message_count = kwargs['messagecount']
|
||||||
return [single_message_body(**kwargs) for i in range(message_count)]
|
return [single_message_body(**kwargs) for i in range(message_count)]
|
||||||
|
|
||||||
|
|
||||||
|
def create_shard_body(**kwargs):
|
||||||
|
shard_body = {
|
||||||
|
'weight': kwargs['weight'],
|
||||||
|
'uri': kwargs['uri'],
|
||||||
|
'options': {
|
||||||
|
'max_retry_sleep': 1,
|
||||||
|
'partitions': 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shard_body
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
[marconi]
|
[marconi]
|
||||||
# run_server = True
|
# run_server = True
|
||||||
# url = http://0.0.0.0:8888
|
# url = http://0.0.0.0:8888
|
||||||
# version = v1
|
|
||||||
# config = functional-marconi.conf
|
# config = functional-marconi.conf
|
||||||
|
|
||||||
[headers]
|
[headers]
|
||||||
|
@ -22,7 +22,7 @@ from marconi.tests.functional import helpers
|
|||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class TestClaims(base.FunctionalTestBase):
|
class TestClaims(base.V1FunctionalTestBase):
|
||||||
"""Tests for Claims."""
|
"""Tests for Claims."""
|
||||||
|
|
||||||
server_class = base.MarconiServer
|
server_class = base.MarconiServer
|
||||||
@ -33,7 +33,7 @@ class TestClaims(base.FunctionalTestBase):
|
|||||||
self.queue = uuid.uuid1()
|
self.queue = uuid.uuid1()
|
||||||
self.queue_url = ("{url}/{version}/queues/{queue}".format(
|
self.queue_url = ("{url}/{version}/queues/{queue}".format(
|
||||||
url=self.cfg.marconi.url,
|
url=self.cfg.marconi.url,
|
||||||
version=self.cfg.marconi.version,
|
version="v1",
|
||||||
queue=self.queue))
|
queue=self.queue))
|
||||||
|
|
||||||
self.client.put(self.queue_url)
|
self.client.put(self.queue_url)
|
||||||
@ -52,8 +52,7 @@ class TestClaims(base.FunctionalTestBase):
|
|||||||
@ddt.data({}, dict(limit=2))
|
@ddt.data({}, dict(limit=2))
|
||||||
def test_claim_messages(self, params):
|
def test_claim_messages(self, params):
|
||||||
"""Claim messages."""
|
"""Claim messages."""
|
||||||
message_count = params.get('limit',
|
message_count = params.get('limit', self.limits.max_messages_per_claim)
|
||||||
self.limits.max_messages_per_claim)
|
|
||||||
|
|
||||||
doc = {"ttl": 300, "grace": 100}
|
doc = {"ttl": 300, "grace": 100}
|
||||||
|
|
||||||
@ -65,7 +64,6 @@ class TestClaims(base.FunctionalTestBase):
|
|||||||
|
|
||||||
response_headers = set(result.headers.keys())
|
response_headers = set(result.headers.keys())
|
||||||
self.assertIsSubset(self.headers_response_with_body, response_headers)
|
self.assertIsSubset(self.headers_response_with_body, response_headers)
|
||||||
|
|
||||||
self.assertSchema(result.json(), 'claim_create')
|
self.assertSchema(result.json(), 'claim_create')
|
||||||
|
|
||||||
test_claim_messages.tags = ['smoke', 'positive']
|
test_claim_messages.tags = ['smoke', 'positive']
|
||||||
|
@ -24,7 +24,7 @@ from marconi.tests.functional import helpers
|
|||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class TestMessages(base.FunctionalTestBase):
|
class TestMessages(base.V1FunctionalTestBase):
|
||||||
|
|
||||||
"""Tests for Messages."""
|
"""Tests for Messages."""
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ class TestMessages(base.FunctionalTestBase):
|
|||||||
self.queue = uuid.uuid1()
|
self.queue = uuid.uuid1()
|
||||||
self.queue_url = ("{url}/{version}/queues/{queue}".format(
|
self.queue_url = ("{url}/{version}/queues/{queue}".format(
|
||||||
url=self.cfg.marconi.url,
|
url=self.cfg.marconi.url,
|
||||||
version=self.cfg.marconi.version,
|
version="v1",
|
||||||
queue=self.queue))
|
queue=self.queue))
|
||||||
|
|
||||||
self.client.put(self.queue_url)
|
self.client.put(self.queue_url)
|
||||||
@ -139,7 +139,7 @@ class TestMessages(base.FunctionalTestBase):
|
|||||||
|
|
||||||
test_message_bulk_insert.tags = ['smoke', 'positive']
|
test_message_bulk_insert.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
@ddt.data({'limit': 10}, {'limit': 5})
|
@ddt.data({}, {'limit': 5})
|
||||||
def test_get_message(self, params):
|
def test_get_message(self, params):
|
||||||
"""Get Messages."""
|
"""Get Messages."""
|
||||||
|
|
||||||
@ -164,6 +164,7 @@ class TestMessages(base.FunctionalTestBase):
|
|||||||
if result.status_code == 200:
|
if result.status_code == 200:
|
||||||
actual_msg_count = len(result.json()['messages'])
|
actual_msg_count = len(result.json()['messages'])
|
||||||
self.assertMessageCount(actual_msg_count, expected_msg_count)
|
self.assertMessageCount(actual_msg_count, expected_msg_count)
|
||||||
|
|
||||||
self.assertSchema(result.json(), 'message_list')
|
self.assertSchema(result.json(), 'message_list')
|
||||||
|
|
||||||
href = result.json()['links'][0]['href']
|
href = result.json()['links'][0]['href']
|
||||||
@ -248,6 +249,7 @@ class TestMessages(base.FunctionalTestBase):
|
|||||||
url += ',nonexisting'
|
url += ',nonexisting'
|
||||||
result = self.client.get(url)
|
result = self.client.get(url)
|
||||||
self.assertEqual(result.status_code, 200)
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
self.assertSchema(result.json(), "message_get_many")
|
self.assertSchema(result.json(), "message_get_many")
|
||||||
|
|
||||||
test_message_partial_get.tags = ['negative']
|
test_message_partial_get.tags = ['negative']
|
||||||
|
@ -68,7 +68,7 @@ def annotated(test_name, test_input):
|
|||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class TestInsertQueue(base.FunctionalTestBase):
|
class TestInsertQueue(base.V1FunctionalTestBase):
|
||||||
|
|
||||||
"""Tests for Insert queue."""
|
"""Tests for Insert queue."""
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ class TestInsertQueue(base.FunctionalTestBase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestInsertQueue, self).setUp()
|
super(TestInsertQueue, self).setUp()
|
||||||
self.base_url = '{0}/{1}'.format(self.cfg.marconi.url,
|
self.base_url = '{0}/{1}'.format(self.cfg.marconi.url,
|
||||||
self.cfg.marconi.version)
|
"v1")
|
||||||
|
|
||||||
self.header = helpers.create_marconi_headers(self.cfg)
|
self.header = helpers.create_marconi_headers(self.cfg)
|
||||||
self.headers_response_empty = set(['location'])
|
self.headers_response_empty = set(['location'])
|
||||||
@ -189,7 +189,7 @@ class TestInsertQueue(base.FunctionalTestBase):
|
|||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class TestQueueMetaData(base.FunctionalTestBase):
|
class TestQueueMetaData(base.V1FunctionalTestBase):
|
||||||
|
|
||||||
"""Tests for queue metadata."""
|
"""Tests for queue metadata."""
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ class TestQueueMetaData(base.FunctionalTestBase):
|
|||||||
super(TestQueueMetaData, self).setUp()
|
super(TestQueueMetaData, self).setUp()
|
||||||
|
|
||||||
self.base_url = '{0}/{1}'.format(self.cfg.marconi.url,
|
self.base_url = '{0}/{1}'.format(self.cfg.marconi.url,
|
||||||
self.cfg.marconi.version)
|
"v1")
|
||||||
|
|
||||||
self.queue_url = self.base_url + '/queues/{0}'.format(uuid.uuid1())
|
self.queue_url = self.base_url + '/queues/{0}'.format(uuid.uuid1())
|
||||||
self.client.put(self.queue_url)
|
self.client.put(self.queue_url)
|
||||||
@ -254,7 +254,7 @@ class TestQueueMetaData(base.FunctionalTestBase):
|
|||||||
|
|
||||||
|
|
||||||
@ddt.ddt
|
@ddt.ddt
|
||||||
class TestQueueMisc(base.FunctionalTestBase):
|
class TestQueueMisc(base.V1FunctionalTestBase):
|
||||||
|
|
||||||
server_class = base.MarconiServer
|
server_class = base.MarconiServer
|
||||||
|
|
||||||
@ -264,19 +264,16 @@ class TestQueueMisc(base.FunctionalTestBase):
|
|||||||
self.base_url = self.cfg.marconi.url
|
self.base_url = self.cfg.marconi.url
|
||||||
self.client.set_base_url(self.base_url)
|
self.client.set_base_url(self.base_url)
|
||||||
|
|
||||||
template = self.base_url + '/{0}/queues/{1}'
|
self.queue_url = (self.base_url + '/{0}/queues/{1}'
|
||||||
|
.format("v1", uuid.uuid1()))
|
||||||
self.queue_url = template.format(self.cfg.marconi.version,
|
|
||||||
uuid.uuid1())
|
|
||||||
|
|
||||||
def test_list_queues(self):
|
def test_list_queues(self):
|
||||||
"""List Queues."""
|
"""List Queues."""
|
||||||
|
|
||||||
self.client.put(self.queue_url)
|
self.client.put(self.queue_url)
|
||||||
self.addCleanup(self.client.delete, self.queue_url)
|
self.addCleanup(self.client.delete, self.queue_url)
|
||||||
|
result = self.client.get('/{0}/queues'
|
||||||
url = '/{0}/queues'.format(self.cfg.marconi.version)
|
.format('v1'))
|
||||||
result = self.client.get(url)
|
|
||||||
|
|
||||||
self.assertEqual(result.status_code, 200)
|
self.assertEqual(result.status_code, 200)
|
||||||
self.assertSchema(result.json(), 'queue_list')
|
self.assertSchema(result.json(), 'queue_list')
|
||||||
@ -291,7 +288,7 @@ class TestQueueMisc(base.FunctionalTestBase):
|
|||||||
|
|
||||||
params = {'detailed': True}
|
params = {'detailed': True}
|
||||||
result = self.client.get('/{0}/queues'
|
result = self.client.get('/{0}/queues'
|
||||||
.format(self.cfg.marconi.version),
|
.format("v1"),
|
||||||
params=params)
|
params=params)
|
||||||
self.assertEqual(result.status_code, 200)
|
self.assertEqual(result.status_code, 200)
|
||||||
self.assertSchema(result.json(), 'queue_list')
|
self.assertSchema(result.json(), 'queue_list')
|
||||||
@ -307,7 +304,7 @@ class TestQueueMisc(base.FunctionalTestBase):
|
|||||||
|
|
||||||
params = {'limit': limit}
|
params = {'limit': limit}
|
||||||
result = self.client.get('/{0}/queues'
|
result = self.client.get('/{0}/queues'
|
||||||
.format(self.cfg.marconi.version),
|
.format("v1"),
|
||||||
params=params)
|
params=params)
|
||||||
self.assertEqual(result.status_code, 400)
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
@ -317,7 +314,7 @@ class TestQueueMisc(base.FunctionalTestBase):
|
|||||||
"""Test health endpoint."""
|
"""Test health endpoint."""
|
||||||
|
|
||||||
result = self.client.get('/{0}/health'
|
result = self.client.get('/{0}/health'
|
||||||
.format(self.cfg.marconi.version))
|
.format("v1"))
|
||||||
self.assertEqual(result.status_code, 204)
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
test_check_health.tags = ['positive']
|
test_check_health.tags = ['positive']
|
||||||
@ -337,7 +334,7 @@ class TestQueueMisc(base.FunctionalTestBase):
|
|||||||
|
|
||||||
def test_check_queue_exists_negative(self):
|
def test_check_queue_exists_negative(self):
|
||||||
"""Checks non-existing queue."""
|
"""Checks non-existing queue."""
|
||||||
path = '/{0}/queues/nonexistingqueue'.format(self.cfg.marconi.version)
|
path = '/{0}/queues/nonexistingqueue'.format("v1")
|
||||||
result = self.client.get(path)
|
result = self.client.get(path)
|
||||||
self.assertEqual(result.status_code, 404)
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
@ -349,7 +346,7 @@ class TestQueueMisc(base.FunctionalTestBase):
|
|||||||
def test_get_queue_malformed_marker(self):
|
def test_get_queue_malformed_marker(self):
|
||||||
"""List queues with invalid marker."""
|
"""List queues with invalid marker."""
|
||||||
|
|
||||||
path = '/{0}/queues?marker=zzz'.format(self.cfg.marconi.version)
|
path = '/{0}/queues?marker=zzz'.format("v1")
|
||||||
result = self.client.get(path)
|
result = self.client.get(path)
|
||||||
self.assertEqual(result.status_code, 204)
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
@ -371,7 +368,6 @@ class TestQueueMisc(base.FunctionalTestBase):
|
|||||||
expected_response = {'messages':
|
expected_response = {'messages':
|
||||||
{'claimed': 0, 'total': 0, 'free': 0}}
|
{'claimed': 0, 'total': 0, 'free': 0}}
|
||||||
self.assertEqual(result.json(), expected_response)
|
self.assertEqual(result.json(), expected_response)
|
||||||
self.assertSchema(result.json(), 'queue_stats')
|
|
||||||
|
|
||||||
test_get_stats_empty_queue.tags = ['positive']
|
test_get_stats_empty_queue.tags = ['positive']
|
||||||
|
|
||||||
@ -402,7 +398,6 @@ class TestQueueMisc(base.FunctionalTestBase):
|
|||||||
self.assertEqual(result.status_code, 200)
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
self.assertQueueStats(result.json(), claimed)
|
self.assertQueueStats(result.json(), claimed)
|
||||||
self.assertSchema(result.json(), 'queue_stats')
|
|
||||||
|
|
||||||
test_get_queue_stats_claimed.tags = ['positive']
|
test_get_queue_stats_claimed.tags = ['positive']
|
||||||
|
|
||||||
@ -410,7 +405,7 @@ class TestQueueMisc(base.FunctionalTestBase):
|
|||||||
super(TestQueueMisc, self).tearDown()
|
super(TestQueueMisc, self).tearDown()
|
||||||
|
|
||||||
|
|
||||||
class TestQueueNonExisting(base.FunctionalTestBase):
|
class TestQueueNonExisting(base.V1FunctionalTestBase):
|
||||||
|
|
||||||
"""Test Actions on non existing queue."""
|
"""Test Actions on non existing queue."""
|
||||||
|
|
||||||
@ -418,10 +413,10 @@ class TestQueueNonExisting(base.FunctionalTestBase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestQueueNonExisting, self).setUp()
|
super(TestQueueNonExisting, self).setUp()
|
||||||
self.base_url = '{0}/{1}'.format(self.cfg.marconi.url,
|
self.base_url = '{0}/{1}'.format(self.cfg.marconi.url, "v1")
|
||||||
self.cfg.marconi.version)
|
|
||||||
self.queue_url = (self.base_url +
|
self.queue_url = (self.base_url +
|
||||||
'/queues/0a5b1b85-4263-11e3-b034-28cfe91478b9')
|
'/queues/0a5b1b85-4263-11e3-b034-28cfe91478b9')
|
||||||
|
|
||||||
self.client.set_base_url(self.queue_url)
|
self.client.set_base_url(self.queue_url)
|
||||||
|
|
||||||
self.header = helpers.create_marconi_headers(self.cfg)
|
self.header = helpers.create_marconi_headers(self.cfg)
|
||||||
|
0
tests/functional/wsgi/v1_1/__init__.py
Normal file
0
tests/functional/wsgi/v1_1/__init__.py
Normal file
254
tests/functional/wsgi/v1_1/test_claims.py
Normal file
254
tests/functional/wsgi/v1_1/test_claims.py
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import ddt
|
||||||
|
|
||||||
|
from marconi.tests.functional import base
|
||||||
|
from marconi.tests.functional import helpers
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class TestClaims(base.V1_1FunctionalTestBase):
|
||||||
|
"""Tests for Claims."""
|
||||||
|
|
||||||
|
server_class = base.MarconiServer
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestClaims, self).setUp()
|
||||||
|
|
||||||
|
self.headers = helpers.create_marconi_headers(self.cfg)
|
||||||
|
self.client.headers = self.headers
|
||||||
|
|
||||||
|
self.queue = uuid.uuid1()
|
||||||
|
self.queue_url = ("{url}/{version}/queues/{queue}".format(
|
||||||
|
url=self.cfg.marconi.url,
|
||||||
|
version="v1.1",
|
||||||
|
queue=self.queue))
|
||||||
|
|
||||||
|
self.client.put(self.queue_url)
|
||||||
|
|
||||||
|
self.claim_url = self.queue_url + '/claims'
|
||||||
|
self.client.set_base_url(self.claim_url)
|
||||||
|
|
||||||
|
# Post Messages
|
||||||
|
url = self.queue_url + '/messages'
|
||||||
|
doc = helpers.create_message_body(
|
||||||
|
messagecount=self.limits.max_messages_per_page)
|
||||||
|
|
||||||
|
for i in range(10):
|
||||||
|
self.client.post(url, data=doc)
|
||||||
|
|
||||||
|
@ddt.data({}, {'limit': 2})
|
||||||
|
def test_claim_messages(self, params):
|
||||||
|
"""Claim messages."""
|
||||||
|
message_count = params.get('limit', self.limits.max_messages_per_claim)
|
||||||
|
|
||||||
|
doc = {"ttl": 300, "grace": 100}
|
||||||
|
|
||||||
|
result = self.client.post(params=params, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
actual_message_count = len(result.json())
|
||||||
|
self.assertMessageCount(actual_message_count, message_count)
|
||||||
|
|
||||||
|
response_headers = set(result.headers.keys())
|
||||||
|
self.assertIsSubset(self.headers_response_with_body, response_headers)
|
||||||
|
|
||||||
|
test_claim_messages.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
def test_query_claim(self):
|
||||||
|
"""Query Claim."""
|
||||||
|
params = {'limit': 1}
|
||||||
|
doc = {"ttl": 300, "grace": 100}
|
||||||
|
|
||||||
|
result = self.client.post(params=params, data=doc)
|
||||||
|
location = result.headers['Location']
|
||||||
|
|
||||||
|
url = self.cfg.marconi.url + location
|
||||||
|
|
||||||
|
result = self.client.get(url)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
test_query_claim.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
def test_claim_more_than_allowed(self):
|
||||||
|
"""Claim more than max allowed per request.
|
||||||
|
|
||||||
|
Marconi allows a maximum of 20 messages per claim by default.
|
||||||
|
"""
|
||||||
|
params = {"limit": self.limits.max_messages_per_claim + 1}
|
||||||
|
doc = {"ttl": 300, "grace": 100}
|
||||||
|
|
||||||
|
result = self.client.post(params=params, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_claim_more_than_allowed.tags = ['negative']
|
||||||
|
|
||||||
|
def test_claim_patch(self):
|
||||||
|
"""Update Claim."""
|
||||||
|
# Test Setup - Post Claim
|
||||||
|
doc = {"ttl": 300, "grace": 400}
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Patch Claim
|
||||||
|
claim_location = result.headers['Location']
|
||||||
|
url = self.cfg.marconi.url + claim_location
|
||||||
|
doc_updated = {"ttl": 300}
|
||||||
|
|
||||||
|
result = self.client.patch(url, data=doc_updated)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
# verify that the claim TTL is updated
|
||||||
|
result = self.client.get(url)
|
||||||
|
new_ttl = result.json()['ttl']
|
||||||
|
self.assertEqual(new_ttl, 300)
|
||||||
|
|
||||||
|
test_claim_patch.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
def test_delete_claimed_message(self):
|
||||||
|
"""Delete message belonging to a Claim."""
|
||||||
|
# Test Setup - Post claim
|
||||||
|
doc = {"ttl": 60, "grace": 60}
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Delete Claimed Messages
|
||||||
|
for rst in result.json():
|
||||||
|
href = rst['href']
|
||||||
|
url = self.cfg.marconi.url + href
|
||||||
|
result = self.client.delete(url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_delete_claimed_message.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
def test_claim_release(self):
|
||||||
|
"""Release Claim."""
|
||||||
|
doc = {"ttl": 300, "grace": 100}
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Extract claim location and construct the claim URL.
|
||||||
|
location = result.headers['Location']
|
||||||
|
url = self.cfg.marconi.url + location
|
||||||
|
|
||||||
|
# Release Claim.
|
||||||
|
result = self.client.delete(url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_claim_release.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
@ddt.data(10000000000000000000, -100, 1, 59, 43201, -10000000000000000000)
|
||||||
|
def test_claim_invalid_ttl(self, ttl):
|
||||||
|
"""Post Claim with invalid TTL.
|
||||||
|
|
||||||
|
The request JSON body will have a TTL value
|
||||||
|
outside the allowed range.Allowed ttl values is
|
||||||
|
60 <= ttl <= 43200.
|
||||||
|
"""
|
||||||
|
doc = {"ttl": ttl, "grace": 100}
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_claim_invalid_ttl.tags = ['negative']
|
||||||
|
|
||||||
|
@ddt.data(10000000000000000000, -100, 1, 59, 43201, -10000000000000000000)
|
||||||
|
def test_claim_invalid_grace(self, grace):
|
||||||
|
"""Post Claim with invalid grace.
|
||||||
|
|
||||||
|
The request JSON body will have a grace value
|
||||||
|
outside the allowed range.Allowed grace values is
|
||||||
|
60 <= grace <= 43200.
|
||||||
|
"""
|
||||||
|
doc = {"ttl": 100, "grace": grace}
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_claim_invalid_grace.tags = ['negative']
|
||||||
|
|
||||||
|
@ddt.data(0, -100, 30, 10000000000000000000)
|
||||||
|
def test_claim_invalid_limit(self, grace):
|
||||||
|
"""Post Claim with invalid limit.
|
||||||
|
|
||||||
|
The request url will have a limit outside the allowed range.
|
||||||
|
Allowed limit values are 0 < limit <= 20(default max).
|
||||||
|
"""
|
||||||
|
doc = {"ttl": 100, "grace": grace}
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_claim_invalid_limit.tags = ['negative']
|
||||||
|
|
||||||
|
@ddt.data(10000000000000000000, -100, 1, 59, 43201, -10000000000000000000)
|
||||||
|
def test_patch_claim_invalid_ttl(self, ttl):
|
||||||
|
"""Patch Claim with invalid TTL.
|
||||||
|
|
||||||
|
The request JSON body will have a TTL value
|
||||||
|
outside the allowed range.Allowed ttl values is
|
||||||
|
60 <= ttl <= 43200.
|
||||||
|
"""
|
||||||
|
doc = {"ttl": 100, "grace": 100}
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Extract claim location and construct the claim URL.
|
||||||
|
location = result.headers['Location']
|
||||||
|
url = self.cfg.marconi.url + location
|
||||||
|
|
||||||
|
# Patch Claim.
|
||||||
|
doc = {"ttl": ttl}
|
||||||
|
result = self.client.patch(url, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_patch_claim_invalid_ttl.tags = ['negative']
|
||||||
|
|
||||||
|
def test_query_non_existing_claim(self):
|
||||||
|
"""Query Non Existing Claim."""
|
||||||
|
path = '/non-existing-claim'
|
||||||
|
result = self.client.get(path)
|
||||||
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
|
test_query_non_existing_claim.tags = ['negative']
|
||||||
|
|
||||||
|
def test_patch_non_existing_claim(self):
|
||||||
|
"""Patch Non Existing Claim."""
|
||||||
|
path = '/non-existing-claim'
|
||||||
|
doc = {"ttl": 400}
|
||||||
|
result = self.client.patch(path, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
|
test_patch_non_existing_claim.tags = ['negative']
|
||||||
|
|
||||||
|
def test_delete_non_existing_claim(self):
|
||||||
|
"""Patch Non Existing Claim."""
|
||||||
|
path = '/non-existing-claim'
|
||||||
|
result = self.client.delete(path)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_delete_non_existing_claim.tags = ['negative']
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""Delete Queue after Claim Test."""
|
||||||
|
super(TestClaims, self).tearDown()
|
||||||
|
self.client.delete(self.queue_url)
|
455
tests/functional/wsgi/v1_1/test_messages.py
Normal file
455
tests/functional/wsgi/v1_1/test_messages.py
Normal file
@ -0,0 +1,455 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import ddt
|
||||||
|
|
||||||
|
from marconi.tests.functional import base
|
||||||
|
from marconi.tests.functional import helpers
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class TestMessages(base.V1_1FunctionalTestBase):
|
||||||
|
|
||||||
|
"""Message Tests Specific to V1.1."""
|
||||||
|
|
||||||
|
server_class = base.MarconiServer
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestMessages, self).setUp()
|
||||||
|
|
||||||
|
self.queue = uuid.uuid1() # Generate a random queue ID
|
||||||
|
self.queue_url = ("{url}/{version}/queues/{queue}".format(
|
||||||
|
url=self.cfg.marconi.url,
|
||||||
|
version="v1.1",
|
||||||
|
queue=self.queue))
|
||||||
|
|
||||||
|
self.headers = helpers.create_marconi_headers(self.cfg)
|
||||||
|
self.client.headers = self.headers
|
||||||
|
|
||||||
|
self.client.put(self.queue_url) # Create the queue
|
||||||
|
self.message_url = self.queue_url+'/messages'
|
||||||
|
self.client.set_base_url(self.message_url)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.client.delete(self.queue_url) # Remove the queue
|
||||||
|
super(TestMessages, self).tearDown()
|
||||||
|
|
||||||
|
# TODO(abettadapur) Not sure if return format is right
|
||||||
|
def test_message_single_pop(self):
|
||||||
|
"""Pop a message."""
|
||||||
|
# Setup
|
||||||
|
self.skipTest("Not supported")
|
||||||
|
doc = helpers.create_message_body(messagecount=1)
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
href = result.json()['links'][0]['href']
|
||||||
|
index = href.find('/')
|
||||||
|
id = href[index+1:]
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
# Pop a message, compare the HREFs. They should be the same
|
||||||
|
url = self.message_url+'?pop=1'
|
||||||
|
result = self.client.delete(url)
|
||||||
|
claimid = result.json()['messages'][0]['id']
|
||||||
|
self.assertEqual(claimid, id)
|
||||||
|
# Make sure there are no messages left in the queue
|
||||||
|
result = self.client.get(self.message_url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
# TODO(abettadapur) Not sure if return format is right
|
||||||
|
def test_message_bulk_pop(self):
|
||||||
|
"""Pop multiple messages."""
|
||||||
|
# Setup
|
||||||
|
self.skipTest("Not supported")
|
||||||
|
doc = helpers.create_message_body(messagecount=10)
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
links = result.json()["links"]
|
||||||
|
|
||||||
|
# Gather inserted ids
|
||||||
|
ids = []
|
||||||
|
for item in links:
|
||||||
|
href = item['href']
|
||||||
|
index = href.find('/')
|
||||||
|
ids.append(href[index:])
|
||||||
|
|
||||||
|
# Pop the 10 messages
|
||||||
|
url = self.message_url+'?pop=10'
|
||||||
|
result = self.client.delete(url)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
claims = result.json()
|
||||||
|
|
||||||
|
# compare the HREFS
|
||||||
|
match = True
|
||||||
|
for i in range(0, 10):
|
||||||
|
if ids[i] != claims['messages'][i]['id']:
|
||||||
|
match = False
|
||||||
|
break
|
||||||
|
|
||||||
|
self.assertEqual(match, True)
|
||||||
|
# Make sure there are no messages left in the queue
|
||||||
|
result = self.client.get(self.message_url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
def test_message_pop_too_high(self):
|
||||||
|
self.skipTest("Not supported")
|
||||||
|
url = self.message_url+'?pop=21'
|
||||||
|
result = self.client.delete(url)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
def _post_large_bulk_insert(self, offset):
|
||||||
|
"""Insert just under than max allowed messages."""
|
||||||
|
|
||||||
|
doc = '[{{"body": "{0}", "ttl": 300}}, {{"body": "{1}", "ttl": 120}}]'
|
||||||
|
overhead = len(doc.format('', ''))
|
||||||
|
|
||||||
|
half_size = (self.limits.max_message_size - overhead) // 2
|
||||||
|
doc = doc.format(helpers.generate_random_string(half_size),
|
||||||
|
helpers.generate_random_string(half_size + offset))
|
||||||
|
|
||||||
|
return self.client.post(data=doc)
|
||||||
|
|
||||||
|
def test_message_single_insert(self):
|
||||||
|
"""Insert Single Message into the Queue.
|
||||||
|
|
||||||
|
This test also verifies that claimed messages are
|
||||||
|
retuned (or not) depending on the include_claimed flag.
|
||||||
|
"""
|
||||||
|
doc = helpers.create_message_body(messagecount=1)
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
response_headers = set(result.headers.keys())
|
||||||
|
self.assertIsSubset(self.headers_response_with_body, response_headers)
|
||||||
|
|
||||||
|
# GET on posted message
|
||||||
|
href = result.json()['resources'][0]
|
||||||
|
url = self.cfg.marconi.url + href
|
||||||
|
|
||||||
|
result = self.client.get(url)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
# Compare message metadata
|
||||||
|
result_body = result.json()['body']
|
||||||
|
posted_metadata = doc[0]['body']
|
||||||
|
self.assertEqual(result_body, posted_metadata)
|
||||||
|
|
||||||
|
# Post a claim & verify the include_claimed flag.
|
||||||
|
url = self.queue_url + '/claims'
|
||||||
|
doc = {"ttl": 300, "grace": 100}
|
||||||
|
result = self.client.post(url, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
params = {'include_claimed': True,
|
||||||
|
'echo': True}
|
||||||
|
result = self.client.get(params=params)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
response_message_body = result.json()["messages"][0]["body"]
|
||||||
|
self.assertEqual(response_message_body, posted_metadata)
|
||||||
|
|
||||||
|
# By default, include_claimed = false
|
||||||
|
result = self.client.get(self.message_url)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
test_message_single_insert.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
def test_message_bulk_insert(self):
|
||||||
|
"""Bulk Insert Messages into the Queue."""
|
||||||
|
message_count = self.limits.max_messages_per_page
|
||||||
|
doc = helpers.create_message_body(messagecount=message_count)
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# GET on posted messages
|
||||||
|
location = result.headers['location']
|
||||||
|
url = self.cfg.marconi.url + location
|
||||||
|
result = self.client.get(url)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
self.skipTest('Bug #1273335 - Get set of messages returns wrong hrefs '
|
||||||
|
'(happens randomly)')
|
||||||
|
|
||||||
|
# Verify that the response json schema matches the expected schema
|
||||||
|
self.assertSchema(result.json(), 'message_get_many')
|
||||||
|
|
||||||
|
# Compare message metadata
|
||||||
|
result_body = [result.json()[i]['body']
|
||||||
|
for i in range(len(result.json()))]
|
||||||
|
result_body.sort()
|
||||||
|
|
||||||
|
posted_metadata = [doc[i]['body']
|
||||||
|
for i in range(message_count)]
|
||||||
|
posted_metadata.sort()
|
||||||
|
|
||||||
|
self.assertEqual(result_body, posted_metadata)
|
||||||
|
|
||||||
|
test_message_bulk_insert.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
@ddt.data({}, {'limit': 5})
|
||||||
|
def test_get_message(self, params):
|
||||||
|
"""Get Messages."""
|
||||||
|
|
||||||
|
# Note(abettadapur): This will now return 200s and [].
|
||||||
|
# Needs to be addressed when feature patch goes in
|
||||||
|
self.skipTest("Not supported")
|
||||||
|
expected_msg_count = params.get('limit',
|
||||||
|
self.limits.max_messages_per_page)
|
||||||
|
|
||||||
|
# Test Setup
|
||||||
|
doc = helpers.create_message_body(
|
||||||
|
messagecount=self.limits.max_messages_per_page)
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
url = ''
|
||||||
|
params['echo'] = True
|
||||||
|
|
||||||
|
# Follow the hrefs & perform GET, till the end of messages i.e. http
|
||||||
|
# 204
|
||||||
|
while result.status_code in [201, 200]:
|
||||||
|
result = self.client.get(url, params=params)
|
||||||
|
self.assertIn(result.status_code, [200, 204])
|
||||||
|
|
||||||
|
if result.status_code == 200:
|
||||||
|
actual_msg_count = len(result.json()['messages'])
|
||||||
|
self.assertMessageCount(actual_msg_count, expected_msg_count)
|
||||||
|
|
||||||
|
href = result.json()['links'][0]['href']
|
||||||
|
url = self.cfg.marconi.url + href
|
||||||
|
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_get_message.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
def test_message_delete(self):
|
||||||
|
"""Delete Message."""
|
||||||
|
# Test Setup
|
||||||
|
doc = helpers.create_message_body(messagecount=1)
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Delete posted message
|
||||||
|
href = result.json()['resources'][0]
|
||||||
|
url = self.cfg.marconi.url + href
|
||||||
|
|
||||||
|
result = self.client.delete(url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
result = self.client.get(url)
|
||||||
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
|
test_message_delete.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
def test_message_bulk_delete(self):
|
||||||
|
"""Bulk Delete Messages."""
|
||||||
|
doc = helpers.create_message_body(messagecount=10)
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Delete posted messages
|
||||||
|
location = result.headers['Location']
|
||||||
|
url = self.cfg.marconi.url + location
|
||||||
|
|
||||||
|
result = self.client.delete(url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
result = self.client.get(url)
|
||||||
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
|
test_message_bulk_delete.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
def test_message_delete_nonexisting(self):
|
||||||
|
"""Delete non-existing Messages."""
|
||||||
|
result = self.client.delete('/non-existing')
|
||||||
|
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_message_delete_nonexisting.tags = ['negative']
|
||||||
|
|
||||||
|
def test_message_partial_delete(self):
|
||||||
|
"""Delete Messages will be partially successful."""
|
||||||
|
doc = helpers.create_message_body(messagecount=3)
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Delete posted message
|
||||||
|
location = result.headers['Location']
|
||||||
|
url = self.cfg.marconi.url + location
|
||||||
|
url += ',nonexisting'
|
||||||
|
result = self.client.delete(url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_message_partial_delete.tags = ['negative']
|
||||||
|
|
||||||
|
def test_message_partial_get(self):
|
||||||
|
"""Get Messages will be partially successful."""
|
||||||
|
doc = helpers.create_message_body(messagecount=3)
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Get posted message and a nonexisting message
|
||||||
|
location = result.headers['Location']
|
||||||
|
url = self.cfg.marconi.url + location
|
||||||
|
url += ',nonexisting'
|
||||||
|
result = self.client.get(url)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
test_message_partial_get.tags = ['negative']
|
||||||
|
|
||||||
|
@ddt.data(-10, -1, 0)
|
||||||
|
def test_message_bulk_insert_large_bodies(self, offset):
|
||||||
|
"""Insert just under than max allowed messages."""
|
||||||
|
result = self._post_large_bulk_insert(offset)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
test_message_bulk_insert_large_bodies.tags = ['positive']
|
||||||
|
|
||||||
|
@ddt.data(1, 10)
|
||||||
|
def test_message_bulk_insert_large_bodies(self, offset):
|
||||||
|
"""Insert just under than max allowed messages."""
|
||||||
|
result = self._post_large_bulk_insert(offset)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_message_bulk_insert_large_bodies.tags = ['negative']
|
||||||
|
|
||||||
|
def test_message_bulk_insert_oversized(self):
|
||||||
|
"""Insert more than max allowed size."""
|
||||||
|
|
||||||
|
doc = '[{{"body": "{0}", "ttl": 300}}, {{"body": "{1}", "ttl": 120}}]'
|
||||||
|
overhead = len(doc.format('', ''))
|
||||||
|
|
||||||
|
half_size = (self.limits.max_message_size - overhead) // 2
|
||||||
|
doc = doc.format(helpers.generate_random_string(half_size),
|
||||||
|
helpers.generate_random_string(half_size + 1))
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_message_bulk_insert_oversized.tags = ['negative']
|
||||||
|
|
||||||
|
@ddt.data(10000000000000000000, -100, 0, 30, -10000000000000000000)
|
||||||
|
def test_message_get_invalid_limit(self, limit):
|
||||||
|
"""Get Messages with invalid value for limit.
|
||||||
|
|
||||||
|
Allowed values for limit are 0 < limit <= 20(configurable).
|
||||||
|
"""
|
||||||
|
params = {'limit': limit}
|
||||||
|
result = self.client.get(params=params)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_message_get_invalid_limit.tags = ['negative']
|
||||||
|
|
||||||
|
def test_message_bulk_delete_negative(self):
|
||||||
|
"""Delete more messages than allowed in a single request.
|
||||||
|
|
||||||
|
By default, max messages that can be deleted in a single
|
||||||
|
request is 20.
|
||||||
|
"""
|
||||||
|
url = (self.message_url + '?ids='
|
||||||
|
+ ','.join(str(i) for i in
|
||||||
|
range(self.limits.max_messages_per_page + 1)))
|
||||||
|
result = self.client.delete(url)
|
||||||
|
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_message_bulk_delete_negative.tags = ['negative']
|
||||||
|
|
||||||
|
def test_message_bulk_get_negative(self):
|
||||||
|
"""GET more messages by id than allowed in a single request.
|
||||||
|
|
||||||
|
By default, max messages that can be fetched in a single
|
||||||
|
request is 20.
|
||||||
|
"""
|
||||||
|
|
||||||
|
url = (self.message_url + '?ids='
|
||||||
|
+ ','.join(str(i) for i in
|
||||||
|
range(self.limits.max_messages_per_page + 1)))
|
||||||
|
|
||||||
|
result = self.client.get(url)
|
||||||
|
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_message_bulk_get_negative.tags = ['negative']
|
||||||
|
|
||||||
|
def test_get_messages_malformed_marker(self):
|
||||||
|
"""Get messages with non-existing marker."""
|
||||||
|
url = self.message_url + '?marker=invalid'
|
||||||
|
|
||||||
|
result = self.client.get(url, headers=self.headers)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertSchema(result.json(), 'message_list')
|
||||||
|
|
||||||
|
test_get_messages_malformed_marker.tags = ['negative']
|
||||||
|
|
||||||
|
@ddt.data(None, '1234', 'aa2-bb3',
|
||||||
|
'103e09c6-31b7-11e3-86bc-b8ca3ad0f5d81',
|
||||||
|
'103e09c6-31b7-11e3-86bc-b8ca3ad0f5d')
|
||||||
|
def test_get_messages_invalid_client_id(self, client_id):
|
||||||
|
"""Get messages with invalid client id."""
|
||||||
|
url = self.message_url
|
||||||
|
|
||||||
|
header = helpers.create_marconi_headers(self.cfg)
|
||||||
|
header['Client-ID'] = client_id
|
||||||
|
|
||||||
|
result = self.client.get(url, headers=header)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_get_messages_invalid_client_id.tags = ['negative']
|
||||||
|
|
||||||
|
def test_query_non_existing_message(self):
|
||||||
|
"""Get Non Existing Message."""
|
||||||
|
path = '/non-existing-message'
|
||||||
|
result = self.client.get(path)
|
||||||
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
|
test_query_non_existing_message.tags = ['negative']
|
||||||
|
|
||||||
|
def test_query_non_existing_message_set(self):
|
||||||
|
"""Get Set of Non Existing Messages."""
|
||||||
|
path = '?ids=not_there1,not_there2'
|
||||||
|
result = self.client.get(path)
|
||||||
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
|
test_query_non_existing_message_set.tags = ['negative']
|
||||||
|
|
||||||
|
def test_delete_non_existing_message(self):
|
||||||
|
"""Delete Non Existing Message."""
|
||||||
|
path = '/non-existing-message'
|
||||||
|
result = self.client.delete(path)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_delete_non_existing_message.tags = ['negative']
|
||||||
|
|
||||||
|
def test_message_bad_header_single_insert(self):
|
||||||
|
"""Insert Single Message into the Queue.
|
||||||
|
|
||||||
|
This should fail because of the lack of a Client-ID header
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.skipTest("Not supported")
|
||||||
|
del self.client.headers["Client-ID"]
|
||||||
|
doc = helpers.create_message_body(messagecount=1)
|
||||||
|
|
||||||
|
result = self.client.post(data=doc)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
405
tests/functional/wsgi/v1_1/test_queues.py
Normal file
405
tests/functional/wsgi/v1_1/test_queues.py
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
import copy
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import ddt
|
||||||
|
import six
|
||||||
|
|
||||||
|
from marconi.tests.functional import base # noqa
|
||||||
|
from marconi.tests.functional import helpers
|
||||||
|
|
||||||
|
|
||||||
|
class NamedBinaryStr(six.binary_type):
|
||||||
|
|
||||||
|
"""Wrapper for six.binary_type to facilitate overriding __name__."""
|
||||||
|
|
||||||
|
|
||||||
|
class NamedUnicodeStr(six.text_type):
|
||||||
|
|
||||||
|
"""Unicode string look-alike to facilitate overriding __name__."""
|
||||||
|
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
def encode(self, enc):
|
||||||
|
return self.value.encode(enc)
|
||||||
|
|
||||||
|
def __format__(self, formatstr):
|
||||||
|
"""Workaround for ddt bug.
|
||||||
|
|
||||||
|
DDT will always call __format__ even when __name__ exists,
|
||||||
|
which blows up for Unicode strings under Py2.
|
||||||
|
"""
|
||||||
|
return ''
|
||||||
|
|
||||||
|
|
||||||
|
class NamedDict(dict):
|
||||||
|
|
||||||
|
"""Wrapper for dict to facilitate overriding __name__."""
|
||||||
|
|
||||||
|
|
||||||
|
def annotated(test_name, test_input):
|
||||||
|
if isinstance(test_input, dict):
|
||||||
|
annotated_input = NamedDict(test_input)
|
||||||
|
elif isinstance(test_input, six.text_type):
|
||||||
|
annotated_input = NamedUnicodeStr(test_input)
|
||||||
|
else:
|
||||||
|
annotated_input = NamedBinaryStr(test_input)
|
||||||
|
|
||||||
|
setattr(annotated_input, '__name__', test_name)
|
||||||
|
return annotated_input
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class TestInsertQueue(base.V1_1FunctionalTestBase):
|
||||||
|
|
||||||
|
"""Tests for Insert queue."""
|
||||||
|
|
||||||
|
server_class = base.MarconiServer
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestInsertQueue, self).setUp()
|
||||||
|
self.base_url = '{0}/{1}'.format(self.cfg.marconi.url,
|
||||||
|
"v1.1")
|
||||||
|
|
||||||
|
self.header = helpers.create_marconi_headers(self.cfg)
|
||||||
|
self.headers_response_empty = set(['location'])
|
||||||
|
self.client.set_base_url(self.base_url)
|
||||||
|
self.client.headers = self.header
|
||||||
|
|
||||||
|
@ddt.data('qtestqueue', 'TESTqueue', 'hyphen-name', '_undersore',
|
||||||
|
annotated('test_insert_queue_long_name', 'i' * 64))
|
||||||
|
def test_insert_queue(self, queue_name):
|
||||||
|
"""Create Queue."""
|
||||||
|
self.url = self.base_url + '/queues/' + queue_name
|
||||||
|
self.addCleanup(self.client.delete, self.url)
|
||||||
|
|
||||||
|
result = self.client.put(self.url)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
response_headers = set(result.headers.keys())
|
||||||
|
self.assertIsSubset(self.headers_response_empty, response_headers)
|
||||||
|
|
||||||
|
result = self.client.get(self.url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_insert_queue.tags = ['positive', 'smoke']
|
||||||
|
|
||||||
|
@ddt.data(annotated('test_insert_queue_non_ascii_name',
|
||||||
|
u'\u6c49\u5b57\u6f22\u5b57'),
|
||||||
|
'@$@^qw',
|
||||||
|
annotated('test_insert_queue_invalid_name_length', 'i' * 65))
|
||||||
|
def test_insert_queue_invalid_name(self, queue_name):
|
||||||
|
"""Create Queue."""
|
||||||
|
if six.PY2 and isinstance(queue_name, NamedUnicodeStr):
|
||||||
|
queue_name = queue_name.encode('utf-8')
|
||||||
|
|
||||||
|
self.url = self.base_url + '/queues/' + queue_name
|
||||||
|
self.addCleanup(self.client.delete, self.url)
|
||||||
|
|
||||||
|
result = self.client.put(self.url)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_insert_queue_invalid_name.tags = ['negative']
|
||||||
|
|
||||||
|
def test_insert_queue_invalid_authtoken(self):
|
||||||
|
"""Insert Queue with invalid authtoken."""
|
||||||
|
|
||||||
|
# NOTE(flaper87): Currently, tearDown
|
||||||
|
# depends on this attribute. Needs to
|
||||||
|
# be fixed.
|
||||||
|
self.url = self.base_url + '/queues/invalidauthtoken'
|
||||||
|
self.addCleanup(self.client.delete, self.url)
|
||||||
|
|
||||||
|
if not self.cfg.auth.auth_on:
|
||||||
|
self.skipTest("Auth is not on!")
|
||||||
|
|
||||||
|
header = copy.copy(self.header)
|
||||||
|
header['X-Auth-Token'] = 'invalid'
|
||||||
|
|
||||||
|
result = self.client.put(self.url, headers=header)
|
||||||
|
self.assertEqual(result.status_code, 401)
|
||||||
|
|
||||||
|
test_insert_queue_invalid_authtoken.tags = ['negative']
|
||||||
|
|
||||||
|
def test_insert_queue_header_plaintext(self):
|
||||||
|
"""Insert Queue with 'Accept': 'plain/text'."""
|
||||||
|
path = '/queues/plaintextheader'
|
||||||
|
self.addCleanup(self.client.delete, path)
|
||||||
|
|
||||||
|
header = {"Accept": 'plain/text'}
|
||||||
|
result = self.client.put(path, headers=header)
|
||||||
|
self.assertEqual(result.status_code, 406)
|
||||||
|
|
||||||
|
test_insert_queue_header_plaintext.tags = ['negative']
|
||||||
|
|
||||||
|
def test_insert_queue_header_asterisk(self):
|
||||||
|
"""Insert Queue with 'Accept': '*/*'."""
|
||||||
|
path = '/queues/asteriskinheader'
|
||||||
|
headers = {"Accept": '*/*'}
|
||||||
|
self.addCleanup(self.client.delete, url=path, headers=headers)
|
||||||
|
|
||||||
|
result = self.client.put(path, headers=headers)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
test_insert_queue_header_asterisk.tags = ['positive']
|
||||||
|
|
||||||
|
def test_insert_queue_with_metadata(self):
|
||||||
|
"""Insert queue with a non-empty request body."""
|
||||||
|
self.url = self.base_url + '/queues/hasmetadata'
|
||||||
|
doc = {"queue": "Has Metadata"}
|
||||||
|
self.addCleanup(self.client.delete, self.url)
|
||||||
|
result = self.client.put(self.url, data=doc)
|
||||||
|
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
self.url = self.base_url + '/queues/hasmetadata/metadata'
|
||||||
|
result = self.client.get(self.url)
|
||||||
|
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertEqual(result.json(), {})
|
||||||
|
|
||||||
|
test_insert_queue_with_metadata.tags = ['negative']
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestInsertQueue, self).tearDown()
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class TestQueueMisc(base.V1_1FunctionalTestBase):
|
||||||
|
|
||||||
|
server_class = base.MarconiServer
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestQueueMisc, self).setUp()
|
||||||
|
self.base_url = self.cfg.marconi.url
|
||||||
|
self.client.set_base_url(self.base_url)
|
||||||
|
|
||||||
|
self.queue_url = self.base_url + ('/{0}/queues/{1}'
|
||||||
|
.format("v1.1", uuid.uuid1()))
|
||||||
|
|
||||||
|
def test_list_queues(self):
|
||||||
|
"""List Queues."""
|
||||||
|
|
||||||
|
self.client.put(self.queue_url)
|
||||||
|
self.addCleanup(self.client.delete, self.queue_url)
|
||||||
|
|
||||||
|
result = self.client.get('/{0}/queues'
|
||||||
|
.format("v1.1"))
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertSchema(result.json(), 'queue_list')
|
||||||
|
|
||||||
|
test_list_queues.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
def test_list_queues_detailed(self):
|
||||||
|
"""List Queues with detailed = True."""
|
||||||
|
|
||||||
|
self.client.put(self.queue_url)
|
||||||
|
self.addCleanup(self.client.delete, self.queue_url)
|
||||||
|
|
||||||
|
params = {'detailed': True}
|
||||||
|
result = self.client.get('/{0}/queues'
|
||||||
|
.format("v1.1"),
|
||||||
|
params=params)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertSchema(result.json(), 'queue_list')
|
||||||
|
|
||||||
|
response_keys = result.json()['queues'][0].keys()
|
||||||
|
self.assertIn('metadata', response_keys)
|
||||||
|
|
||||||
|
test_list_queues_detailed.tags = ['smoke', 'positive']
|
||||||
|
|
||||||
|
@ddt.data(0, -1, 1001)
|
||||||
|
def test_list_queue_invalid_limit(self, limit):
|
||||||
|
"""List Queues with a limit value that is not allowed."""
|
||||||
|
|
||||||
|
params = {'limit': limit}
|
||||||
|
result = self.client.get('/{0}/queues'
|
||||||
|
.format("v1.1"),
|
||||||
|
params=params)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
test_list_queue_invalid_limit.tags = ['negative']
|
||||||
|
|
||||||
|
def test_check_health(self):
|
||||||
|
"""Test health endpoint."""
|
||||||
|
|
||||||
|
result = self.client.get('/{0}/health'
|
||||||
|
.format("v1.1"))
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_check_health.tags = ['positive']
|
||||||
|
|
||||||
|
def test_check_queue_exists(self):
|
||||||
|
"""Checks if queue exists."""
|
||||||
|
|
||||||
|
self.client.put(self.queue_url)
|
||||||
|
self.addCleanup(self.client.delete, self.queue_url)
|
||||||
|
result = self.client.get(self.queue_url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
result = self.client.head(self.queue_url)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_check_queue_exists.tags = ['positive']
|
||||||
|
|
||||||
|
def test_check_queue_exists_negative(self):
|
||||||
|
"""Checks non-existing queue."""
|
||||||
|
path = '/{0}/queues/nonexistingqueue'.format("v1.1")
|
||||||
|
result = self.client.get(path)
|
||||||
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
|
result = self.client.head(path)
|
||||||
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
|
test_check_queue_exists_negative.tags = ['negative']
|
||||||
|
|
||||||
|
def test_get_queue_malformed_marker(self):
|
||||||
|
"""List queues with invalid marker."""
|
||||||
|
|
||||||
|
path = '/{0}/queues?marker=zzz'.format("v1.1")
|
||||||
|
result = self.client.get(path)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
test_get_queue_malformed_marker.tags = ['negative']
|
||||||
|
|
||||||
|
def test_get_stats_empty_queue(self):
|
||||||
|
"""Get queue stats on an empty queue."""
|
||||||
|
|
||||||
|
result = self.client.put(self.queue_url)
|
||||||
|
self.addCleanup(self.client.delete, self.queue_url)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
stats_url = self.queue_url + '/stats'
|
||||||
|
|
||||||
|
# Get stats on an empty queue
|
||||||
|
result = self.client.get(stats_url)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
expected_response = {'messages':
|
||||||
|
{'claimed': 0, 'total': 0, 'free': 0}}
|
||||||
|
self.assertEqual(result.json(), expected_response)
|
||||||
|
|
||||||
|
test_get_stats_empty_queue.tags = ['positive']
|
||||||
|
|
||||||
|
@ddt.data(0, 1)
|
||||||
|
def test_get_queue_stats_claimed(self, claimed):
|
||||||
|
"""Get stats on a queue."""
|
||||||
|
result = self.client.put(self.queue_url)
|
||||||
|
self.addCleanup(self.client.delete, self.queue_url)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Post Messages to the test queue
|
||||||
|
doc = helpers.create_message_body(
|
||||||
|
messagecount=self.limits.max_messages_per_claim)
|
||||||
|
|
||||||
|
message_url = self.queue_url + '/messages'
|
||||||
|
result = self.client.post(message_url, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
if claimed > 0:
|
||||||
|
claim_url = self.queue_url + '/claims?limit=' + str(claimed)
|
||||||
|
doc = {'ttl': 300, 'grace': 300}
|
||||||
|
result = self.client.post(claim_url, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Get stats on the queue.
|
||||||
|
stats_url = self.queue_url + '/stats'
|
||||||
|
result = self.client.get(stats_url)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
self.assertQueueStats(result.json(), claimed)
|
||||||
|
|
||||||
|
test_get_queue_stats_claimed.tags = ['positive']
|
||||||
|
|
||||||
|
def test_ping_queue(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestQueueMisc, self).tearDown()
|
||||||
|
|
||||||
|
|
||||||
|
class TestQueueNonExisting(base.V1_1FunctionalTestBase):
|
||||||
|
|
||||||
|
"""Test Actions on non existing queue."""
|
||||||
|
|
||||||
|
server_class = base.MarconiServer
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestQueueNonExisting, self).setUp()
|
||||||
|
if self.cfg.version != "v1":
|
||||||
|
self.skipTest("Not Supported")
|
||||||
|
|
||||||
|
self.base_url = '{0}/{1}'.format(self.cfg.marconi.url,
|
||||||
|
"v1.1")
|
||||||
|
self.queue_url = (self.base_url +
|
||||||
|
'/queues/0a5b1b85-4263-11e3-b034-28cfe91478b9')
|
||||||
|
self.client.set_base_url(self.queue_url)
|
||||||
|
|
||||||
|
self.header = helpers.create_marconi_headers(self.cfg)
|
||||||
|
self.headers_response_empty = set(['location'])
|
||||||
|
self.header = helpers.create_marconi_headers(self.cfg)
|
||||||
|
|
||||||
|
def test_get_queue(self):
|
||||||
|
"""Get non existing Queue."""
|
||||||
|
result = self.client.get()
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertEqual(result.json(), [])
|
||||||
|
|
||||||
|
def test_get_stats(self):
|
||||||
|
"""Get stats on non existing Queue."""
|
||||||
|
result = self.client.get('/stats')
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertEqual(result.json(), [])
|
||||||
|
|
||||||
|
def test_get_metadata(self):
|
||||||
|
"""Get metadata on non existing Queue."""
|
||||||
|
result = self.client.get('/metadata')
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertEqual(result.json(), [])
|
||||||
|
|
||||||
|
def test_get_messages(self):
|
||||||
|
"""Get messages on non existing Queue."""
|
||||||
|
result = self.client.get('/messages')
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertEqual(result.json(), [])
|
||||||
|
|
||||||
|
def test_post_messages(self):
|
||||||
|
"""Post messages to a non existing Queue."""
|
||||||
|
doc = [{"ttl": 200, "body": {"Home": ""}}]
|
||||||
|
result = self.client.post('/messages', data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# check existence of queue
|
||||||
|
result = self.client.get()
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertNotEqual(result.json(), [])
|
||||||
|
|
||||||
|
def test_claim_messages(self):
|
||||||
|
"""Claim messages from a non existing Queue."""
|
||||||
|
doc = {"ttl": 200, "grace": 300}
|
||||||
|
result = self.client.post('/claims', data=doc)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertEqual(result.json(), [])
|
||||||
|
|
||||||
|
def test_delete_queue(self):
|
||||||
|
"""Delete non existing Queue."""
|
||||||
|
result = self.client.delete()
|
||||||
|
self.assertEqual(result.status_code, 204)
|
242
tests/functional/wsgi/v1_1/test_shards.py
Normal file
242
tests/functional/wsgi/v1_1/test_shards.py
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
# 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.
|
||||||
|
import ddt
|
||||||
|
|
||||||
|
from marconi.tests.functional import base
|
||||||
|
from marconi.tests.functional import helpers
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class TestShards(base.V1_1FunctionalTestBase):
|
||||||
|
|
||||||
|
server_class = base.MarconiServer
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestShards, self).setUp()
|
||||||
|
|
||||||
|
self.shard_url = ("{url}/{version}/shards".format(
|
||||||
|
url=self.cfg.marconi.url,
|
||||||
|
version="v1.1"
|
||||||
|
))
|
||||||
|
self.cfg.marconi.version = "v1.1"
|
||||||
|
|
||||||
|
self.skipTest("NOT IMPLEMENTED")
|
||||||
|
|
||||||
|
self.headers = helpers.create_marconi_headers(self.cfg)
|
||||||
|
self.client.headers = self.headers
|
||||||
|
|
||||||
|
self.client.set_base_url(self.shard_url)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestShards, self).tearDown()
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{
|
||||||
|
'name': "newshard",
|
||||||
|
'weight': 10,
|
||||||
|
'uri': "mongodb://127.0.0.1:27017"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_insert_shard(self, params):
|
||||||
|
"""Test the registering of one shard."""
|
||||||
|
doc = helpers.create_shard_body(
|
||||||
|
weight=params.get('weight', 10),
|
||||||
|
uri=params.get('uri', "mongodb://127.0.0.1:27017")
|
||||||
|
)
|
||||||
|
|
||||||
|
shard_name = params.get('name', "newshard")
|
||||||
|
self.addCleanup(self.client.delete, url='/'+shard_name)
|
||||||
|
|
||||||
|
result = self.client.put('/'+shard_name, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Test existence
|
||||||
|
result = self.client.get('/'+shard_name)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{
|
||||||
|
'name': "newshard",
|
||||||
|
'weight': 10,
|
||||||
|
'uri': "mongodb://127.0.0.1:27017"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_shard_details(self, params):
|
||||||
|
"""Get the details of a shard. Assert the respective schema."""
|
||||||
|
doc = helpers.create_shard_body(
|
||||||
|
weight=params.get('weight', 10),
|
||||||
|
uri=params.get('uri', "mongodb://127.0.0.1:27017")
|
||||||
|
)
|
||||||
|
|
||||||
|
shard_name = params.get('name', "newshard")
|
||||||
|
self.addCleanup(self.client.delete, url='/'+shard_name)
|
||||||
|
result = self.client.put('/'+shard_name, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Test existence
|
||||||
|
result = self.client.get('/'+shard_name+'?detailed=true')
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertSchema(result.json(), 'shard-detail')
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{
|
||||||
|
'name': "newshard",
|
||||||
|
'weight': 10,
|
||||||
|
'uri': "mongodb://127.0.0.1:27017"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_delete_shard(self, params):
|
||||||
|
"""Create a shard, then delete it.
|
||||||
|
|
||||||
|
Make sure operation is successful.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Create the shard
|
||||||
|
doc = helpers.create_shard_body(
|
||||||
|
weight=params.get('weight', 10),
|
||||||
|
uri=params.get('uri', "mongodb://127.0.0.1:27017")
|
||||||
|
)
|
||||||
|
|
||||||
|
shard_name = params.get('name', "newshard")
|
||||||
|
result = self.client.put('/'+shard_name, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Make sure it exists
|
||||||
|
result = self.client.get('/'+shard_name)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
# Delete it
|
||||||
|
result = self.client.delete('/'+shard_name)
|
||||||
|
self.assertEqual(result.status_code, 204)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{
|
||||||
|
'name': "newshard",
|
||||||
|
'weight': 10,
|
||||||
|
'uri': "mongodb://127.0.0.1:27017"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_list_shards(self, params):
|
||||||
|
"""Add a shard. Get the list of all the shards.
|
||||||
|
|
||||||
|
Assert respective schema
|
||||||
|
"""
|
||||||
|
doc = helpers.create_shard_body(
|
||||||
|
weight=params.get('weight', 10),
|
||||||
|
uri=params.get('uri', "mongodb://127.0.0.1:27017")
|
||||||
|
)
|
||||||
|
shard_name = params.get('name', "newshard")
|
||||||
|
self.addCleanup(self.client.delete, url='/'+shard_name)
|
||||||
|
result = self.client.put('/'+shard_name, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
result = self.client.get()
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertSchema(result.json(), 'shard-list')
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{
|
||||||
|
'name': "newshard",
|
||||||
|
'weight': 10,
|
||||||
|
'uri': "mongodb://127.0.0.1:27017"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_patch_shard(self, params):
|
||||||
|
"""Create a shard. Issue a patch command,
|
||||||
|
|
||||||
|
make sure command was successful. Check details to be sure.
|
||||||
|
"""
|
||||||
|
|
||||||
|
doc = helpers.create_shard_body(
|
||||||
|
weight=params.get('weight', 10),
|
||||||
|
uri=params.get('uri', "mongodb://127.0.0.1:27017")
|
||||||
|
)
|
||||||
|
shard_name = params.get('name', "newshard")
|
||||||
|
self.addCleanup(self.client.delete, url='/'+shard_name)
|
||||||
|
result = self.client.put('/'+shard_name, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
# Update that shard
|
||||||
|
|
||||||
|
patchdoc = helpers.create_shard_body(
|
||||||
|
weight=5,
|
||||||
|
uri="mongodb://127.0.0.1:27017"
|
||||||
|
)
|
||||||
|
result = self.client.patch('/'+shard_name, data=patchdoc)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
|
||||||
|
# Get the shard, check update#
|
||||||
|
result = self.client.get('/'+shard_name)
|
||||||
|
self.assertEqual(result.status_code, 200)
|
||||||
|
self.assertEqual(result.json()["weight"], 5)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{
|
||||||
|
'name': "newshard",
|
||||||
|
'weight': 10,
|
||||||
|
'uri': "mongodb://127.0.0.1:27017"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_patch_shard_bad_data(self, params):
|
||||||
|
"""Issue a patch command without a body. Assert 400."""
|
||||||
|
# create a shard
|
||||||
|
doc = helpers.create_shard_body(
|
||||||
|
weight=params.get('weight', 10),
|
||||||
|
uri=params.get('uri', "mongodb://127.0.0.1:27017")
|
||||||
|
)
|
||||||
|
shard_name = params.get('name', "newshard")
|
||||||
|
self.addCleanup(self.client.delete, url='/'+shard_name)
|
||||||
|
result = self.client.put('/'+shard_name, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 201)
|
||||||
|
|
||||||
|
# Update shard with bad post data. Ensure 400
|
||||||
|
result = self.client.patch('/'+shard_name)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{
|
||||||
|
'name': "newshard",
|
||||||
|
'weight': 10,
|
||||||
|
'uri': "mongodb://127.0.0.1:27017"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_patch_shard_non_exist(self, params):
|
||||||
|
"""Issue patch command to shard that doesn't exist. Assert 404."""
|
||||||
|
doc = helpers.create_shard_body(
|
||||||
|
weight=5,
|
||||||
|
uri=params.get('uri', "mongodb://127.0.0.1:27018")
|
||||||
|
)
|
||||||
|
result = self.client.patch('/nonexistshard', data=doc)
|
||||||
|
self.assertEqual(result.status_code, 404)
|
||||||
|
|
||||||
|
@ddt.data(
|
||||||
|
{'name': u'\u6c49\u5b57\u6f22\u5b57'},
|
||||||
|
{'name': 'i'*65},
|
||||||
|
{'weight': -1}
|
||||||
|
)
|
||||||
|
def test_insert_shard_bad_data(self, params):
|
||||||
|
"""Create shards with invalid names and weights. Assert 400."""
|
||||||
|
doc = helpers.create_shard_body(
|
||||||
|
weight=params.get('weight', 10),
|
||||||
|
uri=params.get('uri', "mongodb://127.0.0.1:27017")
|
||||||
|
)
|
||||||
|
shard_name = params.get('name', "newshard")
|
||||||
|
self.addCleanup(self.client.delete, url='/'+shard_name)
|
||||||
|
result = self.client.put('/'+shard_name, data=doc)
|
||||||
|
self.assertEqual(result.status_code, 400)
|
||||||
|
|
||||||
|
def test_delete_shard_non_exist(self):
|
||||||
|
"""Delete a shard that doesn't exist. Assert 404."""
|
||||||
|
result = self.client.delete('/nonexistshard')
|
||||||
|
self.assertEqual(result.status_code, 204)
|
Loading…
x
Reference in New Issue
Block a user