Skip to content

Commit

Permalink
Add explicit timeouts for the monitor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pavel-kirienko committed Jan 22, 2024
1 parent 2237db0 commit 8b31d9a
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
45 changes: 43 additions & 2 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,53 @@
# Copyright (c) 2020 OpenCyphal
# This software is distributed under the terms of the MIT License.
# Author: Pavel Kirienko <[email protected]>
# pylint: disable=wrong-import-position

import pathlib
from pathlib import Path
from typing import Callable, TypeVar, Any

# Please maintain these carefully if you're changing the project's directory structure.
TEST_DIR = pathlib.Path(__file__).resolve().parent
TEST_DIR = Path(__file__).resolve().parent
ROOT_DIR = TEST_DIR.parent

DEPS_DIR = TEST_DIR / "deps"
assert DEPS_DIR.is_dir()


T = TypeVar("T")


def timeout(seconds: int) -> Callable[[Callable[..., T]], Callable[..., T]]:
"""
This is a decorator that makes the function raise :class:`TimeoutError` if it takes more than ``seconds``
seconds to complete.
>>> import time
>>> @timeout(3)
... def runas(delay: float) -> None:
... time.sleep(delay)
>>> runas(1)
>>> runas(10)
Traceback (most recent call last):
...
TimeoutError: ...
"""
import signal
from functools import wraps

def decorator(fun: Callable[..., T]) -> Callable[..., T]:
@wraps(fun)
def wrapper(*args: Any, **kwargs: Any) -> T:
def signal_handler(_signum: int, _frame: Any) -> None:
raise TimeoutError(f"Function {fun} took more than {seconds:.0f}s to complete")

signal.signal(signal.SIGALRM, signal_handler)
signal.alarm(seconds)
try:
return fun(*args, **kwargs)
finally:
signal.alarm(0)

return wrapper

return decorator
3 changes: 3 additions & 0 deletions tests/cmd/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
from pycyphal.transport.udp import UDPTransport
from tests.subprocess import Subprocess
from tests.dsdl import OUTPUT_DIR
from tests import timeout
import yakut


# noinspection SpellCheckingInspection
@timeout(300)
@pytest.mark.asyncio
async def _unittest_monitor_nodes(compiled_dsdl: Any) -> None:
_ = compiled_dsdl
Expand Down Expand Up @@ -110,6 +112,7 @@ async def _unittest_monitor_nodes(compiled_dsdl: Any) -> None:


# noinspection SpellCheckingInspection
@timeout(60)
@pytest.mark.asyncio
async def _unittest_monitor_errors(compiled_dsdl: Any) -> None:
_ = compiled_dsdl
Expand Down

0 comments on commit 8b31d9a

Please sign in to comment.