Add support for using Falcon 2.0.0

Falcon 2.0.0 introduces some breaking changes. The relevant ones here are:

- falcon.testing.TestCase.api property was removed
- falcon.testing.TestBase class was removed

This commit also switches the project to use stestr, update sphinx dependency
and add lower-constraints job

Change-Id: I34255a603c069ed3b1e52017634ff01147473221
Story: 2005695
Task: 35688
This commit is contained in:
akhiljain23 2019-07-05 11:56:47 +05:30 committed by Akhil jain
parent 6647b88cbe
commit 8ec3b67b77
11 changed files with 99 additions and 81 deletions

View File

@ -1,9 +0,0 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
${PYTHON:-python} -m subunit.run discover $PWD $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list
group_regex=monasca_events_api\.tests\.unit(?:\.|_)([^_]+)

View File

@ -51,6 +51,7 @@
- project:
templates:
- openstack-cover-jobs
- openstack-lower-constraints-jobs
- openstack-python-jobs
- openstack-python36-jobs
- openstack-python37-jobs

28
lower-constraints.txt Normal file
View File

@ -0,0 +1,28 @@
bashate==0.2
coverage==4.0
doc8==0.6.0
eventlet==0.18.2
falcon==2.0.0
fixtures==3.0.0
keystonemiddleware==4.12.0
mock==2.0
monasca-common==1.4.0
openstackdocstheme==1.16.0
os-api-ref==1.0.0
oslo.config==6.1.0
oslo.context==2.14.0
oslo.log==3.22.0
oslo.middleware==3.27.0
oslo.policy==1.23.0
oslo.serialization==1.10.0
oslo.utils==3.20.0
oslotest==1.10.0
Paste==2.0.2
PasteDeploy==1.5.0
pbr==2.0.0
reno==2.5.0
simplejson==3.5.1
six==1.10.0
sphinx==1.6.2
stestr==1.0.0
voluptuous==0.8.9

View File

@ -17,7 +17,6 @@ import falcon
from oslo_log import log
from monasca_common.rest import exceptions
from monasca_common.rest import utils as rest_utils
LOG = log.getLogger(__name__)
@ -31,9 +30,7 @@ def read_json_msg_body(req):
:raises falcon.HTTPBadRequest:
"""
try:
msg = req.stream.read()
json_msg = rest_utils.from_json(msg)
return json_msg
return req.media
except exceptions.DataConversionException as ex:
LOG.debug(ex)
raise falcon.HTTPBadRequest('Bad request',

View File

@ -100,18 +100,12 @@ class PolicyFixture(fixtures.Fixture):
rules[rule.name] = rule.check_str
class MockedApi(falcon.API):
"""Mocked API.
class BaseApiTestCase(BaseTestCase, testing.TestCase):
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
)
class BaseApiTestCase(BaseTestCase, testing.TestBase):
api_class = MockedApi
def setUp(self):
super(BaseApiTestCase, self).setUp()
self.app = falcon.API(request_type=request.Request)
# NOTE: 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

View File

@ -27,7 +27,7 @@ ENDPOINT = '/events'
def _init_resource(test):
resource = events.Events()
test.api.add_route(ENDPOINT, resource)
test.app.add_route(ENDPOINT, resource)
return resource
@ -44,7 +44,7 @@ class TestEventsApi(base.BaseApiTestCase):
json_file_path)
with open(patch_to_req_simple_event_file, 'r') as fi:
body = fi.read()
self.simulate_request(
response = self.simulate_request(
path=ENDPOINT,
method='POST',
headers={
@ -53,7 +53,7 @@ class TestEventsApi(base.BaseApiTestCase):
},
body=body
)
self.assertEqual(falcon.HTTP_200, self.srmock.status)
self.assertEqual(falcon.HTTP_200, response.status)
def test_should_multiple_events(self, bulk_processor):
events_resource = _init_resource(self)
@ -64,7 +64,7 @@ class TestEventsApi(base.BaseApiTestCase):
json_file_path)
with open(req_multiple_events_json, 'r') as fi:
body = fi.read()
self.simulate_request(
response = self.simulate_request(
path=ENDPOINT,
method='POST',
headers={
@ -73,12 +73,12 @@ class TestEventsApi(base.BaseApiTestCase):
},
body=body
)
self.assertEqual(falcon.HTTP_200, self.srmock.status)
self.assertEqual(falcon.HTTP_200, response.status)
def test_should_fail_empty_body(self, bulk_processor):
events_resource = _init_resource(self)
events_resource._processor = bulk_processor
self.simulate_request(
response = self.simulate_request(
path=ENDPOINT,
method='POST',
headers={
@ -87,7 +87,7 @@ class TestEventsApi(base.BaseApiTestCase):
},
body=''
)
self.assertEqual(falcon.HTTP_400, self.srmock.status)
self.assertEqual(falcon.HTTP_422, response.status)
def test_should_fail_missing_timestamp_in_body(self, bulk_processor):
events_resource = _init_resource(self)
@ -99,7 +99,7 @@ class TestEventsApi(base.BaseApiTestCase):
with open(patch_to_req_simple_event_file, 'r') as fi:
events = json.load(fi)['events']
body = {'events': [events]}
self.simulate_request(
response = self.simulate_request(
path=ENDPOINT,
method='POST',
headers={
@ -108,13 +108,13 @@ class TestEventsApi(base.BaseApiTestCase):
},
body=json.dumps(body)
)
self.assertEqual(falcon.HTTP_422, self.srmock.status)
self.assertEqual(falcon.HTTP_422, response.status)
def test_should_fail_missing_events_in_body(self, bulk_processor):
events_resource = _init_resource(self)
events_resource._processor = bulk_processor
body = {'timestamp': '2012-10-29T13:42:11Z+0200'}
self.simulate_request(
response = self.simulate_request(
path=ENDPOINT,
method='POST',
headers={
@ -123,13 +123,13 @@ class TestEventsApi(base.BaseApiTestCase):
},
body=json.dumps(body)
)
self.assertEqual(falcon.HTTP_422, self.srmock.status)
self.assertEqual(falcon.HTTP_422, response.status)
def test_should_fail_missing_content_type(self, bulk_processor):
events_resource = _init_resource(self)
events_resource._processor = bulk_processor
body = {'timestamp': '2012-10-29T13:42:11Z+0200'}
self.simulate_request(
response = self.simulate_request(
path=ENDPOINT,
method='POST',
headers={
@ -137,13 +137,13 @@ class TestEventsApi(base.BaseApiTestCase):
},
body=json.dumps(body)
)
self.assertEqual(falcon.HTTP_400, self.srmock.status)
self.assertEqual(falcon.HTTP_400, response.status)
def test_should_fail_wrong_content_type(self, bulk_processor):
events_resource = _init_resource(self)
events_resource._processor = bulk_processor
body = {'timestamp': '2012-10-29T13:42:11Z+0200'}
self.simulate_request(
response = self.simulate_request(
path=ENDPOINT,
method='POST',
headers={
@ -152,7 +152,7 @@ class TestEventsApi(base.BaseApiTestCase):
},
body=json.dumps(body)
)
self.assertEqual(falcon.HTTP_415, self.srmock.status)
self.assertEqual(falcon.HTTP_415, response.status)
class TestApiEventsVersion(base.BaseApiTestCase):

View File

@ -14,7 +14,6 @@
import falcon
import mock
import ujson as json
from monasca_events_api.app.controller import healthchecks
from monasca_events_api.app.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_events_api.app.healthcheck.'
'kafka_check.KafkaHealthCheck')
@ -43,17 +45,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_events_api.app.healthcheck.'
'kafka_check.KafkaHealthCheck')
@ -64,14 +65,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'))

View File

@ -15,7 +15,6 @@
from six.moves.urllib.parse import urlparse as urlparse
import falcon
import ujson as json
from monasca_events_api.app.controller import versions
from monasca_events_api.tests.unit import base
@ -27,24 +26,25 @@ def _get_versioned_url(version_id):
class TestVersionApi(base.BaseApiTestCase):
def before(self):
def setUp(self):
super(TestVersionApi, 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_request_for_incorrect_version(self):
incorrect_version = 'v2.0'
uri = _get_versioned_url(incorrect_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_supported_event_api_version(self):
@ -80,15 +80,14 @@ class TestVersionApi(base.BaseApiTestCase):
for version in supported_versions:
endpoint = '%s/%s' % (version_endpoint, version)
res = self.simulate_request(
endpoint,
path=endpoint,
method='GET',
headers={
'Content-Type': 'application/json'
},
decode='utf-8'
}
)
self.assertEqual(falcon.HTTP_200, self.srmock.status)
response = json.loads(res)
self.assertEqual(falcon.HTTP_200, res.status)
response = res.json
self.assertIn('links', response)
_check_global_links(endpoint, response['links'])
self.assertIn('elements', response)

View File

@ -3,10 +3,10 @@
# process, which may cause wedges in the gate later.
pbr!=2.1.0,>=2.0.0 # Apache-2.0
Paste # MIT
falcon>=1.0.0 # Apache-2.0
Paste>=2.0.2 # MIT
falcon>=2.0.0 # Apache-2.0
keystonemiddleware>=4.12.0 # Apache-2.0
oslo.config!=4.3.0,!=4.4.0 # Apache-2.0
oslo.config>=6.1.0 # Apache-2.0
oslo.context>=2.14.0 # Apache-2.0
oslo.middleware>=3.27.0 # Apache-2.0
oslo.log>=3.22.0 # Apache-2.0

View File

@ -12,13 +12,14 @@ fixtures>=3.0.0 # Apache-2.0/BSD
coverage!=4.4,>=4.0 # Apache-2.0
mock>=2.0 # BSD
oslotest>=1.10.0 # Apache-2.0
os-testr>=0.8.0 # Apache-2.0
simplejson>=2.2.0 # MIT
simplejson>=3.5.1 # MIT
stestr>=1.0.0 # Apache-2.0
voluptuous>=0.8.9 # BSD License
# documentation
doc8 # Apache-2.0
sphinx>=1.6.2 # BSD
doc8>=0.6.0 # Apache-2.0
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.0.0 # Apache-2.0
reno # Apache-2.0
reno>=2.5.0 # Apache-2.0
openstackdocstheme>=1.16.0 # Apache-2.0

11
tox.ini
View File

@ -26,14 +26,14 @@ description = Runs unit test using Python2.7
basepython = python2.7
commands =
{[testenv]commands}
ostestr {posargs}
stestr run {posargs}
[testenv:py36]
description = Runs unit test using Python3.6
basepython = python3.6
commands =
{[testenv]commands}
ostestr {posargs}
stestr run {posargs}
[testenv:cover]
basepython = python3
@ -158,4 +158,11 @@ enable-extensions = H203,H106
ignore = D100,D104
import-order-style = pep8
[testenv:lower-constraints]
basepython = python3
deps =
-c{toxinidir}/lower-constraints.txt
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt
[hacking]