sanic/tests/test_exceptions.py
2017-07-21 01:54:45 -07:00

192 lines
5.9 KiB
Python

import pytest
from bs4 import BeautifulSoup
from sanic import Sanic
from sanic.response import text
from sanic.exceptions import InvalidUsage, ServerError, NotFound, Unauthorized
from sanic.exceptions import Forbidden, abort
class SanicExceptionTestException(Exception):
pass
@pytest.fixture(scope='module')
def exception_app():
app = Sanic('test_exceptions')
@app.route('/')
def handler(request):
return text('OK')
@app.route('/error')
def handler_error(request):
raise ServerError("OK")
@app.route('/404')
def handler_404(request):
raise NotFound("OK")
@app.route('/403')
def handler_403(request):
raise Forbidden("Forbidden")
@app.route('/401/basic')
def handler_401_basic(request):
raise Unauthorized("Unauthorized", "Basic", {"realm": "Sanic"})
@app.route('/401/digest')
def handler_401_digest(request):
challenge = {
"realm": "Sanic",
"qop": "auth, auth-int",
"algorithm": "MD5",
"nonce": "abcdef",
"opaque": "zyxwvu",
}
raise Unauthorized("Unauthorized", "Digest", challenge)
@app.route('/401/bearer')
def handler_401_bearer(request):
raise Unauthorized("Unauthorized", "Bearer")
@app.route('/invalid')
def handler_invalid(request):
raise InvalidUsage("OK")
@app.route('/abort')
def handler_invalid(request):
abort(500)
return text("OK")
@app.route('/divide_by_zero')
def handle_unhandled_exception(request):
1 / 0
@app.route('/error_in_error_handler_handler')
def custom_error_handler(request):
raise SanicExceptionTestException('Dummy message!')
@app.exception(SanicExceptionTestException)
def error_in_error_handler_handler(request, exception):
1 / 0
return app
def test_catch_exception_list():
app = Sanic('exception_list')
@app.exception([SanicExceptionTestException, NotFound])
def exception_list(request, exception):
return text("ok")
@app.route('/')
def exception(request):
raise SanicExceptionTestException("You won't see me")
request, response = app.test_client.get('/random')
assert response.text == 'ok'
request, response = app.test_client.get('/')
assert response.text == 'ok'
def test_no_exception(exception_app):
"""Test that a route works without an exception"""
request, response = exception_app.test_client.get('/')
assert response.status == 200
assert response.text == 'OK'
def test_server_error_exception(exception_app):
"""Test the built-in ServerError exception works"""
request, response = exception_app.test_client.get('/error')
assert response.status == 500
def test_invalid_usage_exception(exception_app):
"""Test the built-in InvalidUsage exception works"""
request, response = exception_app.test_client.get('/invalid')
assert response.status == 400
def test_not_found_exception(exception_app):
"""Test the built-in NotFound exception works"""
request, response = exception_app.test_client.get('/404')
assert response.status == 404
def test_forbidden_exception(exception_app):
"""Test the built-in Forbidden exception"""
request, response = exception_app.test_client.get('/403')
assert response.status == 403
def test_unauthorized_exception(exception_app):
"""Test the built-in Unauthorized exception"""
request, response = exception_app.test_client.get('/401/basic')
assert response.status == 401
assert response.headers.get('WWW-Authenticate') is not None
assert response.headers.get('WWW-Authenticate') == "Basic realm='Sanic'"
request, response = exception_app.test_client.get('/401/digest')
assert response.status == 401
auth_header = response.headers.get('WWW-Authenticate')
assert auth_header is not None
assert auth_header.startswith('Digest')
assert "qop='auth, auth-int'" in auth_header
assert "algorithm='MD5'" in auth_header
assert "nonce='abcdef'" in auth_header
assert "opaque='zyxwvu'" in auth_header
request, response = exception_app.test_client.get('/401/bearer')
assert response.status == 401
assert response.headers.get('WWW-Authenticate') == "Bearer"
def test_handled_unhandled_exception(exception_app):
"""Test that an exception not built into sanic is handled"""
request, response = exception_app.test_client.get('/divide_by_zero')
assert response.status == 500
soup = BeautifulSoup(response.body, 'html.parser')
assert soup.h1.text == 'Internal Server Error'
message = " ".join(soup.p.text.split())
assert message == (
"The server encountered an internal error and "
"cannot complete your request.")
def test_exception_in_exception_handler(exception_app):
"""Test that an exception thrown in an error handler is handled"""
request, response = exception_app.test_client.get(
'/error_in_error_handler_handler')
assert response.status == 500
assert response.body == b'An error occurred while handling an error'
def test_exception_in_exception_handler_debug_off(exception_app):
"""Test that an exception thrown in an error handler is handled"""
request, response = exception_app.test_client.get(
'/error_in_error_handler_handler',
debug=False)
assert response.status == 500
assert response.body == b'An error occurred while handling an error'
def test_exception_in_exception_handler_debug_off(exception_app):
"""Test that an exception thrown in an error handler is handled"""
request, response = exception_app.test_client.get(
'/error_in_error_handler_handler',
debug=True)
assert response.status == 500
assert response.body.startswith(b'Exception raised in exception ')
def test_abort(exception_app):
"""Test the abort function"""
request, response = exception_app.test_client.get('/abort')
assert response.status == 500