diff --git a/zaqar/tests/unit/transport/wsgi/__init__.py b/zaqar/tests/unit/transport/wsgi/__init__.py index 55ac71550..075f95072 100644 --- a/zaqar/tests/unit/transport/wsgi/__init__.py +++ b/zaqar/tests/unit/transport/wsgi/__init__.py @@ -19,4 +19,3 @@ from zaqar.tests.unit.transport.wsgi import base TestBase = base.TestBase TestBaseFaulty = base.TestBaseFaulty -V1_1Base = base.V1_1Base diff --git a/zaqar/tests/unit/transport/wsgi/base.py b/zaqar/tests/unit/transport/wsgi/base.py index c8e4996eb..629f41371 100644 --- a/zaqar/tests/unit/transport/wsgi/base.py +++ b/zaqar/tests/unit/transport/wsgi/base.py @@ -136,34 +136,18 @@ class TestBaseFaulty(TestBase): """This test ensures we aren't letting any exceptions go unhandled.""" -class V1_1Base(TestBase): - """Base class for V1.1 API Tests. - - Should contain methods specific to V1.1 of the API - """ - url_prefix = '/v1.1' - - def _empty_message_list(self, body): - self.assertEqual([], jsonutils.loads(body[0])['messages']) - - -class V1_1BaseFaulty(TestBaseFaulty): - """Base class for V1.1 API Faulty Tests. - - Should contain methods specific to V1.1 exception testing - """ - url_prefix = '/v1.1' - - -class V2Base(V1_1Base): +class V2Base(TestBase): """Base class for V2 API Tests. Should contain methods specific to V2 of the API """ url_prefix = '/v2' + def _empty_message_list(self, body): + self.assertEqual([], jsonutils.loads(body[0])['messages']) -class V2BaseFaulty(V1_1BaseFaulty): + +class V2BaseFaulty(TestBaseFaulty): """Base class for V2 API Faulty Tests. Should contain methods specific to V2 exception testing diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/__init__.py b/zaqar/tests/unit/transport/wsgi/v1_1/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_auth.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_auth.py deleted file mode 100644 index cf844e0af..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_auth.py +++ /dev/null @@ -1,43 +0,0 @@ -# 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. -"""Test Auth.""" - - -import falcon -from falcon import testing -from keystonemiddleware import auth_token -from oslo_utils import uuidutils - -from zaqar.tests.unit.transport.wsgi import base - - -class TestAuth(base.V1_1Base): - - config_file = 'keystone_auth.conf' - - def setUp(self): - super(TestAuth, self).setUp() - self.headers = {'Client-ID': uuidutils.generate_uuid()} - - def test_auth_install(self): - self.assertIsInstance(self.app._auth_app, auth_token.AuthProtocol) - - def test_non_authenticated(self): - env = testing.create_environ(self.url_prefix + '/480924/queues/', - method='GET', - headers=self.headers) - - self.app(env, self.srmock) - self.assertEqual(falcon.HTTP_401, self.srmock.status) diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_claims.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_claims.py deleted file mode 100644 index b763a26e8..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_claims.py +++ /dev/null @@ -1,314 +0,0 @@ -# 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. - -import datetime -from unittest import mock - -import ddt -import falcon -from oslo_serialization import jsonutils -from oslo_utils import timeutils -from oslo_utils import uuidutils -from testtools import matchers - -from zaqar import tests as testing -from zaqar.tests.unit.transport.wsgi import base - - -@ddt.ddt -class TestClaimsMongoDB(base.V1_1Base): - - config_file = 'wsgi_mongodb.conf' - - @testing.requires_mongodb - def setUp(self): - super(TestClaimsMongoDB, self).setUp() - - self.default_claim_ttl = self.boot.transport._defaults.claim_ttl - self.project_id = '737_abc8332832' - self.headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': self.project_id - } - self.queue_path = self.url_prefix + '/queues/fizbit' - self.claims_path = self.queue_path + '/claims' - self.messages_path = self.queue_path + '/messages' - - doc = jsonutils.dumps({"_ttl": 60}) - - self.simulate_put(self.queue_path, body=doc, headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - doc = jsonutils.dumps({'messages': [{'body': 239, 'ttl': 300}] * 10}) - self.simulate_post(self.queue_path + '/messages', - body=doc, headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - def tearDown(self): - storage = self.boot.storage._storage - control = self.boot.control - connection = storage.connection - - connection.drop_database(control.queues_database) - - for db in storage.message_databases: - connection.drop_database(db) - self.simulate_delete(self.queue_path, headers=self.headers) - - super(TestClaimsMongoDB, self).tearDown() - - @ddt.data('[', '[]', '.', '"fail"') - def test_bad_claim(self, doc): - self.simulate_post(self.claims_path, body=doc, headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - href = self._get_a_claim() - - self.simulate_patch(href, body=doc, headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_exceeded_claim(self): - self.simulate_post(self.claims_path, - body='{"ttl": 100, "grace": 60}', - query_string='limit=21', headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - @ddt.data((-1, -1), (59, 60), (60, 59), (60, 43201), (43201, 60)) - def test_unacceptable_ttl_or_grace(self, ttl_grace): - ttl, grace = ttl_grace - self.simulate_post(self.claims_path, - body=jsonutils.dumps({'ttl': ttl, 'grace': grace}), - headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - @ddt.data(-1, 59, 43201) - def test_unacceptable_new_ttl(self, ttl): - href = self._get_a_claim() - - self.simulate_patch(href, - body=jsonutils.dumps({'ttl': ttl}), - headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_default_ttl_and_grace(self): - self.simulate_post(self.claims_path, - body='{}', headers=self.headers) - - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - body = self.simulate_get(self.srmock.headers_dict['location'], - headers=self.headers) - - claim = jsonutils.loads(body[0]) - self.assertEqual(self.default_claim_ttl, claim['ttl']) - - def _get_a_claim(self): - doc = '{"ttl": 100, "grace": 60}' - self.simulate_post(self.claims_path, body=doc, headers=self.headers) - return self.srmock.headers_dict['Location'] - - def test_lifecycle(self): - doc = '{"ttl": 100, "grace": 60}' - - # First, claim some messages - body = self.simulate_post(self.claims_path, body=doc, - headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - claimed = jsonutils.loads(body[0])['messages'] - claim_href = self.srmock.headers_dict['Location'] - message_href, params = claimed[0]['href'].split('?') - - # No more messages to claim - self.simulate_post(self.claims_path, body=doc, - query_string='limit=3', headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # Listing messages, by default, won't include claimed, will echo - body = self.simulate_get(self.messages_path, - headers=self.headers, - query_string="echo=true") - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self._empty_message_list(body) - - # Listing messages, by default, won't include claimed, won't echo - body = self.simulate_get(self.messages_path, - headers=self.headers, - query_string="echo=false") - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self._empty_message_list(body) - - # List messages, include_claimed, but don't echo - body = self.simulate_get(self.messages_path, - query_string='include_claimed=true' - '&echo=false', - headers=self.headers) - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self._empty_message_list(body) - - # List messages with a different client-id and echo=false. - # Should return some messages - headers = self.headers.copy() - headers["Client-ID"] = uuidutils.generate_uuid() - body = self.simulate_get(self.messages_path, - query_string='include_claimed=true' - '&echo=false', - headers=headers) - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # Include claimed messages this time, and echo - body = self.simulate_get(self.messages_path, - query_string='include_claimed=true' - '&echo=true', - headers=self.headers) - listed = jsonutils.loads(body[0]) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self.assertEqual(len(claimed), len(listed['messages'])) - - now = timeutils.utcnow() + datetime.timedelta(seconds=10) - timeutils_utcnow = 'oslo_utils.timeutils.utcnow' - with mock.patch(timeutils_utcnow) as mock_utcnow: - mock_utcnow.return_value = now - body = self.simulate_get(claim_href, headers=self.headers) - - claim = jsonutils.loads(body[0]) - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self.assertEqual(100, claim['ttl']) - # NOTE(cpp-cabrera): verify that claim age is non-negative - self.assertThat(claim['age'], matchers.GreaterThan(-1)) - - # Try to delete the message without submitting a claim_id - self.simulate_delete(message_href, headers=self.headers) - self.assertEqual(falcon.HTTP_403, self.srmock.status) - - # Delete the message and its associated claim - self.simulate_delete(message_href, - query_string=params, headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # Try to get it from the wrong project - headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': 'bogusproject' - } - self.simulate_get(message_href, query_string=params, headers=headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - # Get the message - self.simulate_get(message_href, query_string=params, - headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - # Update the claim - new_claim_ttl = '{"ttl": 60, "grace": 60}' - creation = timeutils.utcnow() - self.simulate_patch(claim_href, body=new_claim_ttl, - headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # Get the claimed messages (again) - body = self.simulate_get(claim_href, headers=self.headers) - query = timeutils.utcnow() - claim = jsonutils.loads(body[0]) - message_href, params = claim['messages'][0]['href'].split('?') - - self.assertEqual(60, claim['ttl']) - estimated_age = timeutils.delta_seconds(creation, query) - self.assertGreater(estimated_age, claim['age']) - - # Delete the claim - self.simulate_delete(claim['href'], headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # Try to delete a message with an invalid claim ID - self.simulate_delete(message_href, - query_string=params, headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - # Make sure it wasn't deleted! - self.simulate_get(message_href, query_string=params, - headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # Try to get a claim that doesn't exist - self.simulate_get(claim['href'], headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - # Try to update a claim that doesn't exist - self.simulate_patch(claim['href'], body=doc, - headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - def test_post_claim_nonexistent_queue(self): - path = self.url_prefix + '/queues/nonexistent/claims' - self.simulate_post(path, - body='{"ttl": 100, "grace": 60}', - headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - def test_get_claim_nonexistent_queue(self): - path = self.url_prefix + '/queues/nonexistent/claims/aaabbbba' - self.simulate_get(path, headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - # NOTE(cpp-cabrera): regression test against bug #1203842 - def test_get_nonexistent_claim_404s(self): - self.simulate_get(self.claims_path + '/a', headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - def test_delete_nonexistent_claim_204s(self): - self.simulate_delete(self.claims_path + '/a', - headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - def test_patch_nonexistent_claim_404s(self): - patch_data = jsonutils.dumps({'ttl': 100}) - self.simulate_patch(self.claims_path + '/a', body=patch_data, - headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - -class TestClaimsFaultyDriver(base.V1_1BaseFaulty): - - config_file = 'wsgi_faulty.conf' - - def test_simple(self): - self.project_id = '480924abc_' - self.headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': self.project_id - } - - claims_path = self.url_prefix + '/queues/fizbit/claims' - doc = '{"ttl": 100, "grace": 60}' - - self.simulate_post(claims_path, body=doc, headers=self.headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - self.simulate_get(claims_path + '/nichts', headers=self.headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - self.simulate_patch(claims_path + '/nichts', body=doc, - headers=self.headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - self.simulate_delete(claims_path + '/foo', headers=self.headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_default_limits.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_default_limits.py deleted file mode 100644 index 5d1b39c19..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_default_limits.py +++ /dev/null @@ -1,124 +0,0 @@ -# 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. - -import contextlib - -import falcon -from oslo_serialization import jsonutils -from oslo_utils import uuidutils - -from zaqar import storage -from zaqar.tests.unit.transport.wsgi import base - - -class TestDefaultLimits(base.V1_1Base): - - config_file = 'wsgi_mongodb_default_limits.conf' - - def setUp(self): - super(TestDefaultLimits, self).setUp() - - self.headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': '%s_' % uuidutils.generate_uuid() - } - self.queue_path = self.url_prefix + '/queues' - self.q1_queue_path = self.queue_path + '/' + uuidutils.generate_uuid() - self.messages_path = self.q1_queue_path + '/messages' - self.claims_path = self.q1_queue_path + '/claims' - - self.simulate_put(self.q1_queue_path, headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - def tearDown(self): - self.simulate_delete(self.queue_path, headers=self.headers) - super(TestDefaultLimits, self).tearDown() - - def test_queue_listing(self): - # 2 queues to list - self.simulate_put(self.queue_path + '/q2', headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - with self._prepare_queues(storage.DEFAULT_QUEUES_PER_PAGE + 1): - result = self.simulate_get(self.queue_path, headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - queues = jsonutils.loads(result[0])['queues'] - self.assertEqual(storage.DEFAULT_QUEUES_PER_PAGE, len(queues)) - - def test_message_listing_different_id(self): - self._prepare_messages(storage.DEFAULT_MESSAGES_PER_PAGE + 1) - - headers = self.headers.copy() - headers['Client-ID'] = uuidutils.generate_uuid() - result = self.simulate_get(self.messages_path, - headers=headers, - query_string='echo=false') - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - messages = jsonutils.loads(result[0])['messages'] - self.assertEqual(storage.DEFAULT_MESSAGES_PER_PAGE, len(messages)) - - def test_message_listing_same_id(self): - self._prepare_messages(storage.DEFAULT_MESSAGES_PER_PAGE + 1) - result = self.simulate_get(self.messages_path, - headers=self.headers, - query_string='echo=false') - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self._empty_message_list(result) - - self._prepare_messages(storage.DEFAULT_MESSAGES_PER_PAGE + 1) - result = self.simulate_get(self.messages_path, - headers=self.headers, - query_string='echo=true') - - messages = jsonutils.loads(result[0])['messages'] - self.assertEqual(storage.DEFAULT_MESSAGES_PER_PAGE, len(messages)) - - def test_claim_creation(self): - self._prepare_messages(storage.DEFAULT_MESSAGES_PER_CLAIM + 1) - - result = self.simulate_post(self.claims_path, - body='{"ttl": 60, "grace": 60}', - headers=self.headers) - - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - messages = jsonutils.loads(result[0])['messages'] - self.assertEqual(storage.DEFAULT_MESSAGES_PER_CLAIM, len(messages)) - - @contextlib.contextmanager - def _prepare_queues(self, count): - queue_paths = [self.queue_path + '/multi-{0}'.format(i) - for i in range(count)] - - for path in queue_paths: - self.simulate_put(path, headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - yield - - for path in queue_paths: - self.simulate_delete(path, headers=self.headers) - - def _prepare_messages(self, count): - doc = {'messages': [{'body': 239, 'ttl': 300}] * count} - body = jsonutils.dumps(doc) - self.simulate_post(self.messages_path, body=body, - headers=self.headers) - - self.assertEqual(falcon.HTTP_201, self.srmock.status) diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_health.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_health.py deleted file mode 100644 index 8c562d03c..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_health.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2014 Catalyst IT Ltd -# -# 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 unittest import mock - -import ddt -import falcon -from oslo_serialization import jsonutils - -from zaqar.storage import errors -import zaqar.storage.mongodb as mongo -from zaqar import tests as testing -from zaqar.tests.unit.transport.wsgi import base - - -@ddt.ddt -class TestHealthMongoDB(base.V1_1Base): - - config_file = 'wsgi_mongodb.conf' - - @testing.requires_mongodb - def setUp(self): - super(TestHealthMongoDB, self).setUp() - - def test_basic(self): - path = self.url_prefix + '/health' - body = self.simulate_get(path) - health = jsonutils.loads(body[0]) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self.assertTrue(health['storage_reachable']) - self.assertIsNotNone(health['message_volume']) - for op in health['operation_status']: - self.assertTrue(health['operation_status'][op]['succeeded']) - - @mock.patch.object(mongo.driver.DataDriver, '_health') - def test_message_volume(self, mock_driver_get): - def _health(): - KPI = {} - KPI['message_volume'] = {'free': 1, 'claimed': 2, 'total': 3} - return KPI - - mock_driver_get.side_effect = _health - - path = self.url_prefix + '/health' - body = self.simulate_get(path) - health = jsonutils.loads(body[0]) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - message_volume = health['message_volume'] - self.assertEqual(1, message_volume['free']) - self.assertEqual(2, message_volume['claimed']) - self.assertEqual(3, message_volume['total']) - - @mock.patch.object(mongo.messages.MessageController, 'delete') - def test_operation_status(self, mock_messages_delete): - mock_messages_delete.side_effect = errors.NotPermitted() - - path = self.url_prefix + '/health' - body = self.simulate_get(path) - health = jsonutils.loads(body[0]) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - op_status = health['operation_status'] - for op in op_status.keys(): - if op == 'delete_messages': - self.assertFalse(op_status[op]['succeeded']) - self.assertIsNotNone(op_status[op]['ref']) - else: - self.assertTrue(op_status[op]['succeeded']) - - -class TestHealthFaultyDriver(base.V1_1BaseFaulty): - - config_file = 'wsgi_faulty.conf' - - def test_simple(self): - path = self.url_prefix + '/health' - self.simulate_get(path) - self.assertEqual(falcon.HTTP_503, self.srmock.status) diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_home.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_home.py deleted file mode 100644 index 15c0614cc..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_home.py +++ /dev/null @@ -1,71 +0,0 @@ -# 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. - - -import falcon -from oslo_serialization import jsonutils -from oslo_utils import uuidutils -from urllib import parse as urlparse - -from zaqar.tests.unit.transport.wsgi import base - - -class TestHomeDocument(base.V1_1Base): - - config_file = 'wsgi_mongodb.conf' - - def test_json_response(self): - self.headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': '8383830383abc_' - } - body = self.simulate_get(self.url_prefix + '/', headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - content_type = self.srmock.headers_dict['Content-Type'] - self.assertEqual('application/json-home', content_type) - - try: - jsonutils.loads(body[0]) - except ValueError: - self.fail('Home document is not valid JSON') - - def test_href_template(self): - self.headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': '8383830383' - } - body = self.simulate_get(self.url_prefix + '/', headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - resp = jsonutils.loads(body[0]) - queue_href_template = resp['resources']['rel/queue']['href-template'] - path_1 = 'https://zaqar.example.com' + self.url_prefix - path_2 = 'https://zaqar.example.com' + self.url_prefix + '/' - - # Verify all the href template start with the correct version prefix - def get_href_or_template(resource): - return resource.get('href-template', '') or resource['href'] - - for resource in list(resp['resources']): - self.assertTrue( - get_href_or_template(resp['resources'][resource]). - startswith(self.url_prefix)) - - url = urlparse.urljoin(path_1, queue_href_template) - expected = ('https://zaqar.example.com' + self.url_prefix + - '/queues/foo') - self.assertEqual(expected, url.format(queue_name='foo')) - - url = urlparse.urljoin(path_2, queue_href_template) - self.assertEqual(expected, url.format(queue_name='foo')) diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_media_type.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_media_type.py deleted file mode 100644 index a75855de2..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_media_type.py +++ /dev/null @@ -1,81 +0,0 @@ -# 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. - -import uuid - -import falcon -from falcon import testing -from oslo_serialization import jsonutils - -from zaqar.tests.unit.transport.wsgi import base - - -class TestMediaType(base.V1_1Base): - - config_file = 'wsgi_mongodb.conf' - - def test_json_only_endpoints_with_wrong_accept_header(self): - endpoints = ( - ('GET', self.url_prefix + '/queues'), - ('GET', self.url_prefix + '/queues/nonexistent/stats'), - ('POST', self.url_prefix + '/queues/nonexistent/messages'), - ('GET', self.url_prefix + '/queues/nonexistent/messages/deadbeaf'), - ('POST', self.url_prefix + '/queues/nonexistent/claims'), - ('GET', self.url_prefix + '/queues/nonexistent/claims/0ad'), - ('GET', self.url_prefix + '/health'), - ) - - for method, endpoint in endpoints: - headers = { - 'Client-ID': str(uuid.uuid4()), - 'Accept': 'application/xml', - } - - env = testing.create_environ(endpoint, - method=method, - headers=headers) - - self.app(env, self.srmock) - self.assertEqual(falcon.HTTP_406, self.srmock.status) - - def test_request_with_body_and_urlencoded_contenttype_header_fails(self): - # NOTE(Eva-i): this test case makes sure wsgi 'before' hook - # "require_content_type_be_non_urlencoded" works to prevent - # bug/1547100. - eww_queue_path = self.url_prefix + '/queues/eww' - eww_queue_messages_path = eww_queue_path + '/messages' - sample_message = jsonutils.dumps({'messages': [{'body': {'eww!'}, - 'ttl': 200}]}) - bad_headers = { - 'Client-ID': str(uuid.uuid4()), - 'Content-Type': 'application/x-www-form-urlencoded', - } - - # Create queue request with bad headers. Should still work, because it - # has no body. - self.simulate_put(eww_queue_path, headers=bad_headers) - self.addCleanup(self.simulate_delete, eww_queue_path, - headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - # Post message request with good headers. Should work. - self.simulate_post(eww_queue_messages_path, body=sample_message, - headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - # Post message request with bad headers. Should not work. - self.simulate_post(eww_queue_messages_path, body=sample_message, - headers=bad_headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_messages.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_messages.py deleted file mode 100644 index f975fd5a9..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_messages.py +++ /dev/null @@ -1,639 +0,0 @@ -# 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. - -import datetime -from unittest import mock -import uuid - -import ddt -import falcon -from oslo_serialization import jsonutils -from oslo_utils import timeutils -from testtools import matchers - -from zaqar import tests as testing -from zaqar.tests.unit.transport.wsgi import base -from zaqar.transport import validation - - -@ddt.ddt -class TestMessagesMongoDB(base.V1_1Base): - - config_file = 'wsgi_mongodb.conf' - - @testing.requires_mongodb - def setUp(self): - super(TestMessagesMongoDB, self).setUp() - - self.default_message_ttl = self.boot.transport._defaults.message_ttl - - if self.conf.pooling: - for i in range(4): - uri = "%s/%s" % (self.mongodb_url, str(i)) - doc = {'weight': 100, 'uri': uri} - self.simulate_put(self.url_prefix + '/pools/' + str(i), - body=jsonutils.dumps(doc)) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - self.project_id = '7e55e1a7e' - self.headers = { - 'Client-ID': str(uuid.uuid4()), - 'X-Project-ID': self.project_id - } - - # TODO(kgriffs): Add support in self.simulate_* for a "base path" - # so that we don't have to concatenate against self.url_prefix - # all over the place. - self.queue_path = self.url_prefix + '/queues/fizbit' - self.messages_path = self.queue_path + '/messages' - - doc = '{"_ttl": 60}' - self.simulate_put(self.queue_path, body=doc, headers=self.headers) - - def tearDown(self): - self.simulate_delete(self.queue_path, headers=self.headers) - if self.conf.pooling: - for i in range(4): - self.simulate_delete(self.url_prefix + '/pools/' + str(i), - headers=self.headers) - - super(TestMessagesMongoDB, self).tearDown() - - def test_name_restrictions(self): - sample_messages = [ - {'body': {'key': 'value'}, 'ttl': 200}, - ] - messages_path = self.url_prefix + '/queues/%s/messages' - sample_doc = jsonutils.dumps({'messages': sample_messages}) - - self.simulate_post(messages_path % 'Nice-Boat_2', - body=sample_doc, headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - self.simulate_post(messages_path % 'Nice-Bo@t', - body=sample_doc, headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - self.simulate_post(messages_path % ('_niceboat' * 8), - body=sample_doc, headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def _test_post(self, sample_messages): - sample_doc = jsonutils.dumps({'messages': sample_messages}) - - result = self.simulate_post(self.messages_path, - body=sample_doc, headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - result_doc = jsonutils.loads(result[0]) - - msg_ids = self._get_msg_ids(self.srmock.headers_dict) - self.assertEqual(len(sample_messages), len(msg_ids)) - - expected_resources = [str(self.messages_path + '/' + id) - for id in msg_ids] - self.assertEqual(expected_resources, result_doc['resources']) - - # NOTE(kgriffs): As of v1.1, "partial" is no longer given - # in the response document. - self.assertNotIn('partial', result_doc) - - self.assertEqual(len(sample_messages), len(msg_ids)) - - lookup = dict([(m['ttl'], m['body']) for m in sample_messages]) - - # Test GET on the message resource directly - # NOTE(cpp-cabrera): force the passing of time to age a message - timeutils_utcnow = 'oslo_utils.timeutils.utcnow' - now = timeutils.utcnow() + datetime.timedelta(seconds=10) - with mock.patch(timeutils_utcnow) as mock_utcnow: - mock_utcnow.return_value = now - for msg_id in msg_ids: - message_uri = self.messages_path + '/' + msg_id - - headers = self.headers.copy() - headers['X-Project-ID'] = '777777' - # Wrong project ID - self.simulate_get(message_uri, headers=headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - # Correct project ID - result = self.simulate_get(message_uri, headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # Check message properties - message = jsonutils.loads(result[0]) - self.assertEqual(message_uri, message['href']) - self.assertEqual(lookup[message['ttl']], message['body']) - self.assertEqual(msg_id, message['id']) - - # no negative age - # NOTE(cpp-cabrera): testtools lacks GreaterThanEqual on py26 - self.assertThat(message['age'], - matchers.GreaterThan(-1)) - - # Test bulk GET - query_string = 'ids=' + ','.join(msg_ids) - result = self.simulate_get(self.messages_path, - query_string=query_string, - headers=self.headers) - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - result_doc = jsonutils.loads(result[0]) - expected_ttls = set(m['ttl'] for m in sample_messages) - actual_ttls = set(m['ttl'] for m in result_doc['messages']) - self.assertFalse(expected_ttls - actual_ttls) - actual_ids = set(m['id'] for m in result_doc['messages']) - self.assertFalse(set(msg_ids) - actual_ids) - - def test_exceeded_payloads(self): - # Get a valid message id - self._post_messages(self.messages_path) - msg_id = self._get_msg_id(self.srmock.headers_dict) - - # Bulk GET restriction - query_string = 'ids=' + ','.join([msg_id] * 21) - self.simulate_get(self.messages_path, - query_string=query_string, headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - # Listing restriction - self.simulate_get(self.messages_path, - query_string='limit=21', - headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - # Bulk deletion restriction - query_string = 'ids=' + ','.join([msg_id] * 22) - self.simulate_delete(self.messages_path, - query_string=query_string, headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_post_single(self): - sample_messages = [ - {'body': {'key': 'value'}, 'ttl': 200}, - ] - - self._test_post(sample_messages) - - def test_post_multiple(self): - sample_messages = [ - {'body': 239, 'ttl': 100}, - {'body': {'key': 'value'}, 'ttl': 200}, - {'body': [1, 3], 'ttl': 300}, - ] - - self._test_post(sample_messages) - - def test_post_optional_ttl(self): - sample_messages = { - 'messages': [ - {'body': 239}, - {'body': {'key': 'value'}, 'ttl': 200}, - ], - } - - # Manually check default TTL is max from config - - sample_doc = jsonutils.dumps(sample_messages) - result = self.simulate_post(self.messages_path, - body=sample_doc, headers=self.headers) - - self.assertEqual(falcon.HTTP_201, self.srmock.status) - result_doc = jsonutils.loads(result[0]) - - href = result_doc['resources'][0] - result = self.simulate_get(href, headers=self.headers) - message = jsonutils.loads(result[0]) - - self.assertEqual(self.default_message_ttl, message['ttl']) - - def test_post_to_non_ascii_queue(self): - # NOTE(kgriffs): This test verifies that routes with - # embedded queue name params go through the validation - # hook, regardless of the target resource. - - path = self.url_prefix + '/queues/non-ascii-n\u0153me/messages' - - self._post_messages(path) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_post_with_long_queue_name(self): - # NOTE(kgriffs): This test verifies that routes with - # embedded queue name params go through the validation - # hook, regardless of the target resource. - - queues_path = self.url_prefix + '/queues/' - - game_title = 'v' * validation.QUEUE_NAME_MAX_LEN - self.addCleanup( - self.simulate_delete, queues_path + game_title, - headers=self.headers) - self._post_messages(queues_path + game_title + '/messages') - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - game_title += 'v' - self._post_messages(queues_path + game_title + '/messages') - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_post_to_missing_queue(self): - self.addCleanup( - self.simulate_delete, self.url_prefix + '/queues/nonexistent', - headers=self.headers) - self._post_messages(self.url_prefix + '/queues/nonexistent/messages') - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - def test_get_from_missing_queue(self): - body = self.simulate_get(self.url_prefix + - '/queues/nonexistent/messages', - headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self._empty_message_list(body) - - @ddt.data('', '0xdeadbeef', '550893e0-2b6e-11e3-835a-5cf9dd72369') - def test_bad_client_id(self, text_id): - self.simulate_post(self.queue_path + '/messages', - body='{"ttl": 60, "body": ""}', - headers={'Client-ID': text_id}) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - self.simulate_get(self.queue_path + '/messages', - query_string='limit=3&echo=true', - headers={'Client-ID': text_id}) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - @ddt.data(None, '[', '[]', '{}', '.') - def test_post_bad_message(self, document): - self.simulate_post(self.queue_path + '/messages', - body=document, - headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - @ddt.data(-1, 59, 1209601) - def test_unacceptable_ttl(self, ttl): - doc = {'messages': [{'ttl': ttl, 'body': None}]} - - self.simulate_post(self.queue_path + '/messages', - body=jsonutils.dumps(doc), - headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_exceeded_message_posting(self): - # Total (raw request) size - doc = {'messages': [{'body': "some body", 'ttl': 100}] * 20} - body = jsonutils.dumps(doc, indent=4) - - max_len = self.transport_cfg.max_messages_post_size - long_body = body + (' ' * (max_len - len(body) + 1)) - - self.simulate_post(self.queue_path + '/messages', - body=long_body, - headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - @ddt.data('{"overflow": 9223372036854775808}', - '{"underflow": -9223372036854775809}') - def test_unsupported_json(self, document): - self.simulate_post(self.queue_path + '/messages', - body=document, - headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_delete(self): - self._post_messages(self.messages_path) - msg_id = self._get_msg_id(self.srmock.headers_dict) - target = self.messages_path + '/' + msg_id - - self.simulate_get(target, headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - self.simulate_delete(target, headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - self.simulate_get(target, headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - # Safe to delete non-existing ones - self.simulate_delete(target, headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - def test_bulk_delete(self): - path = self.queue_path + '/messages' - self._post_messages(path, repeat=5) - [target, params] = self.srmock.headers_dict['location'].split('?') - - # Deleting the whole collection is denied - self.simulate_delete(path, headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - self.simulate_delete(target, query_string=params, headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - self.simulate_get(target, query_string=params, headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - # Safe to delete non-existing ones - self.simulate_delete(target, query_string=params, headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # Even after the queue is gone - self.simulate_delete(self.queue_path, headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - self.simulate_delete(target, query_string=params, headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - def test_list(self): - path = self.queue_path + '/messages' - self._post_messages(path, repeat=10) - - query_string = 'limit=3&echo=true' - body = self.simulate_get(path, - query_string=query_string, - headers=self.headers) - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - cnt = 0 - while jsonutils.loads(body[0])['messages'] != []: - contents = jsonutils.loads(body[0]) - [target, params] = contents['links'][0]['href'].split('?') - - for msg in contents['messages']: - self.simulate_get(msg['href'], headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - body = self.simulate_get(target, - query_string=params, - headers=self.headers) - cnt += 1 - - self.assertEqual(4, cnt) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self._empty_message_list(body) - - # Stats - body = self.simulate_get(self.queue_path + '/stats', - headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - message_stats = jsonutils.loads(body[0])['messages'] - - # NOTE(kgriffs): The other parts of the stats are tested - # in tests.storage.base and so are not repeated here. - expected_pattern = self.queue_path + '/messages/[^/]+$' - for message_stat_name in ('oldest', 'newest'): - self.assertThat(message_stats[message_stat_name]['href'], - matchers.MatchesRegex(expected_pattern)) - - # NOTE(kgriffs): Try to get messages for a missing queue - body = self.simulate_get(self.url_prefix + - '/queues/nonexistent/messages', - headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self._empty_message_list(body) - - def test_list_with_bad_marker(self): - path = self.queue_path + '/messages' - self._post_messages(path, repeat=5) - - query_string = 'limit=3&echo=true&marker=sfhlsfdjh2048' - body = self.simulate_get(path, - query_string=query_string, - headers=self.headers) - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self._empty_message_list(body) - - def test_no_uuid(self): - headers = { - 'Client-ID': "textid", - 'X-Project-ID': '7e7e7e' - } - path = self.queue_path + '/messages' - - self.simulate_post(path, body='[{"body": 0, "ttl": 100}]', - headers=headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - self.simulate_get(path, headers=headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_get_claimed_contains_claim_id_in_href(self): - path = self.queue_path - res = self._post_messages(path + '/messages', repeat=5) - for url in jsonutils.loads(res[0])['resources']: - message = self.simulate_get(url) - self.assertNotIn('claim_id', jsonutils.loads(message[0])['href']) - - self.simulate_post(path + '/claims', - body='{"ttl": 100, "grace": 100}', - headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - for url in jsonutils.loads(res[0])['resources']: - message = self.simulate_get(url) - self.assertIn('claim_id', jsonutils.loads(message[0])['href']) - - # NOTE(cpp-cabrera): regression test against bug #1210633 - def test_when_claim_deleted_then_messages_unclaimed(self): - path = self.queue_path - self._post_messages(path + '/messages', repeat=5) - - # post claim - self.simulate_post(path + '/claims', - body='{"ttl": 100, "grace": 100}', - headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - location = self.srmock.headers_dict['location'] - - # release claim - self.simulate_delete(location, headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # get unclaimed messages - self.simulate_get(path + '/messages', - query_string='echo=true', - headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # NOTE(cpp-cabrera): regression test against bug #1203842 - def test_get_nonexistent_message_404s(self): - path = self.url_prefix + '/queues/notthere/messages/a' - self.simulate_get(path, headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - def test_get_multiple_invalid_messages_404s(self): - path = self.url_prefix + '/queues/notthere/messages' - self.simulate_get(path, query_string='ids=a,b,c', - headers=self.headers) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - def test_delete_multiple_invalid_messages_204s(self): - path = self.url_prefix + '/queues/notthere/messages' - self.simulate_delete(path, query_string='ids=a,b,c', - headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - def test_delete_message_with_invalid_claim_doesnt_delete_message(self): - path = self.queue_path - resp = self._post_messages(path + '/messages', 1) - location = jsonutils.loads(resp[0])['resources'][0] - - self.simulate_delete(location, query_string='claim_id=invalid', - headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - self.simulate_get(location, headers=self.headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - def test_no_duplicated_messages_path_in_href(self): - """Test for bug 1240897.""" - - path = self.queue_path + '/messages' - self._post_messages(path, repeat=1) - - msg_id = self._get_msg_id(self.srmock.headers_dict) - - query_string = 'ids=%s' % msg_id - body = self.simulate_get(path, - query_string=query_string, - headers=self.headers) - messages = jsonutils.loads(body[0]) - - self.assertNotIn(self.queue_path + '/messages/messages', - messages['messages'][0]['href']) - - def _post_messages(self, target, repeat=1): - doc = {'messages': [{'body': 239, 'ttl': 300}] * repeat} - - body = jsonutils.dumps(doc) - return self.simulate_post(target, body=body, headers=self.headers) - - def _get_msg_id(self, headers): - return self._get_msg_ids(headers)[0] - - def _get_msg_ids(self, headers): - return headers['location'].rsplit('=', 1)[-1].split(',') - - @ddt.data(1, 2, 10) - def test_pop(self, message_count): - - self._post_messages(self.messages_path, repeat=message_count) - msg_id = self._get_msg_id(self.srmock.headers_dict) - target = self.messages_path + '/' + msg_id - - self.simulate_get(target, self.project_id) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - query_string = 'pop=' + str(message_count) - result = self.simulate_delete(self.messages_path, self.project_id, - query_string=query_string) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - result_doc = jsonutils.loads(result[0]) - - self.assertEqual(message_count, len(result_doc['messages'])) - - self.simulate_get(target, self.project_id) - self.assertEqual(falcon.HTTP_404, self.srmock.status) - - @ddt.data('', 'pop=1000000', 'pop=10&ids=1', 'pop=-1') - def test_pop_invalid(self, query_string): - - self.simulate_delete(self.messages_path, self.project_id, - query_string=query_string) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_pop_empty_queue(self): - - query_string = 'pop=1' - result = self.simulate_delete(self.messages_path, self.project_id, - query_string=query_string) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - result_doc = jsonutils.loads(result[0]) - self.assertEqual([], result_doc['messages']) - - def test_pop_single_message(self): - - self._post_messages(self.messages_path, repeat=5) - msg_id = self._get_msg_id(self.srmock.headers_dict) - target = self.messages_path + '/' + msg_id - - self.simulate_get(target, self.project_id) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # Pop Single message from the queue - query_string = 'pop=1' - result = self.simulate_delete(self.messages_path, self.project_id, - query_string=query_string) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # Get messages from the queue & verify message count - query_string = 'echo=True' - result = self.simulate_get(self.messages_path, self.project_id, - query_string=query_string, - headers=self.headers) - result_doc = jsonutils.loads(result[0]) - actual_msg_count = len(result_doc['messages']) - expected_msg_count = 4 - self.assertEqual(expected_msg_count, actual_msg_count) - - -class TestMessagesMongoDBPooled(TestMessagesMongoDB): - config_file = 'wsgi_mongodb_pooled.conf' - - # TODO(cpp-cabrera): remove this skipTest once pooled queue - # listing is implemented - def test_list(self): - self.skipTest("Need to implement pooled queue listing.") - - -class TestMessagesFaultyDriver(base.V1_1BaseFaulty): - config_file = 'wsgi_faulty.conf' - - def test_simple(self): - project_id = 'xyz' - path = self.url_prefix + '/queues/fizbit/messages' - body = '{"messages": [{"body": 239, "ttl": 100}]}' - headers = { - 'Client-ID': str(uuid.uuid4()), - 'X-Project-ID': project_id - } - - self.simulate_post(path, - body=body, - headers=headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - self.simulate_get(path, - headers=headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - self.simulate_get(path + '/nonexistent', headers=headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - self.simulate_delete(path + '/nada', headers=headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_ping.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_ping.py deleted file mode 100644 index abbbdb675..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_ping.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2015 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. - -import falcon - -from zaqar.tests.unit.transport.wsgi import base - - -class TestPing(base.V1_1Base): - - config_file = 'wsgi_mongodb.conf' - - def test_get(self): - # TODO(kgriffs): Make use of setUp for setting the URL prefix - # so we can just say something like: - # - # response = self.simulate_get('/ping') - # - response = self.simulate_get('/v1.1/ping') - self.assertEqual(falcon.HTTP_204, self.srmock.status) - self.assertEqual([], response) - - def test_head(self): - response = self.simulate_head('/v1.1/ping') - self.assertEqual(falcon.HTTP_204, self.srmock.status) - self.assertEqual([], response) diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_queue_lifecycle.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_queue_lifecycle.py deleted file mode 100644 index c28104bc6..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_queue_lifecycle.py +++ /dev/null @@ -1,388 +0,0 @@ -# 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 unittest import mock - -import ddt -import falcon -from oslo_serialization import jsonutils -from oslo_utils import uuidutils - -from zaqar.storage import errors as storage_errors -from zaqar import tests as testing -from zaqar.tests.unit.transport.wsgi import base - - -@ddt.ddt -class TestQueueLifecycleMongoDB(base.V1_1Base): - - config_file = 'wsgi_mongodb.conf' - - @testing.requires_mongodb - def setUp(self): - super(TestQueueLifecycleMongoDB, self).setUp() - - self.queue_path = self.url_prefix + '/queues' - self.gumshoe_queue_path = self.queue_path + '/gumshoe' - self.fizbat_queue_path = self.queue_path + '/fizbat' - - self.headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': '3387309841abc_' - } - - def tearDown(self): - storage = self.boot.storage._storage - connection = storage.connection - - connection.drop_database(self.boot.control.queues_database) - - for db in storage.message_databases: - connection.drop_database(db) - - super(TestQueueLifecycleMongoDB, self).tearDown() - - def test_empty_project_id(self): - headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': '' - } - - self.simulate_put(self.gumshoe_queue_path, headers=headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - self.simulate_delete(self.gumshoe_queue_path, headers=headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - @ddt.data('480924', 'foo') - def test_basics_thoroughly(self, project_id): - headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': project_id - } - gumshoe_queue_path_stats = self.gumshoe_queue_path + '/stats' - - # Stats are empty - queue not created yet - self.simulate_get(gumshoe_queue_path_stats, headers=headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # Create - doc = '{"messages": {"ttl": 600}}' - self.simulate_put(self.gumshoe_queue_path, - headers=headers, body=doc) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - location = self.srmock.headers_dict['Location'] - self.assertEqual(self.gumshoe_queue_path, location) - - # Fetch metadata - result = self.simulate_get(self.gumshoe_queue_path, - headers=headers) - result_doc = jsonutils.loads(result[0]) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - self.assertEqual(jsonutils.loads(doc), result_doc) - - # Stats empty queue - self.simulate_get(gumshoe_queue_path_stats, headers=headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # Delete - self.simulate_delete(self.gumshoe_queue_path, headers=headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # Get non-existent stats - self.simulate_get(gumshoe_queue_path_stats, headers=headers) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - def test_name_restrictions(self): - self.simulate_put(self.queue_path + '/Nice-Boat_2', - headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - self.simulate_put(self.queue_path + '/Nice-Bo@t', - headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - self.simulate_put(self.queue_path + '/_' + 'niceboat' * 8, - headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_project_id_restriction(self): - muvluv_queue_path = self.queue_path + '/Muv-Luv' - - self.simulate_put(muvluv_queue_path, - headers={'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': 'JAM Project' * 24}) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - # no charset restrictions - self.simulate_put(muvluv_queue_path, - headers={'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': 'JAM Project'}) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - def test_non_ascii_name(self): - test_params = (('/queues/non-ascii-n\u0153me', 'utf-8'), - ('/queues/non-ascii-n\xc4me', 'iso8859-1')) - - for uri, enc in test_params: - uri = self.url_prefix + uri - - self.simulate_put(uri, headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - self.simulate_delete(uri, headers=self.headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_no_metadata(self): - self.simulate_put(self.fizbat_queue_path, - headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - self.simulate_put(self.fizbat_queue_path, body='', - headers=self.headers) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - @ddt.data('{', '[]', '.', ' ') - def test_bad_metadata(self, document): - self.simulate_put(self.fizbat_queue_path, - headers=self.headers, - body=document) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_too_much_metadata(self): - self.simulate_put(self.fizbat_queue_path, headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - doc = '{{"messages": {{"ttl": 600}}, "padding": "{pad}"}}' - - max_size = self.transport_cfg.max_queue_metadata - padding_len = max_size - (len(doc) - 10) + 1 - - doc = doc.format(pad='x' * padding_len) - - self.simulate_put(self.fizbat_queue_path, - headers=self.headers, - body=doc) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_way_too_much_metadata(self): - self.simulate_put(self.fizbat_queue_path, headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - doc = '{{"messages": {{"ttl": 600}}, "padding": "{pad}"}}' - - max_size = self.transport_cfg.max_queue_metadata - padding_len = max_size * 100 - - doc = doc.format(pad='x' * padding_len) - - self.simulate_put(self.fizbat_queue_path, - headers=self.headers, body=doc) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_custom_metadata(self): - # Set - doc = '{{"messages": {{"ttl": 600}}, "padding": "{pad}"}}' - - max_size = self.transport_cfg.max_queue_metadata - padding_len = max_size - (len(doc) - 2) - - doc = doc.format(pad='x' * padding_len) - self.simulate_put(self.fizbat_queue_path, - headers=self.headers, - body=doc) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - # Get - result = self.simulate_get(self.fizbat_queue_path, - headers=self.headers) - result_doc = jsonutils.loads(result[0]) - self.assertEqual(jsonutils.loads(doc), result_doc) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - def test_update_metadata(self): - self.skip("This should use patch instead") - xyz_queue_path = self.url_prefix + '/queues/xyz' - xyz_queue_path_metadata = xyz_queue_path - - # Create - self.simulate_put(xyz_queue_path, headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - # Set meta - doc1 = '{"messages": {"ttl": 600}}' - self.simulate_put(xyz_queue_path_metadata, - headers=self.headers, - body=doc1) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # Update - doc2 = '{"messages": {"ttl": 100}}' - self.simulate_put(xyz_queue_path_metadata, - headers=self.headers, - body=doc2) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # Get - result = self.simulate_get(xyz_queue_path_metadata, - headers=self.headers) - result_doc = jsonutils.loads(result[0]) - - self.assertEqual(jsonutils.loads(doc2), result_doc) - - def test_list(self): - arbitrary_number = 644079696574693 - project_id = str(arbitrary_number) - client_id = uuidutils.generate_uuid() - header = { - 'X-Project-ID': project_id, - 'Client-ID': client_id - } - - # NOTE(kgriffs): It's important that this one sort after the one - # above. This is in order to prove that bug/1236605 is fixed, and - # stays fixed! - alt_project_id = str(arbitrary_number + 1) - - # List empty - result = self.simulate_get(self.queue_path, headers=header) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - results = jsonutils.loads(result[0]) - self.assertEqual([], results['queues']) - self.assertIn('links', results) - self.assertEqual(0, len(results['links'])) - - # Payload exceeded - self.simulate_get(self.queue_path, headers=header, - query_string='limit=21') - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - # Create some - def create_queue(name, project_id, body): - altheader = {'Client-ID': client_id} - if project_id is not None: - altheader['X-Project-ID'] = project_id - uri = self.queue_path + '/' + name - self.simulate_put(uri, headers=altheader, body=body) - - create_queue('q1', project_id, '{"node": 31}') - create_queue('q2', project_id, '{"node": 32}') - create_queue('q3', project_id, '{"node": 33}') - - create_queue('q3', alt_project_id, '{"alt": 1}') - - # List (limit) - result = self.simulate_get(self.queue_path, headers=header, - query_string='limit=2') - - result_doc = jsonutils.loads(result[0]) - self.assertEqual(2, len(result_doc['queues'])) - - # List (no metadata, get all) - result = self.simulate_get(self.queue_path, - headers=header, query_string='limit=5') - - result_doc = jsonutils.loads(result[0]) - [target, params] = result_doc['links'][0]['href'].split('?') - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # Ensure we didn't pick up the queue from the alt project. - queues = result_doc['queues'] - self.assertEqual(3, len(queues)) - - # List with metadata - result = self.simulate_get(self.queue_path, headers=header, - query_string='detailed=true') - - self.assertEqual(falcon.HTTP_200, self.srmock.status) - result_doc = jsonutils.loads(result[0]) - [target, params] = result_doc['links'][0]['href'].split('?') - - queue = result_doc['queues'][0] - result = self.simulate_get(queue['href'], headers=header) - result_doc = jsonutils.loads(result[0]) - self.assertEqual(queue['metadata'], result_doc) - self.assertEqual({'node': 31}, result_doc) - - # List tail - self.simulate_get(target, headers=header, query_string=params) - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - # List manually-constructed tail - self.simulate_get(target, headers=header, query_string='marker=zzz') - self.assertEqual(falcon.HTTP_200, self.srmock.status) - - def test_list_returns_503_on_nopoolfound_exception(self): - arbitrary_number = 644079696574693 - project_id = str(arbitrary_number) - client_id = uuidutils.generate_uuid() - header = { - 'X-Project-ID': project_id, - 'Client-ID': client_id - } - - queue_controller = self.boot.storage.queue_controller - - with mock.patch.object(queue_controller, 'list') as mock_queue_list: - - def queue_generator(): - raise storage_errors.NoPoolFound() - - # This generator tries to be like queue controller list generator - # in some ways. - def fake_generator(): - yield queue_generator() - yield {} - mock_queue_list.return_value = fake_generator() - self.simulate_get(self.queue_path, headers=header) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - -class TestQueueLifecycleFaultyDriver(base.V1_1BaseFaulty): - - config_file = 'wsgi_faulty.conf' - - def test_simple(self): - self.headers = { - 'Client-ID': uuidutils.generate_uuid(), - 'X-Project-ID': '338730984abc_1' - } - - gumshoe_queue_path = self.url_prefix + '/queues/gumshoe' - doc = '{"messages": {"ttl": 600}}' - self.simulate_put(gumshoe_queue_path, - headers=self.headers, - body=doc) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - location = ('Location', gumshoe_queue_path) - self.assertNotIn(location, self.srmock.headers) - - result = self.simulate_get(gumshoe_queue_path, - headers=self.headers) - result_doc = jsonutils.loads(result[0]) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - self.assertNotEqual(result_doc, jsonutils.loads(doc)) - - self.simulate_get(gumshoe_queue_path + '/stats', - headers=self.headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - self.simulate_get(self.url_prefix + '/queues', - headers=self.headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) - - self.simulate_delete(gumshoe_queue_path, headers=self.headers) - self.assertEqual(falcon.HTTP_503, self.srmock.status) diff --git a/zaqar/tests/unit/transport/wsgi/v1_1/test_validation.py b/zaqar/tests/unit/transport/wsgi/v1_1/test_validation.py deleted file mode 100644 index f0c239936..000000000 --- a/zaqar/tests/unit/transport/wsgi/v1_1/test_validation.py +++ /dev/null @@ -1,137 +0,0 @@ -# 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. - -import falcon - -from oslo_serialization import jsonutils -from oslo_utils import uuidutils -from zaqar.tests.unit.transport.wsgi import base - - -class TestValidation(base.V1_1Base): - - config_file = 'wsgi_mongodb_validation.conf' - - def setUp(self): - super(TestValidation, self).setUp() - - self.project_id = '7e55e1a7e' - - self.queue_path = self.url_prefix + '/queues/noein' - self.simulate_put(self.queue_path, self.project_id) - - self.headers = { - 'Client-ID': uuidutils.generate_uuid(), - } - - def tearDown(self): - self.simulate_delete(self.queue_path, self.project_id) - super(TestValidation, self).tearDown() - - def test_metadata_deserialization(self): - # Normal case - self.simulate_put(self.queue_path, - self.project_id, - body='{"timespace": "Shangri-la"}') - - self.assertEqual(falcon.HTTP_204, self.srmock.status) - - # Too long - max_queue_metadata = 64 - - doc_tmpl = '{{"Dragon Torc":"{0}"}}' - doc_tmpl_ws = '{{ "Dragon Torc" : "{0}" }}' # with whitespace - envelope_length = len(doc_tmpl.format('')) - - for tmpl in doc_tmpl, doc_tmpl_ws: - gen = '0' * (max_queue_metadata - envelope_length + 1) - doc = tmpl.format(gen) - self.simulate_put(self.queue_path, - self.project_id, - body=doc) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_message_deserialization(self): - # Normal case - body = '{"messages": [{"body": "Dragon Knights", "ttl": 100}]}' - self.simulate_post(self.queue_path + '/messages', - self.project_id, body=body, - headers=self.headers) - - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - # Both messages' size are too long - max_messages_post_size = 256 - - obj = {'a': 0, 'b': ''} - envelope_length = len(jsonutils.dumps(obj, separators=(',', ':'))) - obj['b'] = 'x' * (max_messages_post_size - envelope_length + 1) - - for long_body in ('a' * (max_messages_post_size - 2 + 1), obj): - doc = jsonutils.dumps([{'body': long_body, 'ttl': 100}]) - self.simulate_post(self.queue_path + '/messages', - self.project_id, - body=doc, - headers=self.headers) - - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_request_without_client_id(self): - # No Client-ID in headers, it will raise 400 error. - empty_headers = {} - self.simulate_put(self.queue_path, - self.project_id, - headers=empty_headers) - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - def test_queue_metadata_putting(self): - # Test _default_message_ttl - # TTL normal case - queue_1 = self.url_prefix + '/queues/queue1' - self.simulate_put(queue_1, - self.project_id, - body='{"_default_message_ttl": 60}') - self.addCleanup(self.simulate_delete, queue_1, self.project_id, - headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - # TTL under min - self.simulate_put(queue_1, - self.project_id, - body='{"_default_message_ttl": 59}') - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - # TTL over max - self.simulate_put(queue_1, - self.project_id, - body='{"_default_message_ttl": 1209601}') - self.assertEqual(falcon.HTTP_400, self.srmock.status) - - # Test _max_messages_post_size - # Size normal case - queue_2 = self.url_prefix + '/queues/queue2' - self.simulate_put(queue_2, - self.project_id, - body='{"_max_messages_post_size": 255}') - self.addCleanup(self.simulate_delete, queue_2, self.project_id, - headers=self.headers) - self.assertEqual(falcon.HTTP_201, self.srmock.status) - - # Size over max - self.simulate_put(queue_2, - self.project_id, - body='{"_max_messages_post_size": 257}') - self.assertEqual(falcon.HTTP_400, self.srmock.status)