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

Validate that the loop was set correctly during the test #16

Merged
merged 1 commit into from
Sep 12, 2024
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
21 changes: 21 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import asyncio
import typing
from typing import Generator

import pytest

from monitored_ioloop.monitored_asyncio import MonitoredAsyncIOEventLoopPolicy
from monitored_ioloop.monitored_ioloop_base import BaseMonitoredEventLoopPolicy
from monitored_ioloop.monitored_uvloop import MonitoredUvloopEventLoopPolicy
from tests.utils import assert_expected_loop_type


@pytest.fixture(
params=[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy]
)
def ioloop_policy_class(
request: pytest.FixtureRequest,
) -> Generator[typing.Type[BaseMonitoredEventLoopPolicy], None, None]:
yield request.param
assert_expected_loop_type(request.param)
asyncio.set_event_loop_policy(None)
59 changes: 7 additions & 52 deletions tests/test_asyncio_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,24 @@
BaseMonitoredEventLoopPolicy,
)
from monitored_ioloop.monitored_uvloop import MonitoredUvloopEventLoopPolicy
from monitored_ioloop.monitored_asyncio import (
MonitoredAsyncIOEventLoopPolicy,
from tests.utils import (
busy_wait,
_assert_monitor_result,
_check_monitor_result,
)
from tests.utils import busy_wait, _assert_monitor_result, _check_monitor_result


async def blocking_coroutine(block_for: float) -> None:
busy_wait(block_for)


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_simple_blocking_coroutine(
ioloop_policy_class: typing.Type[BaseMonitoredEventLoopPolicy],
) -> None:
mock = Mock()
asyncio.set_event_loop_policy(ioloop_policy_class(monitor_callback=mock))
block_for = 0.5
asyncio.run(blocking_coroutine(block_for))
print(mock.mock_calls)
(blocking_coroutine_monitor,) = mock.mock_calls[0].args
_assert_monitor_result(block_for, blocking_coroutine_monitor.callback_wall_time)
assert (
Expand All @@ -45,10 +41,6 @@ def monitor_callback_with_error(monitor: typing.Any) -> None:
raise ValueError("This monitor callback raises an exception.")


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_monitor_callback_error_is_handled(
ioloop_policy_class: typing.Type[BaseMonitoredEventLoopPolicy],
) -> None:
Expand All @@ -64,16 +56,11 @@ async def coroutine_with_result() -> int:
return 10


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_callback_returns_value_even_if_monitor_callback_fails(
ioloop_policy_class: typing.Type[MonitoredUvloopEventLoopPolicy],
ioloop_policy_class: typing.Type[BaseMonitoredEventLoopPolicy],
) -> None:
asyncio.set_event_loop_policy(
ioloop_policy_class(monitor_callback=monitor_callback_with_error)
)
policy = ioloop_policy_class(monitor_callback=monitor_callback_with_error)
asyncio.set_event_loop_policy(policy)
result = asyncio.run(coroutine_with_result())
assert result == 10

Expand All @@ -84,10 +71,6 @@ async def complex_blocking_coroutine(block_for: float) -> None:
busy_wait(block_for)


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_complex_blocking_coroutine(
ioloop_policy_class: typing.Type[MonitoredUvloopEventLoopPolicy],
) -> None:
Expand All @@ -106,10 +89,6 @@ async def run_blocking_coroutine_in_task(block_for: float) -> None:
await task


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_task_blocking_coroutine(
ioloop_policy_class: typing.Type[MonitoredUvloopEventLoopPolicy],
) -> None:
Expand All @@ -125,10 +104,6 @@ async def non_cpu_intensive_blocking_coroutine(block_time: float) -> None:
time.sleep(block_time)


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_non_cpu_intensive_blocking_coroutine(
ioloop_policy_class: typing.Type[MonitoredUvloopEventLoopPolicy],
) -> None:
Expand All @@ -144,10 +119,6 @@ async def exception_raising_coroutine() -> None:
raise ValueError("This coroutine raises an exception.")


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_handles_count_decreases_even_if_handle_raises_exception(
ioloop_policy_class: typing.Type[MonitoredUvloopEventLoopPolicy],
) -> None:
Expand Down Expand Up @@ -181,10 +152,6 @@ async def blocking_sleep() -> None:
)


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_handles_count_with_multiple_coroutines(
ioloop_policy_class: typing.Type[MonitoredUvloopEventLoopPolicy],
) -> None:
Expand All @@ -201,10 +168,6 @@ def test_handles_count_with_multiple_coroutines(
), "Handles count should drop to 0."


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_loop_lag(
ioloop_policy_class: typing.Type[MonitoredUvloopEventLoopPolicy],
) -> None:
Expand Down Expand Up @@ -234,10 +197,6 @@ def test_loop_lag(
)


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_callback_pretty_name__basic_top_level_coroutine_name(
ioloop_policy_class: typing.Type[MonitoredUvloopEventLoopPolicy],
) -> None:
Expand Down Expand Up @@ -271,10 +230,6 @@ async def second_function() -> None:
)


@pytest.mark.parametrize(
"ioloop_policy_class",
[MonitoredAsyncIOEventLoopPolicy, MonitoredUvloopEventLoopPolicy],
)
def test_callback_pretty_name__several_coroutines_with_gather(
ioloop_policy_class: typing.Type[MonitoredUvloopEventLoopPolicy],
) -> None:
Expand Down
27 changes: 27 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import asyncio
import time
from typing import Type

from monitored_ioloop.monitored_asyncio import (
MonitoredAsyncIOEventLoopPolicy,
MonitoredSelectorEventLoop,
)
from monitored_ioloop.monitored_ioloop_base import BaseMonitoredEventLoopPolicy
from monitored_ioloop.monitored_uvloop import (
MonitoredUvloopEventLoopPolicy,
MonitoredUvloopEventLoop,
)

BLOCK_THRESHOLD = 0.1

Expand All @@ -25,3 +37,18 @@ def _check_monitor_result(
< monitored_block
< expected_block * (1 + threshold)
)


async def _assert_expected_loop_type(
loop_policy: Type[BaseMonitoredEventLoopPolicy],
) -> None:
if issubclass(loop_policy, MonitoredAsyncIOEventLoopPolicy):
assert isinstance(asyncio.get_event_loop(), MonitoredSelectorEventLoop)
elif issubclass(loop_policy, MonitoredUvloopEventLoopPolicy):
assert isinstance(asyncio.get_event_loop(), MonitoredUvloopEventLoop)
else:
raise ValueError("Unknown loop policy")


def assert_expected_loop_type(loop_policy: Type[BaseMonitoredEventLoopPolicy]) -> None:
asyncio.run(_assert_expected_loop_type(loop_policy))
Loading