diff --git a/marconi/queues/api/v1/response.py b/marconi/queues/api/v1/response.py new file mode 100644 index 000000000..344153b74 --- /dev/null +++ b/marconi/queues/api/v1/response.py @@ -0,0 +1,55 @@ +# 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 + self.schema = { + 'message_get_many': + { + "type": "array", + "items": { + "type": "object", + "properties": { + "href": { + "type": "string", + "pattern": "^(/v1/queues/[a-zA-Z0-9_-]{1,64}" + "/messages/[a-zA-Z0-9_-]+)$" + }, + "ttl": { + "type": "number", + "minimum": 1, + "maximum": self.limits.message_ttl_max + }, + "age": { + "type": "number", + "minimum": 0 + }, + "body": { + "type": "object" + } + }, + "required": ["href", "ttl", "age", "body"] + }, + "minItems": 1, + "maxItems": self.limits.message_paging_uplimit + } + } diff --git a/marconi/tests/functional/base.py b/marconi/tests/functional/base.py index 6df738b04..2b7a8e7a6 100644 --- a/marconi/tests/functional/base.py +++ b/marconi/tests/functional/base.py @@ -15,6 +15,7 @@ # limitations under the License. import abc +import jsonschema import multiprocessing @@ -99,6 +100,19 @@ class FunctionalTestBase(testing.TestBase): ', actual count = {1}'.format(expectedCount, actualCount) self.assertTrue(actualCount <= expectedCount, msg) + def assertSchema(self, response, expectedSchema): + """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: dict + """ + try: + jsonschema.validate(response, expectedSchema) + except jsonschema.ValidationError as message: + assert False, message + def assertQueueStats(self, result_json, claimed): """Checks the Queue Stats results diff --git a/tests/functional/wsgi/v1/test_messages.py b/tests/functional/wsgi/v1/test_messages.py index cf30f1566..1ca6ae6c2 100644 --- a/tests/functional/wsgi/v1/test_messages.py +++ b/tests/functional/wsgi/v1/test_messages.py @@ -17,12 +17,14 @@ import uuid import ddt -from marconi.tests.functional import base # noqa +from marconi.queues.api.v1 import response +from marconi.tests.functional import base from marconi.tests.functional import helpers @ddt.ddt class TestMessages(base.FunctionalTestBase): + """Tests for Messages.""" server_class = base.MarconiServer @@ -41,6 +43,8 @@ class TestMessages(base.FunctionalTestBase): self.message_url = self.queue_url + '/messages' self.client.set_base_url(self.message_url) + self.response = response.ResponseSchema(self.limits) + def test_message_single_insert(self): """Insert Single Message into the Queue. @@ -101,6 +105,10 @@ class TestMessages(base.FunctionalTestBase): result = self.client.get(url) self.assertEqual(result.status_code, 200) + # Verify that the response json schema matches the expected schema + expected_schema = self.response.get_schema('message_get_many') + self.assertSchema(result.json(), expected_schema) + # Compare message metadata result_body = [result.json()[i]['body'] for i in range(len(result.json()))] @@ -129,7 +137,8 @@ class TestMessages(base.FunctionalTestBase): url = '' params['echo'] = True - #Follow the hrefs & perform GET, till the end of messages i.e. http 204 + # 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])