test(wsgi): Refactor tests in preparation for API v1.1

The tests were refactored into an inheritance model so that we can
share as much of the testing code as possible between v1.0 and v1.1.

As a part of this process, test class names were normalized and the
py3k check for keystone middleware was removed.

Change-Id: I04d342e2ce8bfd4fa0829935deb9b2753dd5af32
Partially-Implements: blueprint api-v1.1
This commit is contained in:
kgriffs 2014-02-24 17:27:10 -06:00
parent ca2e1d299f
commit a917e8e353
20 changed files with 478 additions and 261 deletions

View File

@ -24,7 +24,7 @@ JSON_HOME = {
# Queues
#------------------------------------------------------------------
'rel/queues': {
'href-template': '/v1/queues{?marker,limit,detailed}',
'href-template': '/v1.1/queues{?marker,limit,detailed}',
'href-vars': {
'marker': 'param/marker',
'limit': 'param/queue_limit',
@ -38,7 +38,7 @@ JSON_HOME = {
},
},
'rel/queue': {
'href-template': '/v1/queues/{queue_name}',
'href-template': '/v1.1/queues/{queue_name}',
'href-vars': {
'queue_name': 'param/queue_name',
},
@ -50,7 +50,7 @@ JSON_HOME = {
},
},
'rel/queue-metadata': {
'href-template': '/v1/queues/{queue_name}/metadata',
'href-template': '/v1.1/queues/{queue_name}/metadata',
'href-vars': {
'queue_name': 'param/queue_name',
},
@ -62,7 +62,7 @@ JSON_HOME = {
},
},
'rel/queue-stats': {
'href-template': '/v1/queues/{queue_name}/stats',
'href-template': '/v1.1/queues/{queue_name}/stats',
'href-vars': {
'queue_name': 'param/queue_name',
},
@ -78,7 +78,7 @@ JSON_HOME = {
# Messages
#------------------------------------------------------------------
'rel/messages': {
'href-template': ('/v1/queues/{queue_name}/messages'
'href-template': ('/v1.1/queues/{queue_name}/messages'
'{?marker,limit,echo,include_claimed}'),
'href-vars': {
'queue_name': 'param/queue_name',
@ -95,7 +95,7 @@ JSON_HOME = {
},
},
'rel/post-messages': {
'href-template': '/v1/queues/{queue_name}/messages',
'href-template': '/v1.1/queues/{queue_name}/messages',
'href-vars': {
'queue_name': 'param/queue_name',
},
@ -112,7 +112,7 @@ JSON_HOME = {
# Claims
#------------------------------------------------------------------
'rel/claim': {
'href-template': '/v1/queues/{queue_name}/claims{?limit}',
'href-template': '/v1.1/queues/{queue_name}/claims{?limit}',
'href-vars': {
'queue_name': 'param/queue_name',
'limit': 'param/claim_limit',

View File

@ -0,0 +1,46 @@
# 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.
# TODO(kgriffs): Consider consolidating all of these tests into a
# single module.
from marconi.tests.queues.transport.wsgi import base
from marconi.tests.queues.transport.wsgi import test_auth
from marconi.tests.queues.transport.wsgi import test_claims
from marconi.tests.queues.transport.wsgi import test_default_limits
from marconi.tests.queues.transport.wsgi import test_home
from marconi.tests.queues.transport.wsgi import test_media_type
from marconi.tests.queues.transport.wsgi import test_messages
from marconi.tests.queues.transport.wsgi import test_queue_lifecycle
from marconi.tests.queues.transport.wsgi import test_shards
TestBase = base.TestBase
TestBaseFaulty = base.TestBaseFaulty
TestAuth = test_auth.TestAuth
TestClaimsFaultyDriver = test_claims.TestClaimsFaultyDriver
TestClaimsMongoDB = test_claims.TestClaimsMongoDB
TestClaimsSQLite = test_claims.TestClaimsSQLite
TestDefaultLimits = test_default_limits.TestDefaultLimits
TestHomeDocument = test_home.TestHomeDocument
TestMediaType = test_media_type.TestMediaType
TestMessagesFaultyDriver = test_messages.TestMessagesFaultyDriver
TestMessagesMongoDB = test_messages.TestMessagesMongoDB
TestMessagesMongoDBSharded = test_messages.TestMessagesMongoDBSharded
TestMessagesSQLite = test_messages.TestMessagesSQLite
TestQueueFaultyDriver = test_queue_lifecycle.TestQueueLifecycleFaultyDriver
TestQueueLifecycleMongoDB = test_queue_lifecycle.TestQueueLifecycleMongoDB
TestQueueLifecycleSQLite = test_queue_lifecycle.TestQueueLifecycleSQLite
TestShardsMongoDB = test_shards.TestShardsMongoDB

View File

@ -18,29 +18,24 @@ import uuid
import falcon
from falcon import testing
import six
import testtools
if not six.PY3:
from keystoneclient.middleware import auth_token
from keystoneclient.middleware import auth_token
from . import base # noqa
@testtools.skipIf(six.PY3, "No Py3K support for keystoneclient")
class TestWSGIAuth(base.TestBase):
class TestAuth(base.TestBase):
config_file = 'keystone_auth.conf'
def setUp(self):
super(TestWSGIAuth, self).setUp()
super(TestAuth, self).setUp()
self.headers = {'Client-ID': str(uuid.uuid4())}
def test_auth_install(self):
self.assertIsInstance(self.app, auth_token.AuthProtocol)
def test_non_authenticated(self):
env = testing.create_environ('/v1/480924/queues/',
env = testing.create_environ(self.url_prefix + '/480924/queues/',
method='GET',
headers=self.headers)

View File

@ -34,7 +34,7 @@ class ClaimsBaseTest(base.TestBase):
super(ClaimsBaseTest, self).setUp()
self.project_id = '480924'
self.queue_path = '/v1/queues/fizbit'
self.queue_path = self.url_prefix + '/queues/fizbit'
self.claims_path = self.queue_path + '/claims'
self.messages_path = self.queue_path + '/messages'
@ -198,12 +198,14 @@ class ClaimsBaseTest(base.TestBase):
self.assertEqual(self.srmock.status, falcon.HTTP_404)
def test_post_claim_nonexistent_queue(self):
self.simulate_post('/v1/queues/nonexistent/claims', self.project_id,
path = self.url_prefix + '/queues/nonexistent/claims'
self.simulate_post(path, self.project_id,
body='{"ttl": 100, "grace": 60}')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
def test_get_claim_nonexistent_queue(self):
self.simulate_get('/v1/queues/nonexistent/claims/aaabbbba')
path = self.url_prefix + '/queues/nonexistent/claims/aaabbbba'
self.simulate_get(path)
self.assertEqual(self.srmock.status, falcon.HTTP_404)
# NOTE(cpp-cabrera): regression test against bug #1203842
@ -221,13 +223,13 @@ class ClaimsBaseTest(base.TestBase):
self.assertEqual(self.srmock.status, falcon.HTTP_404)
@testing.requires_mongodb
class ClaimsMongoDBTests(ClaimsBaseTest):
class TestClaimsMongoDB(ClaimsBaseTest):
config_file = 'wsgi_mongodb.conf'
@testing.requires_mongodb
def setUp(self):
super(ClaimsMongoDBTests, self).setUp()
super(TestClaimsMongoDB, self).setUp()
def tearDown(self):
storage = self.boot.storage._storage
@ -238,21 +240,21 @@ class ClaimsMongoDBTests(ClaimsBaseTest):
for db in storage.message_databases:
connection.drop_database(db)
super(ClaimsMongoDBTests, self).tearDown()
super(TestClaimsMongoDB, self).tearDown()
class ClaimsSQLiteTests(ClaimsBaseTest):
class TestClaimsSQLite(ClaimsBaseTest):
config_file = 'wsgi_sqlite.conf'
class ClaimsFaultyDriverTests(base.TestBaseFaulty):
class TestClaimsFaultyDriver(base.TestBaseFaulty):
config_file = 'wsgi_faulty.conf'
def test_simple(self):
project_id = '480924'
claims_path = '/v1/queues/fizbit/claims'
claims_path = self.url_prefix + '/queues/fizbit/claims'
doc = '{"ttl": 100, "grace": 60}'
self.simulate_post(claims_path, project_id, body=doc)

View File

@ -31,7 +31,7 @@ class TestDefaultLimits(base.TestBase):
def setUp(self):
super(TestDefaultLimits, self).setUp()
self.queue_path = '/v1/queues/q1'
self.queue_path = self.url_prefix + '/queues/q1'
self.messages_path = self.queue_path + '/messages'
self.claims_path = self.queue_path + '/claims'
@ -43,11 +43,11 @@ class TestDefaultLimits(base.TestBase):
def test_queue_listing(self):
# 2 queues to list
self.simulate_put('/v1/queues/q2')
self.simulate_put(self.url_prefix + '/queues/q2')
self.assertEqual(self.srmock.status, falcon.HTTP_201)
with self._prepare_queues(storage.DEFAULT_QUEUES_PER_PAGE + 1):
result = self.simulate_get('/v1/queues')
result = self.simulate_get(self.url_prefix + '/queues')
self.assertEqual(self.srmock.status, falcon.HTTP_200)
queues = json.loads(result[0])['queues']
@ -77,7 +77,7 @@ class TestDefaultLimits(base.TestBase):
@contextlib.contextmanager
def _prepare_queues(self, count):
queue_paths = ['/v1/queues/multi-{0}'.format(i)
queue_paths = [self.url_prefix + '/queues/multi-{0}'.format(i)
for i in range(count)]
for path in queue_paths:

View File

@ -27,7 +27,7 @@ class TestHomeDocument(base.TestBase):
config_file = 'wsgi_sqlite.conf'
def test_json_response(self):
body = self.simulate_get('/v1')
body = self.simulate_get(self.url_prefix)
self.assertEqual(self.srmock.status, falcon.HTTP_200)
content_type = self.srmock.headers_dict['Content-Type']
@ -39,22 +39,22 @@ class TestHomeDocument(base.TestBase):
self.fail('Home document is not valid JSON')
def test_href_template(self):
body = self.simulate_get('/v1')
body = self.simulate_get(self.url_prefix)
self.assertEqual(self.srmock.status, falcon.HTTP_200)
resp = json.loads(body[0])
queue_href_template = resp['resources']['rel/queue']['href-template']
path_1 = 'https://marconi.example.com/v1'
path_2 = 'https://marconi.example.com/v1/'
path_1 = 'https://marconi.example.com' + self.url_prefix
path_2 = 'https://marconi.example.com' + self.url_prefix + '/'
# verify all the href template start with /v1
# Verify all the href template start with the correct version prefix
for resource in list(resp['resources']):
self.assertTrue(resp['resources'][resource]['href-template'].
startswith('/v1'))
startswith(self.url_prefix))
url = urlparse.urljoin(path_1, queue_href_template)
self.assertEqual(url.format(queue_name='foo'),
'https://marconi.example.com/v1/queues/foo')
expected = ('https://marconi.example.com' + self.url_prefix +
'/queues/foo')
self.assertEqual(url.format(queue_name='foo'), expected)
url = urlparse.urljoin(path_2, queue_href_template)
self.assertEqual(url.format(queue_name='foo'),
'https://marconi.example.com/v1/queues/foo')
self.assertEqual(url.format(queue_name='foo'), expected)

View File

@ -0,0 +1,51 @@
# 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 . import base # noqa
class TestMediaType(base.TestBase):
config_file = 'wsgi_sqlite.conf'
def test_json_only_endpoints(self):
endpoints = (
('GET', self.url_prefix + '/queues'),
('GET', self.url_prefix + '/queues/nonexistent/metadata'),
('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(self.srmock.status, falcon.HTTP_406)

View File

@ -39,12 +39,16 @@ class MessagesBaseTest(base.TestBase):
for i in range(4):
uri = self.conf['drivers:storage:mongodb'].uri
doc = {'weight': 100, 'uri': uri}
self.simulate_put('/v1/shards/' + str(i),
self.simulate_put(self.url_prefix + '/shards/' + str(i),
body=json.dumps(doc))
self.assertEqual(self.srmock.status, falcon.HTTP_201)
self.project_id = '7e55e1a7e'
self.queue_path = '/v1/queues/fizbit'
# 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}'
@ -58,7 +62,7 @@ class MessagesBaseTest(base.TestBase):
self.simulate_delete(self.queue_path, self.project_id)
if self.conf.sharding:
for i in range(4):
self.simulate_delete('/v1/shards/' + str(i))
self.simulate_delete(self.url_prefix + '/shards/' + str(i))
super(MessagesBaseTest, self).tearDown()
@ -170,7 +174,7 @@ class MessagesBaseTest(base.TestBase):
# embedded queue name params go through the validation
# hook, regardless of the target resource.
path = u'/v1/queues/non-ascii-n\u0153me/messages'
path = self.url_prefix + u'/queues/non-ascii-n\u0153me/messages'
if six.PY2:
path = path.encode('utf-8')
@ -183,20 +187,23 @@ class MessagesBaseTest(base.TestBase):
# 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._post_messages('/v1/queues/' + game_title + '/messages')
self._post_messages(queues_path + game_title + '/messages')
self.assertEqual(self.srmock.status, falcon.HTTP_404)
game_title += 'v'
self._post_messages('/v1/queues/' + game_title + '/messages')
self._post_messages(queues_path + game_title + '/messages')
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_post_to_missing_queue(self):
self._post_messages('/v1/queues/nonexistent/messages')
self._post_messages(self.url_prefix + '/queues/nonexistent/messages')
self.assertEqual(self.srmock.status, falcon.HTTP_404)
def test_get_from_missing_queue(self):
self.simulate_get('/v1/queues/nonexistent/messages', self.project_id,
self.simulate_get(self.url_prefix + '/queues/nonexistent/messages',
self.project_id,
headers={'Client-ID':
'dfcd3238-425c-11e3-8a80-28cfe91478b9'})
self.assertEqual(self.srmock.status, falcon.HTTP_204)
@ -344,7 +351,8 @@ class MessagesBaseTest(base.TestBase):
matchers.MatchesRegex(expected_pattern))
# NOTE(kgriffs): Try to get messages for a missing queue
self.simulate_get('/v1/queues/nonexistent/messages', self.project_id,
self.simulate_get(self.url_prefix + '/queues/nonexistent/messages',
self.project_id,
headers=self.headers)
self.assertEqual(self.srmock.status, falcon.HTTP_204)
@ -392,21 +400,18 @@ class MessagesBaseTest(base.TestBase):
# NOTE(cpp-cabrera): regression test against bug #1203842
def test_get_nonexistent_message_404s(self):
path = '/v1/queues/notthere'
self.simulate_get(path + '/messages/a')
path = self.url_prefix + '/queues/notthere/messages/a'
self.simulate_get(path)
self.assertEqual(self.srmock.status, falcon.HTTP_404)
def test_get_multiple_invalid_messages_204s(self):
path = '/v1/queues/notthere'
self.simulate_get(path + '/messages', query_string='ids=a,b,c')
path = self.url_prefix + '/queues/notthere/messages'
self.simulate_get(path, query_string='ids=a,b,c')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
def test_delete_multiple_invalid_messages_204s(self):
path = '/v1/queues/notthere'
self.simulate_delete(path + '/messages', query_string='ids=a,b,c')
path = self.url_prefix + '/queues/notthere/messages'
self.simulate_delete(path, query_string='ids=a,b,c')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
def test_delete_message_with_invalid_claim_doesnt_delete_message(self):
@ -449,7 +454,7 @@ class MessagesBaseTest(base.TestBase):
return headers['location'].rsplit('=', 1)[-1].split(',')
class MessagesSQLiteTests(MessagesBaseTest):
class TestMessagesSQLite(MessagesBaseTest):
config_file = 'wsgi_sqlite.conf'
@ -458,28 +463,28 @@ class MessagesSQLiteTests(MessagesBaseTest):
# catalogue get an sqlite implementation.
@testing.requires_mongodb
class MessagesMongoDBTests(MessagesBaseTest):
class TestMessagesMongoDB(MessagesBaseTest):
config_file = 'wsgi_mongodb.conf'
@testing.requires_mongodb
def setUp(self):
super(MessagesMongoDBTests, self).setUp()
super(TestMessagesMongoDB, self).setUp()
def tearDown(self):
super(MessagesMongoDBTests, self).tearDown()
super(TestMessagesMongoDB, self).tearDown()
@testing.requires_mongodb
class MessagesMongoDBShardedTests(MessagesBaseTest):
class TestMessagesMongoDBSharded(MessagesBaseTest):
config_file = 'wsgi_mongodb_sharded.conf'
@testing.requires_mongodb
def setUp(self):
super(MessagesMongoDBShardedTests, self).setUp()
super(TestMessagesMongoDBSharded, self).setUp()
def tearDown(self):
super(MessagesMongoDBShardedTests, self).tearDown()
super(TestMessagesMongoDBSharded, self).tearDown()
# TODO(cpp-cabrera): remove this skipTest once sharded queue
# listing is implemented
@ -487,13 +492,13 @@ class MessagesMongoDBShardedTests(MessagesBaseTest):
self.skipTest("Need to implement sharded queue listing.")
class MessagesFaultyDriverTests(base.TestBaseFaulty):
class TestMessagesFaultyDriver(base.TestBaseFaulty):
config_file = 'wsgi_faulty.conf'
def test_simple(self):
project_id = 'xyz'
path = '/v1/queues/fizbit/messages'
path = self.url_prefix + '/queues/fizbit/messages'
doc = '[{"body": 239, "ttl": 100}]'
headers = {
'Client-ID': str(uuid.uuid4()),

View File

@ -33,7 +33,7 @@ class QueueLifecycleBaseTest(base.TestBase):
super(QueueLifecycleBaseTest, self).setUp()
def test_empty_project_id(self):
path = '/v1/queues/gumshoe'
path = self.url_prefix + '/queues/gumshoe'
self.simulate_get(path, '')
self.assertEqual(self.srmock.status, falcon.HTTP_400)
@ -49,7 +49,7 @@ class QueueLifecycleBaseTest(base.TestBase):
@ddt.data('480924', 'foo', None)
def test_basics_thoroughly(self, project_id):
path = '/v1/queues/gumshoe'
path = self.url_prefix + '/queues/gumshoe'
# Stats not found - queue not created yet
self.simulate_get(path + '/stats', project_id)
@ -64,7 +64,7 @@ class QueueLifecycleBaseTest(base.TestBase):
self.assertEqual(self.srmock.status, falcon.HTTP_201)
location = self.srmock.headers_dict['Location']
self.assertEqual(location, '/v1/queues/gumshoe')
self.assertEqual(location, self.url_prefix + '/queues/gumshoe')
# Ensure queue existence
self.simulate_head(path, project_id)
@ -102,63 +102,65 @@ class QueueLifecycleBaseTest(base.TestBase):
self.assertEqual(self.srmock.status, falcon.HTTP_404)
def test_name_restrictions(self):
self.simulate_put('/v1/queues/Nice-Boat_2')
self.simulate_put(self.url_prefix + '/queues/Nice-Boat_2')
self.assertEqual(self.srmock.status, falcon.HTTP_201)
self.simulate_put('/v1/queues/Nice-Bo@t')
self.simulate_put(self.url_prefix + '/queues/Nice-Bo@t')
self.assertEqual(self.srmock.status, falcon.HTTP_400)
self.simulate_put('/v1/queues/_' + 'niceboat' * 8)
self.simulate_put(self.url_prefix + '/queues/_' + 'niceboat' * 8)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_project_id_restriction(self):
self.simulate_put('/v1/queues/Muv-Luv',
self.simulate_put(self.url_prefix + '/queues/Muv-Luv',
headers={'X-Project-ID': 'JAM Project' * 24})
self.assertEqual(self.srmock.status, falcon.HTTP_400)
# no charset restrictions
self.simulate_put('/v1/queues/Muv-Luv',
self.simulate_put(self.url_prefix + '/queues/Muv-Luv',
headers={'X-Project-ID': 'JAM Project'})
self.assertEqual(self.srmock.status, falcon.HTTP_201)
@ddt.data((u'/v1/queues/non-ascii-n\u0153me', 'utf-8'),
(u'/v1/queues/non-ascii-n\xc4me', 'iso8859-1'))
def test_non_ascii_name(self, uri_enc):
uri, enc = uri_enc
def test_non_ascii_name(self):
test_params = ((u'/queues/non-ascii-n\u0153me', 'utf-8'),
(u'/queues/non-ascii-n\xc4me', 'iso8859-1'))
if six.PY2:
uri = uri.encode(enc)
for uri, enc in test_params:
uri = self.url_prefix + uri
self.simulate_put(uri)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
if six.PY2:
uri = uri.encode(enc)
self.simulate_get(uri)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
self.simulate_put(uri)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
self.simulate_delete(uri)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
self.simulate_get(uri)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
self.simulate_delete(uri)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_no_metadata(self):
self.simulate_put('/v1/queues/fizbat')
self.simulate_put(self.url_prefix + '/queues/fizbat')
self.assertEqual(self.srmock.status, falcon.HTTP_201)
self.simulate_put('/v1/queues/fizbat/metadata')
self.simulate_put(self.url_prefix + '/queues/fizbat/metadata')
self.assertEqual(self.srmock.status, falcon.HTTP_400)
self.simulate_put('/v1/queues/fizbat/metadata', body='')
self.simulate_put(self.url_prefix + '/queues/fizbat/metadata', body='')
self.assertEqual(self.srmock.status, falcon.HTTP_400)
@ddt.data('{', '[]', '.', ' ', '')
def test_bad_metadata(self, document):
self.simulate_put('/v1/queues/fizbat', '7e55e1a7e')
self.simulate_put(self.url_prefix + '/queues/fizbat', '7e55e1a7e')
self.assertEqual(self.srmock.status, falcon.HTTP_201)
self.simulate_put('/v1/queues/fizbat/metadata', '7e55e1a7e',
body=document)
self.simulate_put(self.url_prefix + '/queues/fizbat/metadata',
'7e55e1a7e', body=document)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_too_much_metadata(self):
self.simulate_put('/v1/queues/fizbat', '7e55e1a7e')
self.simulate_put(self.url_prefix + '/queues/fizbat', '7e55e1a7e')
self.assertEqual(self.srmock.status, falcon.HTTP_201)
doc = '{{"messages": {{"ttl": 600}}, "padding": "{pad}"}}'
@ -167,11 +169,12 @@ class QueueLifecycleBaseTest(base.TestBase):
doc = doc.format(pad='x' * padding_len)
self.simulate_put('/v1/queues/fizbat/metadata', '7e55e1a7e', body=doc)
self.simulate_put(self.url_prefix + '/queues/fizbat/metadata',
'7e55e1a7e', body=doc)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_way_too_much_metadata(self):
self.simulate_put('/v1/queues/fizbat', '7e55e1a7e')
self.simulate_put(self.url_prefix + '/queues/fizbat', '7e55e1a7e')
self.assertEqual(self.srmock.status, falcon.HTTP_201)
doc = '{{"messages": {{"ttl": 600}}, "padding": "{pad}"}}'
@ -180,11 +183,12 @@ class QueueLifecycleBaseTest(base.TestBase):
doc = doc.format(pad='x' * padding_len)
self.simulate_put('/v1/queues/fizbat/metadata', '7e55e1a7e', body=doc)
self.simulate_put(self.url_prefix + '/queues/fizbat/metadata',
'7e55e1a7e', body=doc)
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_custom_metadata(self):
self.simulate_put('/v1/queues/fizbat', '480924')
self.simulate_put(self.url_prefix + '/queues/fizbat', '480924')
self.assertEqual(self.srmock.status, falcon.HTTP_201)
# Set
@ -194,18 +198,20 @@ class QueueLifecycleBaseTest(base.TestBase):
padding_len = max_size - (len(doc) - 2)
doc = doc.format(pad='x' * padding_len)
self.simulate_put('/v1/queues/fizbat/metadata', '480924', body=doc)
self.simulate_put(self.url_prefix + '/queues/fizbat/metadata',
'480924', body=doc)
self.assertEqual(self.srmock.status, falcon.HTTP_204)
# Get
result = self.simulate_get('/v1/queues/fizbat/metadata', '480924')
result = self.simulate_get(self.url_prefix + '/queues/fizbat/metadata',
'480924')
result_doc = json.loads(result[0])
self.assertEqual(result_doc, json.loads(doc))
self.assertEqual(self.srmock.status, falcon.HTTP_200)
def test_update_metadata(self):
# Create
path = '/v1/queues/xyz'
path = self.url_prefix + '/queues/xyz'
project_id = '480924'
self.simulate_put(path, project_id)
self.assertEqual(self.srmock.status, falcon.HTTP_201)
@ -238,16 +244,17 @@ class QueueLifecycleBaseTest(base.TestBase):
alt_project_id = str(arbitrary_number + 1)
# List empty
self.simulate_get('/v1/queues', project_id)
self.simulate_get(self.url_prefix + '/queues', project_id)
self.assertEqual(self.srmock.status, falcon.HTTP_204)
# Payload exceeded
self.simulate_get('/v1/queues', project_id, query_string='limit=21')
self.simulate_get(self.url_prefix + '/queues', project_id,
query_string='limit=21')
self.assertEqual(self.srmock.status, falcon.HTTP_400)
# Create some
def create_queue(name, project_id, body):
uri = '/v1/queues/' + name
uri = self.url_prefix + '/queues/' + name
self.simulate_put(uri, project_id)
self.simulate_put(uri + '/metadata', project_id, body=body)
@ -261,7 +268,7 @@ class QueueLifecycleBaseTest(base.TestBase):
create_queue('q3', alt_project_id, '{"alt": 1}')
# List (global queues)
result = self.simulate_get('/v1/queues', None,
result = self.simulate_get(self.url_prefix + '/queues', None,
query_string='limit=2&detailed=true')
result_doc = json.loads(result[0])
@ -272,14 +279,14 @@ class QueueLifecycleBaseTest(base.TestBase):
self.assertEqual(queue['metadata'], {'answer': 42})
# List (limit)
result = self.simulate_get('/v1/queues', project_id,
result = self.simulate_get(self.url_prefix + '/queues', project_id,
query_string='limit=2')
result_doc = json.loads(result[0])
self.assertEqual(len(result_doc['queues']), 2)
# List (no metadata, get all)
result = self.simulate_get('/v1/queues', project_id,
result = self.simulate_get(self.url_prefix + '/queues', project_id,
query_string='limit=5')
result_doc = json.loads(result[0])
@ -287,7 +294,7 @@ class QueueLifecycleBaseTest(base.TestBase):
self.assertEqual(self.srmock.status, falcon.HTTP_200)
self.assertEqual(self.srmock.headers_dict['Content-Location'],
'/v1/queues?limit=5')
self.url_prefix + '/queues?limit=5')
# Ensure we didn't pick up the queue from the alt project.
queues = result_doc['queues']
@ -303,7 +310,7 @@ class QueueLifecycleBaseTest(base.TestBase):
self.assertNotIn('metadata', queue)
# List with metadata
result = self.simulate_get('/v1/queues', project_id,
result = self.simulate_get(self.url_prefix + '/queues', project_id,
query_string='detailed=true')
self.assertEqual(self.srmock.status, falcon.HTTP_200)
@ -325,13 +332,13 @@ class QueueLifecycleBaseTest(base.TestBase):
self.assertEqual(self.srmock.status, falcon.HTTP_204)
@testing.requires_mongodb
class QueueLifecycleMongoDBTests(QueueLifecycleBaseTest):
class TestQueueLifecycleMongoDB(QueueLifecycleBaseTest):
config_file = 'wsgi_mongodb.conf'
@testing.requires_mongodb
def setUp(self):
super(QueueLifecycleMongoDBTests, self).setUp()
super(TestQueueLifecycleMongoDB, self).setUp()
def tearDown(self):
storage = self.boot.storage._storage
@ -342,20 +349,20 @@ class QueueLifecycleMongoDBTests(QueueLifecycleBaseTest):
for db in storage.message_databases:
connection.drop_database(db)
super(QueueLifecycleMongoDBTests, self).tearDown()
super(TestQueueLifecycleMongoDB, self).tearDown()
class QueueLifecycleSQLiteTests(QueueLifecycleBaseTest):
class TestQueueLifecycleSQLite(QueueLifecycleBaseTest):
config_file = 'wsgi_sqlite.conf'
class QueueFaultyDriverTests(base.TestBaseFaulty):
class TestQueueLifecycleFaultyDriver(base.TestBaseFaulty):
config_file = 'wsgi_faulty.conf'
def test_simple(self):
path = '/v1/queues/gumshoe'
path = self.url_prefix + '/queues/gumshoe'
doc = '{"messages": {"ttl": 600}}'
self.simulate_put(path, '480924', body=doc)
self.assertEqual(self.srmock.status, falcon.HTTP_503)
@ -371,7 +378,7 @@ class QueueFaultyDriverTests(base.TestBaseFaulty):
self.simulate_get(path + '/stats', '480924')
self.assertEqual(self.srmock.status, falcon.HTTP_503)
self.simulate_get('/v1/queues', '480924')
self.simulate_get(self.url_prefix + '/queues', '480924')
self.assertEqual(self.srmock.status, falcon.HTTP_503)
self.simulate_delete(path, '480924')

View File

@ -41,7 +41,7 @@ def shard(test, name, weight, uri, options={}):
:rtype: see above
"""
doc = {'weight': weight, 'uri': uri, 'options': options}
path = '/v1/shards/' + name
path = test.url_prefix + '/shards/' + name
test.simulate_put(path, body=json.dumps(doc))
@ -64,7 +64,7 @@ def shards(test, count, uri):
:returns: (paths, weights, uris, options)
:rtype: ([six.text_type], [int], [six.text_type], [dict])
"""
base = '/v1/shards/'
base = test.url_prefix + '/shards/'
args = [(base + str(i), i,
{str(i): i})
for i in range(count)]
@ -85,7 +85,7 @@ class ShardsBaseTest(base.TestBase):
def setUp(self):
super(ShardsBaseTest, self).setUp()
self.doc = {'weight': 100, 'uri': 'sqlite://memory'}
self.shard = '/v1/shards/' + str(uuid.uuid1())
self.shard = self.url_prefix + '/shards/' + str(uuid.uuid1())
self.simulate_put(self.shard, body=json.dumps(self.doc))
self.assertEqual(self.srmock.status, falcon.HTTP_201)
@ -101,7 +101,7 @@ class ShardsBaseTest(base.TestBase):
self.assertEqual(self.srmock.status, falcon.HTTP_201)
def test_put_raises_if_missing_fields(self):
path = '/v1/shards/' + str(uuid.uuid1())
path = self.url_prefix + '/shards/' + str(uuid.uuid1())
self.simulate_put(path, body=json.dumps({'weight': 100}))
self.assertEqual(self.srmock.status, falcon.HTTP_400)
@ -110,7 +110,7 @@ class ShardsBaseTest(base.TestBase):
@ddt.data(-1, 2**32+1, 'big')
def test_put_raises_if_invalid_weight(self, weight):
path = '/v1/shards/' + str(uuid.uuid1())
path = self.url_prefix + '/shards/' + str(uuid.uuid1())
doc = {'weight': weight, 'uri': 'a'}
self.simulate_put(path,
body=json.dumps(doc))
@ -118,14 +118,14 @@ class ShardsBaseTest(base.TestBase):
@ddt.data(-1, 2**32+1, [], 'localhost:27017')
def test_put_raises_if_invalid_uri(self, uri):
path = '/v1/shards/' + str(uuid.uuid1())
path = self.url_prefix + '/shards/' + str(uuid.uuid1())
self.simulate_put(path,
body=json.dumps({'weight': 1, 'uri': uri}))
self.assertEqual(self.srmock.status, falcon.HTTP_400)
@ddt.data(-1, 'wee', [])
def test_put_raises_if_invalid_options(self, options):
path = '/v1/shards/' + str(uuid.uuid1())
path = self.url_prefix + '/shards/' + str(uuid.uuid1())
doc = {'weight': 1, 'uri': 'a', 'options': options}
self.simulate_put(path, body=json.dumps(doc))
self.assertEqual(self.srmock.status, falcon.HTTP_400)
@ -151,7 +151,7 @@ class ShardsBaseTest(base.TestBase):
self.assertEqual(self.srmock.status, falcon.HTTP_404)
def test_get_nonexisting_raises_404(self):
self.simulate_get('/v1/shards/nonexisting')
self.simulate_get(self.url_prefix + '/shards/nonexisting')
self.assertEqual(self.srmock.status, falcon.HTTP_404)
def _shard_expect(self, shard, xhref, xweight, xuri):
@ -225,13 +225,13 @@ class ShardsBaseTest(base.TestBase):
self.assertEqual(self.srmock.status, falcon.HTTP_400)
def test_patch_raises_404_if_shard_not_found(self):
self.simulate_patch('/v1/shards/notexists',
self.simulate_patch(self.url_prefix + '/shards/notexists',
body=json.dumps({'weight': 1}))
self.assertEqual(self.srmock.status, falcon.HTTP_404)
def test_empty_listing_returns_204(self):
self.simulate_delete(self.shard)
self.simulate_get('/v1/shards')
self.simulate_get(self.url_prefix + '/shards')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
def _listing_test(self, count=10, limit=10,
@ -244,7 +244,7 @@ class ShardsBaseTest(base.TestBase):
query += '&marker={2}'.format(marker)
with shards(self, count, self.doc['uri']) as expected:
result = self.simulate_get('/v1/shards',
result = self.simulate_get(self.url_prefix + '/shards',
query_string=query)
self.assertEqual(self.srmock.status, falcon.HTTP_200)
results = json.loads(result[0])
@ -275,7 +275,7 @@ class ShardsBaseTest(base.TestBase):
self.simulate_delete(self.shard)
with shards(self, 10, self.doc['uri']) as expected:
result = self.simulate_get('/v1/shards',
result = self.simulate_get(self.url_prefix + '/shards',
query_string='?marker=3')
self.assertEqual(self.srmock.status, falcon.HTTP_200)
shard_list = json.loads(result[0])['shards']
@ -284,10 +284,10 @@ class ShardsBaseTest(base.TestBase):
self._shard_expect(shard_list[0], path, weight, self.doc['uri'])
@testing.requires_mongodb
class ShardsMongoDBTests(ShardsBaseTest):
class TestShardsMongoDB(ShardsBaseTest):
config_file = 'wsgi_mongodb.conf'
@testing.requires_mongodb
def setUp(self):
super(ShardsMongoDBTests, self).setUp()
super(TestShardsMongoDB, self).setUp()

View File

@ -19,9 +19,6 @@ from marconi.common import request
from marconi.tests import base
HREF = '/v1/queue/'
class TestRequest(base.TestBase):
def test_request_deserialized(self):

View File

@ -1,34 +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 . import base # noqa
class TestHealth(base.TestBase):
config_file = 'wsgi_sqlite.conf'
def test_get(self):
response = self.simulate_get('/v1/health')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])
def test_head(self):
response = self.simulate_head('/v1/health')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])

View File

@ -1,53 +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 ddt
import falcon
from falcon import testing
from . import base # noqa
@ddt.ddt
class TestWSGIMediaType(base.TestBase):
config_file = 'wsgi_sqlite.conf'
@ddt.data(
('GET', '/v1/queues'),
('GET', '/v1/queues/nonexistent/metadata'),
('GET', '/v1/queues/nonexistent/stats'),
('POST', '/v1/queues/nonexistent/messages'),
('GET', '/v1/queues/nonexistent/messages/deadbeaf'),
('POST', '/v1/queues/nonexistent/claims'),
('GET', '/v1/queues/nonexistent/claims/0ad'),
('GET', '/v1/health'),
)
def test_json_only_endpoints(self, method_endpoint):
method, endpoint = method_endpoint
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(self.srmock.status, falcon.HTTP_406)

View File

@ -1,35 +0,0 @@
# Copyright 2014 IBM Corp.
# All Rights Reserved.
#
# 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 . import base # noqa
class TestPing(base.TestBase):
config_file = 'wsgi_sqlite.conf'
def test_get(self):
response = self.simulate_get('/v1.1/ping')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])
def test_head(self):
response = self.simulate_head('/v1.1/ping')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])

View File

@ -24,7 +24,7 @@ import testtools
from marconi.queues.transport.wsgi import utils
class TestWSGIutils(testtools.TestCase):
class TestUtils(testtools.TestCase):
def test_get_checked_field_missing(self):
doc = {}

View File

@ -0,0 +1,105 @@
# 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 falcon
from marconi.tests.queues.transport import wsgi
#----------------------------------------------------------------------------
# Identical or just minor variations across versions
#----------------------------------------------------------------------------
URL_PREFIX = '/v1'
class TestAuth(wsgi.TestAuth):
url_prefix = URL_PREFIX
class TestClaimsFaultyDriver(wsgi.TestClaimsFaultyDriver):
url_prefix = URL_PREFIX
class TestClaimsMongoDB(wsgi.TestClaimsMongoDB):
url_prefix = URL_PREFIX
class TestClaimsSQLite(wsgi.TestClaimsSQLite):
url_prefix = URL_PREFIX
class TestDefaultLimits(wsgi.TestDefaultLimits):
url_prefix = URL_PREFIX
class TestHomeDocument(wsgi.TestHomeDocument):
url_prefix = URL_PREFIX
class TestMediaType(wsgi.TestMediaType):
url_prefix = URL_PREFIX
class TestMessagesFaultyDriver(wsgi.TestMessagesFaultyDriver):
url_prefix = URL_PREFIX
class TestMessagesMongoDB(wsgi.TestMessagesMongoDB):
url_prefix = URL_PREFIX
class TestMessagesMongoDBSharded(wsgi.TestMessagesMongoDBSharded):
url_prefix = URL_PREFIX
class TestMessagesSQLite(wsgi.TestMessagesSQLite):
url_prefix = URL_PREFIX
class TestQueueFaultyDriver(wsgi.TestQueueFaultyDriver):
url_prefix = URL_PREFIX
class TestQueueLifecycleMongoDB(wsgi.TestQueueLifecycleMongoDB):
url_prefix = URL_PREFIX
class TestQueueLifecycleSQLite(wsgi.TestQueueLifecycleSQLite):
url_prefix = URL_PREFIX
class TestShardsMongoDB(wsgi.TestShardsMongoDB):
url_prefix = URL_PREFIX
#----------------------------------------------------------------------------
# v1.0 only
#----------------------------------------------------------------------------
class TestHealth(wsgi.TestBase):
config_file = 'wsgi_sqlite.conf'
def test_get(self):
response = self.simulate_get('/v1/health')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])
def test_head(self):
response = self.simulate_head('/v1/health')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])

View File

@ -0,0 +1,127 @@
# 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 falcon
from marconi.tests.queues.transport import wsgi
#----------------------------------------------------------------------------
# Identical or just minor variations across versions
#----------------------------------------------------------------------------
URL_PREFIX = '/v1.1'
class TestAuth(wsgi.TestAuth):
url_prefix = URL_PREFIX
class TestClaimsFaultyDriver(wsgi.TestClaimsFaultyDriver):
url_prefix = URL_PREFIX
class TestClaimsMongoDB(wsgi.TestClaimsMongoDB):
url_prefix = URL_PREFIX
class TestClaimsSQLite(wsgi.TestClaimsSQLite):
url_prefix = URL_PREFIX
class TestDefaultLimits(wsgi.TestDefaultLimits):
url_prefix = URL_PREFIX
class TestHomeDocument(wsgi.TestHomeDocument):
url_prefix = URL_PREFIX
class TestMediaType(wsgi.TestMediaType):
url_prefix = URL_PREFIX
class TestMessagesFaultyDriver(wsgi.TestMessagesFaultyDriver):
url_prefix = URL_PREFIX
class TestMessagesMongoDB(wsgi.TestMessagesMongoDB):
url_prefix = URL_PREFIX
class TestMessagesMongoDBSharded(wsgi.TestMessagesMongoDBSharded):
url_prefix = URL_PREFIX
class TestMessagesSQLite(wsgi.TestMessagesSQLite):
url_prefix = URL_PREFIX
class TestQueueFaultyDriver(wsgi.TestQueueFaultyDriver):
url_prefix = URL_PREFIX
# TODO(kgriffs): Having to list a separate test for each backend is
# sort of a pain; is there a better way?
class TestQueueLifecycleMongoDB(wsgi.TestQueueLifecycleMongoDB):
url_prefix = URL_PREFIX
class TestQueueLifecycleSQLite(wsgi.TestQueueLifecycleSQLite):
url_prefix = URL_PREFIX
class TestShardsMongoDB(wsgi.TestShardsMongoDB):
url_prefix = URL_PREFIX
#----------------------------------------------------------------------------
# v1.1 only
#----------------------------------------------------------------------------
class TestPing(wsgi.TestBase):
config_file = 'wsgi_sqlite.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(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])
def test_head(self):
response = self.simulate_head('/v1.1/ping')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])
class TestHealth(wsgi.TestBase):
config_file = 'wsgi_sqlite.conf'
def test_get(self):
response = self.simulate_get('/v1.1/health')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])
def test_head(self):
response = self.simulate_head('/v1.1/health')
self.assertEqual(self.srmock.status, falcon.HTTP_204)
self.assertEqual(response, [])

View File

@ -18,7 +18,7 @@ import uuid
import falcon
from . import base # noqa
from marconi.tests.queues.transport.wsgi import base
class ValidationTest(base.TestBase):
@ -29,6 +29,10 @@ class ValidationTest(base.TestBase):
super(ValidationTest, self).setUp()
self.project_id = '7e55e1a7e'
# NOTE(kgriffs): ATM, validation logic does not key off
# the API version. Therefore, we just pick '/v1' arbitrarily
# as the url prefix.
self.queue_path = '/v1/queues/noein'
self.simulate_put(self.queue_path, self.project_id)