Skip to content

Commit

Permalink
Cleanup test coverage (#890)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dreamsorcerer committed Jun 10, 2023
1 parent 856de2b commit 1675097
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 77 deletions.
73 changes: 29 additions & 44 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sys
import time
import uuid
from typing import Iterator, TypedDict
from typing import AsyncIterator, Iterator, TypedDict

import aiomcache
import pytest
Expand All @@ -25,7 +25,8 @@ class _MemcachedParams(TypedDict):
port: int


def unused_port() -> int:
def unused_port() -> int: # pragma: no cover
"""Only used for people testing on OS X."""
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("", 0))
s.listen(1)
Expand All @@ -36,17 +37,11 @@ def unused_port() -> int:

@pytest.fixture(scope="session")
def event_loop() -> Iterator[asyncio.AbstractEventLoop]:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(None)

"""Redefine event_loop with session scope (from pytest-asyncio)."""
policy = asyncio.get_event_loop_policy()
loop = policy.new_event_loop()
yield loop

if not loop.is_closed():
loop.call_soon(loop.stop)
loop.run_forever()
loop.close()
gc.collect()
asyncio.set_event_loop(None)
loop.close()


@pytest.fixture(scope="session")
Expand All @@ -63,15 +58,13 @@ def docker() -> DockerClient: # type: ignore[misc] # No docker types.


@pytest.fixture(scope="session")
def redis_server( # type: ignore[misc] # No docker types.
async def redis_server( # type: ignore[misc] # No docker types.
docker: DockerClient,
session_id: str,
event_loop: asyncio.AbstractEventLoop,
) -> Iterator[_ContainerInfo]:
image = "redis:{}".format("latest")
asyncio.set_event_loop(event_loop)

if sys.platform.startswith("darwin"):
if sys.platform.startswith("darwin"): # pragma: no cover
port = unused_port()
else:
port = None
Expand All @@ -89,27 +82,25 @@ def redis_server( # type: ignore[misc] # No docker types.
},
)

if sys.platform.startswith("darwin"):
if sys.platform.startswith("darwin"): # pragma: no cover
host = "0.0.0.0"
else:
inspection = docker.api.inspect_container(container.id)
host = inspection["NetworkSettings"]["IPAddress"]
port = 6379

delay = 0.1
for _i in range(20):
for _i in range(20): # pragma: no cover
try:
conn = aioredis.from_url(f"redis://{host}:{port}")
event_loop.run_until_complete(conn.set("foo", "bar"))
await conn.set("foo", "bar")
break
except aioredis.ConnectionError:
time.sleep(delay)
delay *= 2
finally:
event_loop.run_until_complete(conn.close())
# TODO: Remove once fixed: github.com/aio-libs/aioredis-py/issues/1103
event_loop.run_until_complete(conn.connection_pool.disconnect())
else:
await conn.close()
else: # pragma: no cover
pytest.fail("Cannot start redis server")

yield {"host": host, "port": port, "container": container}
Expand All @@ -124,31 +115,27 @@ def redis_url(redis_server: _ContainerInfo) -> str: # type: ignore[misc]


@pytest.fixture
def redis(
event_loop: asyncio.AbstractEventLoop,
async def redis(
redis_url: str,
) -> Iterator[aioredis.Redis[bytes]]:
) -> AsyncIterator[aioredis.Redis[bytes]]:
async def start(pool: aioredis.ConnectionPool) -> aioredis.Redis[bytes]:
return aioredis.Redis(connection_pool=pool)

asyncio.set_event_loop(event_loop)
pool = aioredis.ConnectionPool.from_url(redis_url)
redis = event_loop.run_until_complete(start(pool))
redis = await start(pool)
yield redis
event_loop.run_until_complete(redis.close())
event_loop.run_until_complete(pool.disconnect())
await redis.close()
await pool.disconnect()


@pytest.fixture(scope="session")
def memcached_server( # type: ignore[misc] # No docker types.
async def memcached_server( # type: ignore[misc] # No docker types.
docker: DockerClient,
session_id: str,
event_loop: asyncio.AbstractEventLoop,
) -> Iterator[_ContainerInfo]:

) -> AsyncIterator[_ContainerInfo]:
image = "memcached:{}".format("latest")

if sys.platform.startswith("darwin"):
if sys.platform.startswith("darwin"): # pragma: no cover
port = unused_port()
else:
port = None
Expand All @@ -166,25 +153,25 @@ def memcached_server( # type: ignore[misc] # No docker types.
},
)

if sys.platform.startswith("darwin"):
if sys.platform.startswith("darwin"): # pragma: no cover
host = "0.0.0.0"
else:
inspection = docker.api.inspect_container(container.id)
host = inspection["NetworkSettings"]["IPAddress"]
port = 11211

delay = 0.1
for _i in range(20):
for _i in range(20): # pragma: no cover
try:
conn = aiomcache.Client(host, port)
event_loop.run_until_complete(conn.set(b"foo", b"bar"))
await conn.set(b"foo", b"bar")
break
except ConnectionRefusedError:
time.sleep(delay)
delay *= 2
finally:
event_loop.run_until_complete(conn.close())
else:
await conn.close()
else: # pragma: no cover
pytest.fail("Cannot start memcached server")

yield {"host": host, "port": port, "container": container}
Expand All @@ -201,9 +188,7 @@ def memcached_params( # type: ignore[misc]


@pytest.fixture
def memcached(
event_loop: asyncio.AbstractEventLoop, memcached_params: _MemcachedParams
) -> Iterator[aiomcache.Client]:
async def memcached(memcached_params: _MemcachedParams) -> AsyncIterator[aiomcache.Client]:
conn = aiomcache.Client(**memcached_params)
yield conn
event_loop.run_until_complete(conn.close())
await conn.close()
15 changes: 8 additions & 7 deletions tests/test_encrypted_cookie_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ def test_invalid_key() -> None:
EncryptedCookieStorage(b"123") # short key


def test_str_key() -> None:
k = Fernet.generate_key().decode("utf-8")
assert EncryptedCookieStorage(k)


async def test_create_new_session_broken_by_format(
aiohttp_client: AiohttpClient, fernet: Fernet, key: bytes
) -> None:
Expand Down Expand Up @@ -203,11 +208,8 @@ async def login(request: web.Request) -> web.StreamResponse:

async def handler(request: web.Request) -> web.StreamResponse:
session = await get_session(request)
created = session["created"] if not session.new else None
text = ""
if created is not None and (time.time() - created) > MAX_AGE:
text += "WARNING!"
return web.Response(text=text)
created = session["created"] if not session.new else ""
return web.Response(text=str(created))

middleware = session_middleware(EncryptedCookieStorage(key, max_age=MAX_AGE))
app = web.Application(middlewares=[middleware])
Expand All @@ -221,5 +223,4 @@ async def handler(request: web.Request) -> web.StreamResponse:
await asyncio.sleep(MAX_AGE + 1)
client.session.cookie_jar.update_cookies({"AIOHTTP_SESSION": cookie})
resp = await client.get("/")
body = await resp.text()
assert body == ""
assert await resp.text() == ""
19 changes: 8 additions & 11 deletions tests/test_get_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,13 @@ async def test_get_new_session() -> None:
session = Session("identity", data=None, new=False)

class Storage(AbstractStorage):
async def load_session( # type: ignore[no-untyped-def]
self,
request: web.Request,
):
pass
async def load_session(self, request: web.Request) -> Session: # type: ignore[empty-body]
"""Dummy"""

async def save_session(
self, request: web.Request, response: web.StreamResponse, session: Session
) -> None:
pass
"""Dummy"""

req[SESSION_KEY] = session
req[STORAGE_KEY] = Storage()
Expand All @@ -77,16 +74,16 @@ async def test_get_new_session_bad_return() -> None:
req = make_mocked_request("GET", "/")

class Storage(AbstractStorage):
async def new_session(self): # type: ignore[no-untyped-def]
return ""
async def new_session(self) -> Session:
return "" # type: ignore[return-value]

async def load_session(self, request: web.Request) -> Session:
return Session(None, data=None, new=True)
async def load_session(self, request: web.Request) -> Session: # type: ignore[empty-body]
"""Dummy"""

async def save_session(
self, request: web.Request, response: web.StreamResponse, session: Session
) -> None:
pass
"""Dummy"""

req[STORAGE_KEY] = Storage()

Expand Down
10 changes: 3 additions & 7 deletions tests/test_nacl_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,8 @@ async def login(request: web.Request) -> web.StreamResponse:

async def handler(request: web.Request) -> web.StreamResponse:
session = await get_session(request)
created = session.get("created", None) if not session.new else None
text = ""
if created is not None and (time.time() - created) > MAX_AGE:
text += "WARNING!"
return web.Response(text=text)
created = session.get("created", "") if not session.new else ""
return web.Response(text=str(created))

app = create_app(handler, key, max_age=MAX_AGE)
app.router.add_route("POST", "/", login)
Expand All @@ -257,5 +254,4 @@ async def handler(request: web.Request) -> web.StreamResponse:
await asyncio.sleep(MAX_AGE + 1)
client.session.cookie_jar.update_cookies({"AIOHTTP_SESSION": cookie})
resp = await client.get("/")
body = await resp.text()
assert body == ""
assert await resp.text() == ""
16 changes: 8 additions & 8 deletions tests/test_redis_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,34 +286,34 @@ async def logout(request: web.Request) -> web.StreamResponse:


async def test_redis_from_create_pool(redis_url: str) -> None:
async def handler(request: web.Request) -> web.Response:
return web.Response()
async def handler(request: web.Request) -> web.Response: # type: ignore[empty-body]
"""Dummy handler"""

redis = aioredis.from_url(redis_url)
create_app(handler=handler, redis=redis)
await redis.close()


async def test_not_redis_provided_to_storage() -> None:
async def handler(request: web.Request) -> web.Response:
return web.Response()
async def handler(request: web.Request) -> web.Response: # type: ignore[empty-body]
"""Dummy handler"""

with pytest.raises(TypeError):
create_app(handler=handler, redis=None) # type: ignore[arg-type]


async def test_no_aioredis_installed(mocker: MockFixture) -> None:
async def handler(request: web.Request) -> web.Response:
return web.Response()
async def handler(request: web.Request) -> web.Response: # type: ignore[empty-body]
"""Dummy handler"""

mocker.patch("aiohttp_session.redis_storage.aioredis", None)
with pytest.raises(RuntimeError):
create_app(handler=handler, redis=None) # type: ignore[arg-type]


async def test_old_aioredis_version(mocker: MockFixture) -> None:
async def handler(request: web.Request) -> web.Response:
return web.Response()
async def handler(request: web.Request) -> web.Response: # type: ignore[empty-body]
"""Dummy handler"""

mocker.patch("aiohttp_session.redis_storage.REDIS_VERSION", (0, 3, "dev0"))
with pytest.raises(RuntimeError):
Expand Down

0 comments on commit 1675097

Please sign in to comment.