Skip to content

Commit

Permalink
✨ Update CI workflow with lint job name and add docker as a dev depen…
Browse files Browse the repository at this point in the history
…dency; remove obsolete test_lock_backends.py
  • Loading branch information
grelinfo committed Nov 27, 2024
1 parent 755371f commit 3b9ae26
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 270 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:

jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down
280 changes: 278 additions & 2 deletions tests/sync/test_backends.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
"""Test Backend Resigry."""
"""Test Synchronization Backends."""

from collections.abc import Callable, Generator
from collections.abc import AsyncGenerator, Callable, Generator
from uuid import uuid4

import pytest
from anyio import sleep
from testcontainers.postgres import PostgresContainer
from testcontainers.redis import AsyncRedisContainer

from grelmicro.sync._backends import get_sync_backend, loaded_backends
from grelmicro.sync.abc import SyncBackend
Expand All @@ -11,6 +15,22 @@
from grelmicro.sync.postgres import PostgresSyncBackend
from grelmicro.sync.redis import RedisSyncBackend

pytestmark = [pytest.mark.anyio, pytest.mark.timeout(10)]


@pytest.fixture(scope="module")
def anyio_backend() -> str:
"""AnyIO Backend Module Scope."""
return "asyncio"


@pytest.fixture(scope="module")
def monkeypatch() -> Generator[pytest.MonkeyPatch, None, None]:
"""Monkeypatch Module Scope."""
monkeypatch = pytest.MonkeyPatch()
yield monkeypatch
monkeypatch.undo()


@pytest.fixture
def clean_registry() -> Generator[None, None, None]:
Expand All @@ -20,6 +40,262 @@ def clean_registry() -> Generator[None, None, None]:
loaded_backends.pop("lock", None)


@pytest.fixture(
scope="module",
params=[
"memory",
pytest.param("redis", marks=[pytest.mark.integration]),
pytest.param("postgres", marks=[pytest.mark.integration]),
],
)
async def backend(
request: pytest.FixtureRequest,
monkeypatch: pytest.MonkeyPatch,
) -> AsyncGenerator[SyncBackend]:
"""Test Container for each Backend."""
if request.param == "redis":
monkeypatch.setenv("REDIS_HOST", "localhost")
monkeypatch.setenv("REDIS_PORT", "6379")
monkeypatch.setenv("REDIS_PASSWORD", "test")
monkeypatch.setenv("REDIS_DB", "0")
with AsyncRedisContainer():
async with RedisSyncBackend(
"redis://test:test@localhost:6379/0"
) as backend:
yield backend
elif request.param == "postgres":
monkeypatch.setenv("POSTGRES_HOST", "localhost")
monkeypatch.setenv("POSTGRES_PORT", "5432")
monkeypatch.setenv("POSTGRES_DB", "test")
monkeypatch.setenv("POSTGRES_USER", "test")
monkeypatch.setenv("POSTGRES_PASSWORD", "test")
with PostgresContainer():
async with PostgresSyncBackend(
"postgresql://test:test@localhost:5432/test"
) as backend:
yield backend
elif request.param == "memory":
async with MemorySyncBackend() as backend:
yield backend


async def test_acquire(backend: SyncBackend) -> None:
"""Test acquire."""
# Arrange
name = "test_acquire"
token = uuid4().hex
duration = 1

# Act
result = await backend.acquire(name=name, token=token, duration=duration)

# Assert
assert result


async def test_acquire_reantrant(backend: SyncBackend) -> None:
"""Test acquire is reantrant."""
# Arrange
name = "test_acquire_reantrant"
token = uuid4().hex
duration = 1

# Act
result1 = await backend.acquire(name=name, token=token, duration=duration)
result2 = await backend.acquire(name=name, token=token, duration=duration)

# Assert
assert result1
assert result2


async def test_acquire_already_acquired(backend: SyncBackend) -> None:
"""Test acquire when already acquired."""
# Arrange
name = "test_acquire_already_acquired"
token1 = uuid4().hex
token2 = uuid4().hex
duration = 1

# Act
result1 = await backend.acquire(name=name, token=token1, duration=duration)
result2 = await backend.acquire(name=name, token=token2, duration=duration)

# Assert
assert token1 != token2
assert result1
assert not result2


async def test_acquire_expired(backend: SyncBackend) -> None:
"""Test acquire when expired."""
# Arrange
name = "test_acquire_expired"
token = uuid4().hex
duration = 0.01

# Act
result = await backend.acquire(name=name, token=token, duration=duration)
await sleep(duration * 2)
result2 = await backend.acquire(name=name, token=token, duration=duration)

# Assert
assert result
assert result2


async def test_acquire_already_acquired_expired(backend: SyncBackend) -> None:
"""Test acquire when already acquired but expired."""
# Arrange
name = "test_acquire_already_acquired_expired" + uuid4().hex
token1 = uuid4().hex
token2 = uuid4().hex
duration = 0.01

# Act
result = await backend.acquire(name=name, token=token1, duration=duration)
await sleep(duration * 2)
result2 = await backend.acquire(name=name, token=token2, duration=duration)

# Assert
assert token1 != token2
assert result
assert result2


async def test_release_not_acquired(backend: SyncBackend) -> None:
"""Test release when not acquired."""
# Arrange
name = "test_release" + uuid4().hex
token = uuid4().hex

# Act
result = await backend.release(name=name, token=token)

# Assert
assert not result


async def test_release_acquired(backend: SyncBackend) -> None:
"""Test release when acquired."""
# Arrange
name = "test_release_acquired" + uuid4().hex
token = uuid4().hex
duration = 1

# Act
result1 = await backend.acquire(name=name, token=token, duration=duration)
result2 = await backend.release(name=name, token=token)

# Assert
assert result1
assert result2


async def test_release_not_reantrant(backend: SyncBackend) -> None:
"""Test release is not reantrant."""
# Arrange
name = "test_release_not_reantrant" + uuid4().hex
token = uuid4().hex
duration = 1

# Act
result1 = await backend.acquire(name=name, token=token, duration=duration)
result2 = await backend.release(name=name, token=token)
result3 = await backend.release(name=name, token=token)

# Assert
assert result1
assert result2
assert not result3


async def test_release_acquired_expired(backend: SyncBackend) -> None:
"""Test release when acquired but expired."""
# Arrange
name = "test_release_acquired_expired" + uuid4().hex
token = uuid4().hex
duration = 0.01

# Act
result1 = await backend.acquire(name=name, token=token, duration=duration)
await sleep(duration * 2)
result2 = await backend.release(name=name, token=token)

# Assert
assert result1
assert not result2


async def test_release_not_acquired_expired(backend: SyncBackend) -> None:
"""Test release when not acquired but expired."""
# Arrange
name = "test_release_not_acquired_expired" + uuid4().hex
token = uuid4().hex
duration = 0.01

# Act
result1 = await backend.acquire(name=name, token=token, duration=duration)
await sleep(duration * 2)
result2 = await backend.release(name=name, token=token)

# Assert
assert result1
assert not result2


async def test_locked(backend: SyncBackend) -> None:
"""Test locked."""
# Arrange
name = "test_locked" + uuid4().hex
token = uuid4().hex
duration = 1

# Act
locked_before = await backend.locked(name=name)
await backend.acquire(name=name, token=token, duration=duration)
locked_after = await backend.locked(name=name)

# Assert
assert locked_before is False
assert locked_after is True


async def test_owned(backend: SyncBackend) -> None:
"""Test owned."""
# Arrange
name = "test_owned" + uuid4().hex
token = uuid4().hex
duration = 1

# Act
owned_before = await backend.owned(name=name, token=token)
await backend.acquire(name=name, token=token, duration=duration)
owned_after = await backend.owned(name=name, token=token)

# Assert
assert owned_before is False
assert owned_after is True


async def test_owned_another(backend: SyncBackend) -> None:
"""Test owned another."""
# Arrange
name = "test_owned_another" + uuid4().hex
token1 = uuid4().hex
token2 = uuid4().hex
duration = 1

# Act
owned_before = await backend.owned(name=name, token=token1)
await backend.acquire(name=name, token=token1, duration=duration)
owned_after = await backend.owned(name=name, token=token2)

# Assert
assert owned_before is False
assert owned_after is False


@pytest.mark.parametrize(
"backend_factory",
[
Expand Down
Loading

0 comments on commit 3b9ae26

Please sign in to comment.