Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix async tests #1558

Merged
merged 2 commits into from
Jun 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion connexion/security/security_handler_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,12 @@ def verify_multiple_schemes(self, schemes):
:rtype: types.FunctionType
"""

def wrapper(request):
async def wrapper(request):
token_info = {}
for scheme_name, func in schemes.items():
result = func(request)
while asyncio.iscoroutine(result):
result = await result
if result is self.no_value:
return self.no_value
token_info[scheme_name] = result
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def read_version(package):

tests_require = [
'pytest>=6,<7',
'pytest-asyncio>=0.18,<0.19',
'pre-commit>=2,<3',
'pytest-cov>=2,<3',
*flask_require,
Expand All @@ -57,7 +58,7 @@ class PyTest(TestCommand):
def initialize_options(self):
TestCommand.initialize_options(self)
self.cov = None
self.pytest_args = ['--cov', 'connexion', '--cov-report', 'term-missing', '-v']
self.pytest_args = ['--cov', 'connexion', '--cov-report', 'term-missing', '-v', "--asyncio-mode", "auto"]
self.cov_html = False

def finalize_options(self):
Expand Down
40 changes: 27 additions & 13 deletions tests/decorators/test_security.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
import json
from unittest.mock import MagicMock

Expand Down Expand Up @@ -63,16 +64,22 @@ async def get_tokeninfo_response(*args, **kwargs):
client.get = get_tokeninfo_response
monkeypatch.setattr(SecurityHandlerFactory, 'client', client)

with pytest.raises(OAuthScopeProblem, match="Provided token doesn't have the required scope"):
with pytest.raises(OAuthScopeProblem) as exc_info:
await wrapped_func(request)

assert exc_info.value.status_code == 403
assert exc_info.value.detail == "Provided token doesn't have the required scope"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is because we are now subclassing connexion exceptions from starlette now, which have a different str representation


tokeninfo["scope"] += " admin"
assert await wrapped_func(request) is not None

tokeninfo["scope"] = ["foo", "bar"]
with pytest.raises(OAuthScopeProblem, match="Provided token doesn't have the required scope"):
with pytest.raises(OAuthScopeProblem) as exc_info:
await wrapped_func(request)

assert exc_info.value.status_code == 403
assert exc_info.value.detail == "Provided token doesn't have the required scope"

tokeninfo["scope"].append("admin")
assert await wrapped_func(request) is not None

Expand Down Expand Up @@ -101,16 +108,22 @@ def token_info(token):
request = MagicMock()
request.headers = {"Authorization": "Bearer 123"}

with pytest.raises(OAuthScopeProblem, match="Provided token doesn't have the required scope"):
with pytest.raises(OAuthScopeProblem) as exc_info:
await wrapped_func(request)

assert exc_info.value.status_code == 403
assert exc_info.value.detail == "Provided token doesn't have the required scope"

tokeninfo["scope"] += " admin"
assert await wrapped_func(request) is not None

tokeninfo["scope"] = ["foo", "bar"]
with pytest.raises(OAuthScopeProblem, match="Provided token doesn't have the required scope"):
with pytest.raises(OAuthScopeProblem) as exc_info:
await wrapped_func(request)

assert exc_info.value.status_code == 403
assert exc_info.value.detail == "Provided token doesn't have the required scope"

tokeninfo["scope"].append("admin")
assert await wrapped_func(request) is not None

Expand All @@ -127,7 +140,7 @@ def somefunc(username, password, required_scopes=None):
assert wrapped_func(request) is security_handler_factory.no_value


def test_verify_basic(security_handler_factory):
async def test_verify_basic(security_handler_factory):
def basic_info(username, password, required_scopes=None):
if username == 'foo' and password == 'bar':
return {'sub': 'foo'}
Expand All @@ -138,10 +151,10 @@ def basic_info(username, password, required_scopes=None):
request = MagicMock()
request.headers = {"Authorization": 'Basic Zm9vOmJhcg=='}

assert wrapped_func(request) is not None
assert await wrapped_func(request) is not None


def test_verify_apikey_query(security_handler_factory):
async def test_verify_apikey_query(security_handler_factory):
def apikey_info(apikey, required_scopes=None):
if apikey == 'foobar':
return {'sub': 'foo'}
Expand All @@ -152,10 +165,10 @@ def apikey_info(apikey, required_scopes=None):
request = MagicMock()
request.query = {"auth": 'foobar'}

assert wrapped_func(request) is not None
assert await wrapped_func(request) is not None


def test_verify_apikey_header(security_handler_factory):
async def test_verify_apikey_header(security_handler_factory):
def apikey_info(apikey, required_scopes=None):
if apikey == 'foobar':
return {'sub': 'foo'}
Expand All @@ -166,7 +179,7 @@ def apikey_info(apikey, required_scopes=None):
request = MagicMock()
request.headers = {"X-Auth": 'foobar'}

assert wrapped_func(request) is not None
assert await wrapped_func(request) is not None


async def test_multiple_schemes(security_handler_factory):
Expand All @@ -191,7 +204,7 @@ def apikey2_info(apikey, required_scopes=None):
request = MagicMock()
request.headers = {"X-Auth-1": 'foobar'}

assert wrapped_func(request) is security_handler_factory.no_value
assert await wrapped_func(request) is security_handler_factory.no_value

request = MagicMock()
request.headers = {"X-Auth-2": 'bar'}
Expand All @@ -214,13 +227,14 @@ def apikey2_info(apikey, required_scopes=None):

async def test_verify_security_oauthproblem(security_handler_factory):
"""Tests whether verify_security raises an OAuthProblem if there are no auth_funcs."""
security_func = security_handler_factory.verify_security([], [])
security_func = security_handler_factory.verify_security([])

request = MagicMock()
with pytest.raises(OAuthProblem) as exc_info:
await security_func(request)

assert str(exc_info.value) == '401 Unauthorized: No authorization token provided'
assert exc_info.value.status_code == 401
assert exc_info.value.detail == 'No authorization token provided'

@pytest.mark.parametrize(
'errors, most_specific',
Expand Down