Skip to content

Commit

Permalink
maint: add Dragonfly test support (#318)
Browse files Browse the repository at this point in the history
  • Loading branch information
cunla authored Aug 24, 2024
1 parent 21a3fe5 commit f9d9b46
Show file tree
Hide file tree
Showing 20 changed files with 388 additions and 210 deletions.
79 changes: 79 additions & 0 deletions .github/workflows/test-dragonfly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
name: Test Dragonfly

on:
workflow_dispatch:


concurrency:
group: dragon-fly-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
tests:
- "test_json"
- "test_mixins"
- "test_stack"
- "test_connection.py"
- "test_asyncredis.py"
- "test_general.py"
- "test_scan.py"
- "test_zadd.py"
- "test_translations.py"
- "test_sortedset_commands.py"
permissions:
pull-requests: write
services:
redis:
image: docker.dragonflydb.io/dragonflydb/dragonfly:latest
ports:
- 6380:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
cache-dependency-path: poetry.lock
python-version: 3.12
- name: Install dependencies
env:
PYTHON_KEYRING_BACKEND: keyring.backends.null.Keyring
run: |
python -m pip --quiet install poetry
echo "$HOME/.poetry/bin" >> $GITHUB_PATH
poetry install
poetry run pip install "fakeredis[json,bf,cf,lua]"
- name: Test without coverage
run: |
poetry run pytest test/${{ matrix.tests }} \
--html=report-${{ matrix.tests }}.html \
--self-contained-html \
-v
- name: Upload Tests Result
if: always()
uses: actions/upload-artifact@v4
with:
name: tests-result-${{ matrix.tests }}
path: report-${{ matrix.tests }}.html

upload-results:
needs: test
if: always()
runs-on: ubuntu-latest
steps:
- name: Collect Tests Result
uses: actions/upload-artifact/merge@v4
with:
delete-merged: true
10 changes: 10 additions & 0 deletions docs/about/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ description: Change log of all fakeredis releases

- Support for TIME SERIES commands (no support for align arguments on some commands) #310

### 🐛 Bug Fixes

- fix:xrevrange to work with exclusive ranges @hurlenko #319

### 🧰 Maintenance

- Update all dependencies, particularly pytest to v8
- Add tests against Dragonfly server #318
- Implement decocator `unsupported_server_types` to enable excluding tests from running against certain server types #318

## v2.23.5

### 🐛 Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
mkdocs==1.6.0
mkdocs-material==9.5.31
mkdocs-material==9.5.33
208 changes: 162 additions & 46 deletions poetry.lock

Large diffs are not rendered by default.

14 changes: 9 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ packages = [
{ include = "fakeredis" },
{ include = "LICENSE" },
]
version = "2.23.5"
version = "2.24.0"
description = "Python implementation of redis API, can be used for testing purposes."
readme = "README.md"
keywords = ["redis", "RedisJson", "RedisBloom", "tests", "redis-stack"]
Expand Down Expand Up @@ -66,15 +66,16 @@ coverage = "^7"
black = { version = "^24.4.2", python = ">=3.8.1" }
flake8 = { version = "^7", python = ">=3.8.1" }
flake8-pyproject = { version = "^1", python = ">=3.8.1" }
hypothesis = "^6.70"
mypy = { version = "^1.10", python = ">=3.8.1" }

[tool.poetry.group.test.dependencies]
pytest = "^7.4"
pytest = { version = "^8.3", python = ">=3.8.1" }
hypothesis = { version = "^6.111", python = ">=3.8.1" }
pytest-timeout = "^2.3.1"
pytest-asyncio = "^0.21"
pytest-cov = "^4.1"
pytest-asyncio = { version = "^0.24", python = ">=3.8.1" }
pytest-cov = { version = "^5.0", python = ">=3.8.1" }
pytest-mock = { version = "^3.14", python = ">=3.8.1" }
pytest-html = { version = "^4.1", python = ">=3.8.1" }

[tool.poetry.group.docs.dependencies]
python-dotenv = { version = "^1", python = ">=3.8.1" }
Expand All @@ -86,6 +87,7 @@ pygithub = "^2.3"
"Documentation" = "https://fakeredis.moransoftware.ca/"

[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "function"
markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
"fake: run tests only with fake redis",
Expand All @@ -94,8 +96,10 @@ markers = [
"min_server",
"max_server",
"decode_responses",
"unsupported_server_types",
]
asyncio_mode = "strict"
generate_report_on_test = true

[tool.mypy]
packages = ['fakeredis', ]
Expand Down
29 changes: 19 additions & 10 deletions test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Callable, Union
from typing import Callable, Tuple, Union, Optional

import pytest
import pytest_asyncio
Expand All @@ -18,22 +18,26 @@ def _check_lua_module_supported() -> bool:


@pytest_asyncio.fixture(scope="session")
def real_redis_version() -> Union[None, str]:
def real_redis_version() -> Tuple[str, Union[None, Tuple[int, ...]]]:
"""Returns server's version or None if server is not running"""
client = None
try:
client = redis.StrictRedis("localhost", port=6380, db=2)
server_version = client.info()["redis_version"]
return server_version
client_info = client.info()
server_type = "dragonfly" if "dragonfly_version" in client_info else "redis"
server_version = client_info["redis_version"] if server_type != "dragonfly" else (7, 0)
server_version = _create_version(server_version) or (7,)
return server_type, server_version
except redis.ConnectionError:
return None
pytest.exit("Redis is not running")
return "redis", (6,)
finally:
if hasattr(client, "close"):
client.close() # Absent in older versions of redis-py


@pytest_asyncio.fixture(name="fake_server")
def _fake_server(request):
def _fake_server(request) -> fakeredis.FakeServer:
min_server_marker = request.node.get_closest_marker("min_server")
server_version = min_server_marker.args[0] if min_server_marker else "6.2"
server = fakeredis.FakeServer(version=server_version)
Expand Down Expand Up @@ -70,10 +74,12 @@ def _marker_version_value(request, marker_name: str):
)
def _create_redis(request) -> Callable[[int], redis.Redis]:
cls_name = request.param
server_version = request.getfixturevalue("real_redis_version")
server_type, server_version = request.getfixturevalue("real_redis_version")
if not cls_name.startswith("Fake") and not server_version:
pytest.skip("Redis is not running")
server_version = _create_version(server_version) or (6,)
unsupported_server_types = request.node.get_closest_marker("unsupported_server_types")
if unsupported_server_types and server_type in unsupported_server_types.args:
pytest.skip(f"Server type {server_type} is not supported")
min_server = _marker_version_value(request, "min_server")
max_server = _marker_version_value(request, "max_server")
if server_version < min_server:
Expand Down Expand Up @@ -103,10 +109,12 @@ def factory(db=2):
params=[pytest.param("fake", marks=pytest.mark.fake), pytest.param("real", marks=pytest.mark.real)],
)
async def _req_aioredis2(request) -> redis.asyncio.Redis:
server_version = request.getfixturevalue("real_redis_version")
server_type, server_version = request.getfixturevalue("real_redis_version")
if request.param != "fake" and not server_version:
pytest.skip("Redis is not running")
server_version = _create_version(server_version) or (6,)
unsupported_server_types = request.node.get_closest_marker("unsupported_server_types")
if unsupported_server_types and server_type in unsupported_server_types.args:
pytest.skip(f"Server type {server_type} is not supported")
min_server_marker = _marker_version_value(request, "min_server")
max_server_marker = _marker_version_value(request, "max_server")
if server_version < min_server_marker:
Expand All @@ -117,6 +125,7 @@ async def _req_aioredis2(request) -> redis.asyncio.Redis:
lua_modules = set(lua_modules_marker.args) if lua_modules_marker else None
if lua_modules and not _check_lua_module_supported():
pytest.skip("LUA modules not supported by fakeredis")
fake_server: Optional[fakeredis.FakeServer]
if request.param == "fake":
fake_server = request.getfixturevalue("fake_server")
ret = fakeredis.FakeAsyncRedis(server=fake_server, lua_modules=lua_modules)
Expand Down
34 changes: 5 additions & 29 deletions test/test_json/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,14 +435,7 @@ def test_decode_response_disabaled_null(r: redis.Redis):


def test_json_get_jset(r: redis.Redis):
assert (
r.json().set(
"foo",
Path.root_path(),
"bar",
)
== 1
)
assert r.json().set("foo", Path.root_path(), "bar") == 1
assert "bar" == r.json().get("foo")
assert r.json().get("baz") is None
assert 1 == r.json().delete("foo")
Expand Down Expand Up @@ -509,19 +502,9 @@ def test_set_path(r: redis.Redis):


def test_type(r: redis.Redis):
r.json().set(
"1",
Path.root_path(),
1,
)
r.json().set("1", Path.root_path(), 1)

assert (
r.json().type(
"1",
Path.root_path(),
)
== b"integer"
)
assert r.json().type("1", Path.root_path()) == b"integer"
assert r.json().type("1") == b"integer" # noqa: E721

meta_data = {
Expand Down Expand Up @@ -553,15 +536,8 @@ def test_objlen(r: redis.Redis):

obj = {"foo": "bar", "baz": "qaz"}

r.json().set(
"obj",
Path.root_path(),
obj,
)
assert len(obj) == r.json().objlen(
"obj",
Path.root_path(),
)
r.json().set("obj", Path.root_path(), obj)
assert len(obj) == r.json().objlen("obj", Path.root_path())

r.json().set("obj", Path.root_path(), obj)
assert len(obj) == r.json().objlen("obj")
Expand Down
Loading

0 comments on commit f9d9b46

Please sign in to comment.