diff --git a/lower-constraints.txt b/lower-constraints.txt index 1056a2de..756cd78b 100644 --- a/lower-constraints.txt +++ b/lower-constraints.txt @@ -12,7 +12,7 @@ docutils==0.11 dulwich==0.15.0 eventlet==0.18.2 extras==1.0.0 -falcon==1.0.0 +falcon==2.0.0 fixtures==3.0.0 flake8==2.5.5 future==0.16.0 diff --git a/monasca_log_api/app/api.py b/monasca_log_api/app/api.py index 968a6591..6505d0bd 100644 --- a/monasca_log_api/app/api.py +++ b/monasca_log_api/app/api.py @@ -77,6 +77,7 @@ def create_version_app(global_conf, **local_conf): wsgi_app = falcon.API( request_type=request.Request ) + wsgi_app.req_options.strip_url_path_trailing_slash = True for route, ctrl in controllers.items(): wsgi_app.add_route(route, ctrl) return wsgi_app diff --git a/monasca_log_api/app/base/validation.py b/monasca_log_api/app/base/validation.py index 260215ea..872625e6 100644 --- a/monasca_log_api/app/base/validation.py +++ b/monasca_log_api/app/base/validation.py @@ -207,7 +207,7 @@ def validate_payload_size(req): ) if payload_size >= max_size: - raise falcon.HTTPRequestEntityTooLarge( + raise falcon.HTTPPayloadTooLarge( title='Log payload size exceeded', description='Maximum allowed size is %d bytes' % max_size ) diff --git a/monasca_log_api/app/controller/v2/aid/service.py b/monasca_log_api/app/controller/v2/aid/service.py index d2a393b6..29fd7786 100644 --- a/monasca_log_api/app/controller/v2/aid/service.py +++ b/monasca_log_api/app/controller/v2/aid/service.py @@ -15,7 +15,6 @@ import datetime -from monasca_common.rest import utils as rest_utils from oslo_config import cfg from oslo_log import log @@ -87,7 +86,6 @@ class LogCreator(object): :keyword: log_object """ - payload = rest_utils.read_body(payload, content_type) if not payload: return None diff --git a/monasca_log_api/app/controller/v2/logs.py b/monasca_log_api/app/controller/v2/logs.py index 90779e19..5dc59186 100644 --- a/monasca_log_api/app/controller/v2/logs.py +++ b/monasca_log_api/app/controller/v2/logs.py @@ -92,7 +92,7 @@ class Logs(logs_api.LogsApi): return self._log_creator.new_log( application_type=request.get_header(*headers.X_APPLICATION_TYPE), dimensions=request.get_header(*headers.X_DIMENSIONS), - payload=request.stream, + payload=request.media, content_type=request.content_type ) diff --git a/monasca_log_api/app/controller/v3/aid/helpers.py b/monasca_log_api/app/controller/v3/aid/helpers.py index 4c18e640..9b57e10d 100644 --- a/monasca_log_api/app/controller/v3/aid/helpers.py +++ b/monasca_log_api/app/controller/v3/aid/helpers.py @@ -33,9 +33,13 @@ def read_json_msg_body(req): :raises falcon.HTTPBadRequest: """ try: - msg = req.stream.read() - json_msg = rest_utils.from_json(msg) - return json_msg + body = req.media + + if body is not None: + return body + else: + raise falcon.HTTPBadRequest('Bad request', + 'Request body is Empty') except rest_utils.exceptions.DataConversionException as ex: LOG.debug(ex) diff --git a/monasca_log_api/tests/base.py b/monasca_log_api/tests/base.py index ed1ac4fe..dda8b46a 100644 --- a/monasca_log_api/tests/base.py +++ b/monasca_log_api/tests/base.py @@ -39,24 +39,6 @@ from monasca_log_api import policies policy.POLICIES = policies -class MockedAPI(falcon.API): - """MockedAPI - - Subclasses :py:class:`falcon.API` in order to overwrite - request_type property with custom :py:class:`request.Request` - - """ - - def __init__(self): - super(MockedAPI, self).__init__( - media_type=falcon.DEFAULT_MEDIA_TYPE, - request_type=request.Request, - response_type=falcon.Response, - middleware=None, - router=None - ) - - def generate_unique_message(size): letters = string.ascii_letters @@ -214,5 +196,12 @@ class BaseTestCase(oslotest_base.BaseTestCase): config.CONF.set_default(k, v, group) -class BaseApiTestCase(BaseTestCase, testing.TestBase): - api_class = MockedAPI +class BaseApiTestCase(BaseTestCase, testing.TestCase): + + def setUp(self): + super(BaseApiTestCase, self).setUp() + self.app = falcon.API(request_type=request.Request) + # NOTE(czarneckia): Falcon 2.0.0 switches the default for this from True + # to False so we explicitly set it here to prevent the behaviour + # changing between versions. + self.app.req_options.strip_url_path_trailing_slash = True diff --git a/monasca_log_api/tests/test_healthchecks.py b/monasca_log_api/tests/test_healthchecks.py index a982be18..9995f551 100644 --- a/monasca_log_api/tests/test_healthchecks.py +++ b/monasca_log_api/tests/test_healthchecks.py @@ -14,7 +14,6 @@ import falcon import mock -import simplejson as json from monasca_log_api.app.controller import healthchecks from monasca_log_api.healthcheck import kafka_check as healthcheck @@ -25,16 +24,19 @@ ENDPOINT = '/healthcheck' class TestApiHealthChecks(base.BaseApiTestCase): - def before(self): + def setUp(self): + super(TestApiHealthChecks, self).setUp() self.resource = healthchecks.HealthChecks() - self.api.add_route( + self.app.add_route( ENDPOINT, self.resource ) def test_should_return_200_for_head(self): - self.simulate_request(ENDPOINT, method='HEAD') - self.assertEqual(falcon.HTTP_NO_CONTENT, self.srmock.status) + res = self.simulate_request( + path=ENDPOINT, + method='HEAD') + self.assertEqual(falcon.HTTP_NO_CONTENT, res.status) @mock.patch('monasca_log_api.healthcheck.kafka_check.KafkaHealthCheck') def test_should_report_healthy_if_kafka_healthy(self, kafka_check): @@ -42,17 +44,16 @@ class TestApiHealthChecks(base.BaseApiTestCase): 'OK') self.resource._kafka_check = kafka_check - ret = self.simulate_request(ENDPOINT, + res = self.simulate_request(path=ENDPOINT, headers={ 'Content-Type': 'application/json' }, - decode='utf8', method='GET') - self.assertEqual(falcon.HTTP_OK, self.srmock.status) + self.assertEqual(falcon.HTTP_OK, res.status) - ret = json.loads(ret) - self.assertIn('kafka', ret) - self.assertEqual('OK', ret.get('kafka')) + res = res.json + self.assertIn('kafka', res) + self.assertEqual('OK', res.get('kafka')) @mock.patch('monasca_log_api.healthcheck.kafka_check.KafkaHealthCheck') def test_should_report_unhealthy_if_kafka_healthy(self, kafka_check): @@ -62,14 +63,13 @@ class TestApiHealthChecks(base.BaseApiTestCase): err_str) self.resource._kafka_check = kafka_check - ret = self.simulate_request(ENDPOINT, + res = self.simulate_request(path=ENDPOINT, headers={ 'Content-Type': 'application/json' }, - decode='utf8', method='GET') - self.assertEqual(falcon.HTTP_SERVICE_UNAVAILABLE, self.srmock.status) + self.assertEqual(falcon.HTTP_SERVICE_UNAVAILABLE, res.status) - ret = json.loads(ret) - self.assertIn('kafka', ret) - self.assertEqual(err_str, ret.get('kafka')) + res = res.json + self.assertIn('kafka', res) + self.assertEqual(err_str, res.get('kafka')) diff --git a/monasca_log_api/tests/test_logs.py b/monasca_log_api/tests/test_logs.py index 5114f4b2..11808b22 100644 --- a/monasca_log_api/tests/test_logs.py +++ b/monasca_log_api/tests/test_logs.py @@ -15,6 +15,7 @@ import falcon import mock +import ujson from monasca_log_api.app.base import exceptions as log_api_exceptions from monasca_log_api.app.controller.api import headers @@ -26,7 +27,7 @@ ROLES = 'admin' def _init_resource(test): resource = logs.Logs() - test.api.add_route('/log/single', resource) + test.app.add_route('/log/single', resource) return resource @@ -47,8 +48,8 @@ class TestApiLogs(base.BaseApiTestCase): __): _init_resource(self) - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -58,16 +59,16 @@ class TestApiLogs(base.BaseApiTestCase): } ) - self.assertEqual(falcon.HTTP_204, self.srmock.status) - self.assertIn('deprecated', self.srmock.headers_dict) - self.assertIn('link', self.srmock.headers_dict) + self.assertEqual(falcon.HTTP_204, res.status) + self.assertIn('deprecated', res.headers) + self.assertIn('link', res.headers) @mock.patch('monasca_log_api.app.base.log_publisher.LogPublisher') @mock.patch('monasca_log_api.app.controller.v2.aid.service.LogCreator') def test_should_fail_not_delegate_ok_cross_tenant_id(self, _, __): _init_resource(self) - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', query_string='tenant_id=1', headers={ @@ -75,7 +76,7 @@ class TestApiLogs(base.BaseApiTestCase): 'Content-Length': '0' } ) - self.assertEqual(falcon.HTTP_401, self.srmock.status) + self.assertEqual(falcon.HTTP_401, res.status) @mock.patch('monasca_log_api.app.controller.v2.aid.service.LogCreator') @mock.patch('monasca_log_api.app.base.log_publisher.LogPublisher') @@ -86,8 +87,8 @@ class TestApiLogs(base.BaseApiTestCase): logs_resource._log_creator = log_creator logs_resource._kafka_publisher = kafka_publisher - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -96,7 +97,7 @@ class TestApiLogs(base.BaseApiTestCase): 'Content-Length': '0' } ) - self.assertEqual(falcon.HTTP_204, self.srmock.status) + self.assertEqual(falcon.HTTP_204, res.status) self.assertEqual(1, kafka_publisher.send_message.call_count) self.assertEqual(1, log_creator.new_log.call_count) @@ -111,8 +112,8 @@ class TestApiLogs(base.BaseApiTestCase): logs_resource._log_creator = log_creator logs_resource._kafka_publisher = kafka_publisher - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -121,7 +122,7 @@ class TestApiLogs(base.BaseApiTestCase): 'Content-Length': '0' } ) - self.assertEqual(falcon.HTTP_204, self.srmock.status) + self.assertEqual(falcon.HTTP_204, res.status) self.assertEqual(1, kafka_publisher.send_message.call_count) self.assertEqual(1, log_creator.new_log.call_count) @@ -136,8 +137,8 @@ class TestApiLogs(base.BaseApiTestCase): resource._log_creator = log_creator resource._kafka_publisher = log_publisher - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', query_string='tenant_id=1', headers={ @@ -147,7 +148,7 @@ class TestApiLogs(base.BaseApiTestCase): 'Content-Length': '0' } ) - self.assertEqual(falcon.HTTP_204, self.srmock.status) + self.assertEqual(falcon.HTTP_204, res.status) self.assertEqual(1, log_publisher.send_message.call_count) self.assertEqual(1, log_creator.new_log.call_count) @@ -159,26 +160,25 @@ class TestApiLogs(base.BaseApiTestCase): _init_resource(self) rest_utils.read_body.return_value = True - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', headers={ headers.X_ROLES.name: ROLES, headers.X_DIMENSIONS.name: '', 'Content-Type': 'application/json', - 'Content-Length': '0' }, body='{"message":"test"}' ) - self.assertEqual(log_api_exceptions.HTTP_422, self.srmock.status) + self.assertEqual(log_api_exceptions.HTTP_422, res.status) @mock.patch('monasca_log_api.app.controller.v2.aid.service.LogCreator') @mock.patch('monasca_log_api.app.base.log_publisher.LogPublisher') def test_should_fail_for_invalid_content_type(self, _, __): _init_resource(self) - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -187,7 +187,7 @@ class TestApiLogs(base.BaseApiTestCase): 'Content-Length': '0' } ) - self.assertEqual(falcon.HTTP_415, self.srmock.status) + self.assertEqual(falcon.HTTP_415, res.status) @mock.patch('monasca_log_api.app.controller.v2.aid.service.LogCreator') @mock.patch('monasca_log_api.app.base.log_publisher.LogPublisher') @@ -195,20 +195,25 @@ class TestApiLogs(base.BaseApiTestCase): _init_resource(self) max_log_size = 1000 - content_length = max_log_size - 100 + body = ujson.dumps({ + 'message': 't' * (max_log_size - 100) + }) + + content_length = len(body) self.conf_override(max_log_size=max_log_size, group='service') - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', headers={ headers.X_ROLES.name: ROLES, headers.X_DIMENSIONS.name: '', 'Content-Type': 'application/json', 'Content-Length': str(content_length) - } + }, + body=body ) - self.assertEqual(falcon.HTTP_204, self.srmock.status) + self.assertEqual(falcon.HTTP_204, res.status) @mock.patch('monasca_log_api.app.controller.v2.aid.service.LogCreator') @mock.patch('monasca_log_api.app.base.log_publisher.LogPublisher') @@ -219,8 +224,8 @@ class TestApiLogs(base.BaseApiTestCase): content_length = max_log_size + 100 self.conf_override(max_log_size=max_log_size, group='service') - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -229,7 +234,7 @@ class TestApiLogs(base.BaseApiTestCase): 'Content-Length': str(content_length) } ) - self.assertEqual(falcon.HTTP_413, self.srmock.status) + self.assertEqual(falcon.HTTP_413, res.status) @mock.patch('monasca_log_api.app.controller.v2.aid.service.LogCreator') @mock.patch('monasca_log_api.app.base.log_publisher.LogPublisher') @@ -240,8 +245,8 @@ class TestApiLogs(base.BaseApiTestCase): content_length = max_log_size self.conf_override(max_log_size=max_log_size, group='service') - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -250,15 +255,15 @@ class TestApiLogs(base.BaseApiTestCase): 'Content-Length': str(content_length) } ) - self.assertEqual(falcon.HTTP_413, self.srmock.status) + self.assertEqual(falcon.HTTP_413, res.status) @mock.patch('monasca_log_api.app.controller.v2.aid.service.LogCreator') @mock.patch('monasca_log_api.app.base.log_publisher.LogPublisher') def test_should_fail_content_length(self, _, __): _init_resource(self) - self.simulate_request( - '/log/single', + res = self.simulate_request( + path='/log/single', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -266,4 +271,4 @@ class TestApiLogs(base.BaseApiTestCase): 'Content-Type': 'application/json' } ) - self.assertEqual(falcon.HTTP_411, self.srmock.status) + self.assertEqual(falcon.HTTP_411, res.status) diff --git a/monasca_log_api/tests/test_logs_v3.py b/monasca_log_api/tests/test_logs_v3.py index 83be9213..6d5cd7b2 100644 --- a/monasca_log_api/tests/test_logs_v3.py +++ b/monasca_log_api/tests/test_logs_v3.py @@ -14,6 +14,7 @@ import falcon import mock +from six import PY3 import ujson as json from monasca_log_api.app.base import exceptions as log_api_exceptions @@ -28,7 +29,7 @@ ROLES = 'admin' def _init_resource(test): resource = logs.Logs() - test.api.add_route(ENDPOINT, resource) + test.app.add_route(ENDPOINT, resource) return resource @@ -92,7 +93,7 @@ class TestApiLogsMonitoring(base.BaseApiTestCase): content_length = len(payload) self.simulate_request( - ENDPOINT, + path=ENDPOINT, method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -128,7 +129,7 @@ class TestApiLogsMonitoring(base.BaseApiTestCase): res._processor._get_dimensions = mock.Mock(side_effect=side_effects) self.simulate_request( - ENDPOINT, + path=ENDPOINT, method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -172,7 +173,7 @@ class TestApiLogsMonitoring(base.BaseApiTestCase): payload = json.dumps(v3_body) content_length = len(payload) self.simulate_request( - ENDPOINT, + path=ENDPOINT, method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -211,8 +212,8 @@ class TestApiLogs(base.BaseApiTestCase): v3_body, v3_logs = _generate_v3_payload(1) payload = json.dumps(v3_body) content_length = len(payload) - self.simulate_request( - '/logs', + res = self.simulate_request( + path='/logs', method='POST', query_string='tenant_id=1', headers={ @@ -222,7 +223,7 @@ class TestApiLogs(base.BaseApiTestCase): }, body=payload ) - self.assertEqual(falcon.HTTP_204, self.srmock.status) + self.assertEqual(falcon.HTTP_204, res.status) logs_resource._processor.send_message.assert_called_with( logs=v3_logs, global_dimensions=v3_body['dimensions'], @@ -232,8 +233,8 @@ class TestApiLogs(base.BaseApiTestCase): 'BulkProcessor') def test_should_fail_not_delegate_ok_cross_tenant_id(self, _): _init_resource(self) - self.simulate_request( - '/logs', + res = self.simulate_request( + path='/logs', method='POST', query_string='tenant_id=1', headers={ @@ -242,7 +243,7 @@ class TestApiLogs(base.BaseApiTestCase): 'Content-Length': '0' } ) - self.assertEqual(falcon.HTTP_400, self.srmock.status) + self.assertEqual(falcon.HTTP_400, res.status) @mock.patch('monasca_log_api.app.controller.v3.aid.bulk_processor.' 'BulkProcessor') @@ -254,8 +255,8 @@ class TestApiLogs(base.BaseApiTestCase): v3_body, _ = _generate_v3_payload(1) payload = json.dumps(v3_body) content_length = len(payload) - self.simulate_request( - '/logs', + res = self.simulate_request( + path='/logs', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -264,7 +265,7 @@ class TestApiLogs(base.BaseApiTestCase): }, body=payload ) - self.assertEqual(falcon.HTTP_204, self.srmock.status) + self.assertEqual(falcon.HTTP_204, res.status) self.assertEqual(1, bulk_processor.send_message.call_count) @mock.patch('monasca_log_api.app.controller.v3.aid.bulk_processor.' @@ -277,8 +278,8 @@ class TestApiLogs(base.BaseApiTestCase): v3_body, _ = _generate_v3_payload(1) payload = json.dumps(v3_body) content_length = len(payload) - self.simulate_request( - '/logs', + res = self.simulate_request( + path='/logs', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -287,7 +288,7 @@ class TestApiLogs(base.BaseApiTestCase): }, body=payload ) - self.assertEqual(falcon.HTTP_204, self.srmock.status) + self.assertEqual(falcon.HTTP_204, res.status) self.assertEqual(1, bulk_processor.send_message.call_count) @@ -301,9 +302,9 @@ class TestUnicodeLogs(base.BaseApiTestCase): messages = [m['input'] for m in base.UNICODE_MESSAGES] v3_body, _ = _generate_v3_payload(messages=messages) payload = json.dumps(v3_body, ensure_ascii=False) - content_length = len(payload) - self.simulate_request( - '/logs', + content_length = len(payload.encode('utf8') if PY3 else payload) + res = self.simulate_request( + path='/logs', method='POST', headers={ headers.X_ROLES.name: ROLES, @@ -312,4 +313,4 @@ class TestUnicodeLogs(base.BaseApiTestCase): }, body=payload ) - self.assertEqual(falcon.HTTP_204, self.srmock.status) + self.assertEqual(falcon.HTTP_204, res.status) diff --git a/monasca_log_api/tests/test_service.py b/monasca_log_api/tests/test_service.py index 7c911a9b..d5dcd6c8 100644 --- a/monasca_log_api/tests/test_service.py +++ b/monasca_log_api/tests/test_service.py @@ -304,7 +304,7 @@ class PayloadSizeValidations(base.BaseTestCase): req.content_length = content_length self.assertRaises( - errors.HTTPRequestEntityTooLarge, + errors.HTTPPayloadTooLarge, validation.validate_payload_size, req ) @@ -319,7 +319,7 @@ class PayloadSizeValidations(base.BaseTestCase): req.content_length = content_length self.assertRaises( - errors.HTTPRequestEntityTooLarge, + errors.HTTPPayloadTooLarge, validation.validate_payload_size, req ) @@ -357,14 +357,13 @@ class LogsCreatorNewLog(base.BaseTestCase): super(LogsCreatorNewLog, self).setUp() self.instance = aid_service.LogCreator() - @mock.patch('io.IOBase') - def test_should_create_log_from_json(self, payload): + def test_should_create_log_from_json(self): msg = u'Hello World' path = u'/var/log/messages' - json_msg = u'{"path":"%s","message":"%s"}' % (path, msg) + payload = {"path": path, + "message": msg} app_type = 'monasca' dimensions = 'cpu_time:30' - payload.read.return_value = json_msg expected_log = { 'message': msg, @@ -381,14 +380,12 @@ class LogsCreatorNewLog(base.BaseTestCase): payload=payload )) - @mock.patch('io.IOBase') - def test_should_create_log_from_text(self, payload): + def test_should_create_log_from_text(self): msg = u'Hello World' app_type = 'monasca' dimension_name = 'cpu_time' dimension_value = 30 dimensions = '%s:%s' % (dimension_name, str(dimension_value)) - payload.read.return_value = msg expected_log = { 'message': msg, @@ -401,7 +398,7 @@ class LogsCreatorNewLog(base.BaseTestCase): self.assertEqual(expected_log, self.instance.new_log( application_type=app_type, dimensions=dimensions, - payload=payload, + payload=msg, content_type='text/plain' )) diff --git a/monasca_log_api/tests/test_v2_v3_compare.py b/monasca_log_api/tests/test_v2_v3_compare.py index 87972ca4..8a542737 100644 --- a/monasca_log_api/tests/test_v2_v3_compare.py +++ b/monasca_log_api/tests/test_v2_v3_compare.py @@ -66,11 +66,11 @@ class TestApiSameV2V3Output(base.BaseApiTestCase): ] } - self.api.add_route('/v2.0', v2) - self.api.add_route('/v3.0', v3) + self.app.add_route('/v2.0', v2) + self.app.add_route('/v3.0', v3) self.simulate_request( - '/v2.0', + path='/v2.0', method='POST', headers={ headers.X_ROLES.name: roles, @@ -78,19 +78,17 @@ class TestApiSameV2V3Output(base.BaseApiTestCase): headers.X_APPLICATION_TYPE.name: component, headers.X_TENANT_ID.name: tenant_id, 'Content-Type': 'application/json', - 'Content-Length': '100' }, body=json.dumps(v2_body) ) self.simulate_request( - '/v3.0', + path='/v3.0', method='POST', headers={ headers.X_ROLES.name: roles, headers.X_TENANT_ID.name: tenant_id, 'Content-Type': 'application/json', - 'Content-Length': '100' }, body=json.dumps(v3_body) ) diff --git a/monasca_log_api/tests/test_versions.py b/monasca_log_api/tests/test_versions.py index 25a0b48a..89a1976e 100644 --- a/monasca_log_api/tests/test_versions.py +++ b/monasca_log_api/tests/test_versions.py @@ -13,7 +13,6 @@ # under the License. import falcon -import ujson as json from monasca_log_api.app.controller import versions from monasca_log_api.tests import base @@ -25,24 +24,25 @@ def _get_versioned_url(version_id): class TestApiVersions(base.BaseApiTestCase): - def before(self): + def setUp(self): + super(TestApiVersions, self).setUp() self.versions = versions.Versions() - self.api.add_route("/version/", self.versions) - self.api.add_route("/version/{version_id}", self.versions) + self.app.add_route("/version/", self.versions) + self.app.add_route("/version/{version_id}", self.versions) def test_should_fail_for_unsupported_version(self): unsupported_version = 'v5.0' uri = _get_versioned_url(unsupported_version) - self.simulate_request( - uri, + res = self.simulate_request( + path=uri, method='GET', headers={ 'Content-Type': 'application/json' } ) - self.assertEqual(falcon.HTTP_400, self.srmock.status) + self.assertEqual(falcon.HTTP_400, res.status) def test_should_return_all_supported_versions(self): @@ -78,16 +78,15 @@ class TestApiVersions(base.BaseApiTestCase): expected_links_keys = 'self', 'version', 'healthcheck' res = self.simulate_request( - '/version', + path='/version', method='GET', headers={ 'Content-Type': 'application/json' - }, - decode='utf-8' + } ) - self.assertEqual(falcon.HTTP_200, self.srmock.status) + self.assertEqual(falcon.HTTP_200, res.status) - response = json.loads(res) + response = res.json _check_elements() _check_global_links() @@ -97,16 +96,15 @@ class TestApiVersions(base.BaseApiTestCase): for expected_version in expected_versions: uri = _get_versioned_url(expected_version) res = self.simulate_request( - uri, + path=uri, method='GET', headers={ 'Content-Type': 'application/json' }, - decode='utf-8' ) - self.assertEqual(falcon.HTTP_200, self.srmock.status) + self.assertEqual(falcon.HTTP_200, res.status) - response = json.loads(res) + response = res.json self.assertIn('elements', response) self.assertIn('links', response) diff --git a/requirements.txt b/requirements.txt index 5fb44c26..ef15ae52 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ pbr!=2.1.0,>=2.0.0 # Apache-2.0 Paste>=2.0.2 # MIT -falcon>=1.0.0 # Apache-2.0 +falcon>=2.0.0 # Apache-2.0 keystonemiddleware>=4.17.0 # Apache-2.0 oslo.config>=5.2.0 # Apache-2.0 oslo.context>=2.19.2 # Apache-2.0 diff --git a/test-requirements.txt b/test-requirements.txt index c9af6856..eeb0200b 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,7 +4,7 @@ # Install bounded pep8/pyflakes first, then let flake8 install hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 -bandit>=1.1.0 # Apache-2.0 +bandit!=1.6.0,>=1.1.0 # Apache-2.0 bashate>=0.5.1 # Apache-2.0 fixtures>=3.0.0 # Apache-2.0/BSD @@ -16,7 +16,8 @@ simplejson>=3.5.1 # MIT # documentation doc8>=0.6.0 # Apache-2.0 -sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD +sphinx!=1.6.6,!=1.6.7,>=1.6.2,<2.0.0;python_version=='2.7' # BSD +sphinx!=1.6.6,!=1.6.7,>=1.6.2;python_version>='3.4' # BSD os-api-ref>=1.4.0 # Apache-2.0 reno>=2.5.0 # Apache-2.0 openstackdocstheme>=1.18.1 # Apache-2.0