Skip to content

Commit

Permalink
test(asgi): Improve coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
kgriffs committed Dec 10, 2019
1 parent 5627a36 commit cccdbd1
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 14 deletions.
5 changes: 5 additions & 0 deletions falcon/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ def process_response(self, req, resp, resource, req_succeeded)

_STATIC_ROUTE_TYPE = routing.StaticRoute

# NOTE(kgriffs): This makes it easier to tell what we are dealing with
# without having to import falcon.asgi to get at the falcon.asgi.App
# type (which we may not be able to do under Python 3.5).
_ASGI = False

__slots__ = ('_request_type', '_response_type',
'_error_handlers', '_router', '_sinks',
'_serialize_error', 'req_options', 'resp_options',
Expand Down
5 changes: 5 additions & 0 deletions falcon/asgi/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ class App(falcon.app.App):

_STATIC_ROUTE_TYPE = falcon.routing.StaticRouteAsync

# NOTE(kgriffs): This makes it easier to tell what we are dealing with
# without having to import falcon.asgi to get at the falcon.asgi.App
# type (which we may not be able to do under Python 3.5).
_ASGI = True

__slots__ = ['_lifespan_handlers']

def __init__(self, *args, request_type=Request, response_type=Response, **kwargs):
Expand Down
9 changes: 8 additions & 1 deletion falcon/asgi/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,14 @@ def get_header(self, name, required=False, default=None):
raise errors.HTTPMissingHeader(name)

def log_error(self, message):
raise NotImplementedError("ASGI does not support writing to the server's log")
# NOTE(kgriffs): Normally the pythonic thing to do would be to simply
# set this method to None so that it can't even be called, but we
# raise an error here to help people who are porting from WSGI.
raise NotImplementedError(
"ASGI does not support writing to the server's log. "
'Please use the standard library logging framework '
'instead.'
)

# ------------------------------------------------------------------------
# Private Helpers
Expand Down
2 changes: 1 addition & 1 deletion requirements/tests
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ ujson
python-rapidjson

# TODO(kgriffs): orjson is failing to build on Travis
# orjson; platform_python_implementation != 'PyPy'
orjson; platform_python_implementation != 'PyPy'
5 changes: 0 additions & 5 deletions tests/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@ def create_app(asgi, **app_kwargs):

app = App(**app_kwargs)

# NOTE(kgriffs): This makes it easier to tell what we are dealing with
# without having to import falcon.asgi to get at the falcon.asgi.App
# type (which we may not be able to do under Python 3.5).
app.is_asgi = asgi

return app


Expand Down
8 changes: 8 additions & 0 deletions tests/asgi/test_request_asgi.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import pytest

from falcon import testing


def test_missing_server_in_scope():
req = testing.create_asgi_req(include_server=False, http_version='1.0')
assert req.host == 'localhost'
assert req.port == 80


def test_log_error_not_supported():
req = testing.create_asgi_req()
with pytest.raises(NotImplementedError):
req.log_error('Boink')
2 changes: 1 addition & 1 deletion tests/asgi/test_scheduled_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ async def background_job_async():

# NOTE(kgriffs): Remove default handlers so that we can check the raised
# exception is what we expecte.
app._error_handlers = []
app._error_handlers.clear()
with pytest.raises(TypeError) as exinfo:
client.simulate_put()

Expand Down
4 changes: 2 additions & 2 deletions tests/test_cmd_print_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ def test_traverse_with_verbose(app):
# any number if this becomes too painful to maintain.

assert (
get_info.endswith('tests/test_cmd_print_api.py:20') or
get_info.endswith('tests/test_cmd_print_api.py:27')
get_info.endswith('tests/test_cmd_print_api.py:19') or
get_info.endswith('tests/test_cmd_print_api.py:26')
)


Expand Down
4 changes: 2 additions & 2 deletions tests/test_http_custom_method_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def test_foo(custom_http_client, resource_things):
def s():
return custom_http_client.simulate_request(path='/things', method='FOO')

if not custom_http_client.app.is_asgi:
if not custom_http_client.app._ASGI:
with pytest.warns(wsgiref.validate.WSGIWarning):
response = s()
else:
Expand All @@ -117,7 +117,7 @@ def test_bar(custom_http_client, resource_things):
def s():
return custom_http_client.simulate_request(path='/things', method='BAR')

if not custom_http_client.app.is_asgi:
if not custom_http_client.app._ASGI:
with pytest.warns(wsgiref.validate.WSGIWarning):
response = s()
else:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_httperror.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ def s():
return client.simulate_request(path=path, method=method)

if method not in falcon.COMBINED_METHODS:
if not client.app.is_asgi:
if not client.app._ASGI:
with pytest.warns(wsgiref.validate.WSGIWarning):
resp = s()
else:
Expand Down
43 changes: 42 additions & 1 deletion tests/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,48 @@ def process_request(self, req, resp):
assert 'start_time' in context
assert 'mid_time' not in context

# NOTE(kgriffs): Shold not have been added since raising an
# NOTE(kgriffs): Should not have been added since raising an
# unhandled error skips further processing, including response
# middleware methods.
assert 'end_time' not in context

def test_inner_mw_throw_exception_while_processing_resp(self, asgi):
"""Test that error in inner middleware leaves"""
global context

class MyException(Exception):
pass

class RaiseErrorMiddleware:

def process_response(self, req, resp, resource, req_succeeded):
raise MyException('Always fail')

app = create_app(asgi, middleware=[TransactionIdMiddleware(),
RequestTimeMiddleware(),
RaiseErrorMiddleware()])

# NOTE(kgriffs): Now that we install a default handler for
# Exception, we have to clear them to test the path we want
# to trigger with RaiseErrorMiddleware
# TODO(kgriffs): Since we always add a default error handler
# for Exception, should we take out the checks in the WSGI/ASGI
# callable and just always assume it will be handled? If so,
# then we would remove the test here...
app._error_handlers.clear()

app.add_route(TEST_ROUTE, MiddlewareClassResource())
client = testing.TestClient(app)

with pytest.raises(MyException):
client.simulate_request(path=TEST_ROUTE)

# RequestTimeMiddleware process_response should be executed
assert 'transaction_id' in context
assert 'start_time' in context
assert 'mid_time' in context

# NOTE(kgriffs): Should not have been added since raising an
# unhandled error skips further processing, including response
# middleware methods.
assert 'end_time' not in context
Expand Down

0 comments on commit cccdbd1

Please sign in to comment.