diff --git a/docker-compose.yml b/docker-compose.yml index 17d4b23977..09418ed094 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,12 +5,11 @@ version: "3.8" services: redis: - image: redis/redis-stack-server:edge + image: ${REDIS_IMAGE:-redis:latest} container_name: redis-standalone + command: redis-server --enable-debug-command yes ports: - 6379:6379 - environment: - - "REDIS_ARGS=--enable-debug-command yes --enable-module-command yes" profiles: - standalone - sentinel @@ -18,12 +17,11 @@ services: - all replica: - image: redis/redis-stack-server:edge + image: ${REDIS_IMAGE:-redis:latest} container_name: redis-replica depends_on: - redis - environment: - - "REDIS_ARGS=--replicaof redis 6379" + command: redis-server --replicaof redis 6379 ports: - 6380:6379 profiles: @@ -35,6 +33,8 @@ services: build: context: . dockerfile: dockers/Dockerfile.cluster + args: + REDIS_IMAGE: ${REDIS_IMAGE:-redis:latest} ports: - 16379:16379 - 16380:16380 @@ -63,13 +63,11 @@ services: - "./dockers/stunnel/keys:/etc/stunnel/keys:ro" sentinel: - image: redis/redis-stack-server:edge + image: ${REDIS_IMAGE:-redis:latest} container_name: redis-sentinel depends_on: - redis - environment: - - "REDIS_ARGS=--port 26379" - entrypoint: "/opt/redis-stack/bin/redis-sentinel /redis.conf --port 26379" + entrypoint: "/usr/local/bin/redis-sentinel /redis.conf --port 26379" ports: - 26379:26379 volumes: @@ -79,13 +77,11 @@ services: - all sentinel2: - image: redis/redis-stack-server:edge + image: ${REDIS_IMAGE:-redis:latest} container_name: redis-sentinel2 depends_on: - redis - environment: - - "REDIS_ARGS=--port 26380" - entrypoint: "/opt/redis-stack/bin/redis-sentinel /redis.conf --port 26380" + entrypoint: "/usr/local/bin/redis-sentinel /redis.conf --port 26380" ports: - 26380:26380 volumes: @@ -95,11 +91,11 @@ services: - all sentinel3: - image: redis/redis-stack-server:edge + image: ${REDIS_IMAGE:-redis:latest} container_name: redis-sentinel3 depends_on: - redis - entrypoint: "/opt/redis-stack/bin/redis-sentinel /redis.conf --port 26381" + entrypoint: "/usr/local/bin/redis-sentinel /redis.conf --port 26381" ports: - 26381:26381 volumes: @@ -107,3 +103,14 @@ services: profiles: - sentinel - all + + redis-stack: + image: redis/redis-stack-server:edge + container_name: redis-stack + ports: + - 6479:6379 + environment: + - "REDIS_ARGS=--enable-debug-command yes --enable-module-command yes" + profiles: + - standalone + - all diff --git a/dockers/Dockerfile.cluster b/dockers/Dockerfile.cluster index 3a0d73415e..4096009f9a 100644 --- a/dockers/Dockerfile.cluster +++ b/dockers/Dockerfile.cluster @@ -1,7 +1,7 @@ -FROM redis/redis-stack-server:edge as rss +ARG REDIS_IMAGE=redis:latest +FROM $REDIS_IMAGE COPY dockers/create_cluster.sh /create_cluster.sh -RUN ls -R /opt/redis-stack RUN chmod a+x /create_cluster.sh ENTRYPOINT [ "/create_cluster.sh"] diff --git a/dockers/cluster.redis.conf b/dockers/cluster.redis.conf index d4de46fbed..e9f7617d09 100644 --- a/dockers/cluster.redis.conf +++ b/dockers/cluster.redis.conf @@ -1,8 +1,2 @@ protected-mode no enable-debug-command yes -loadmodule /opt/redis-stack/lib/redisearch.so -loadmodule /opt/redis-stack/lib/redisgraph.so -loadmodule /opt/redis-stack/lib/redistimeseries.so -loadmodule /opt/redis-stack/lib/rejson.so -loadmodule /opt/redis-stack/lib/redisbloom.so -loadmodule /opt/redis-stack/lib/redisgears.so v8-plugin-path /opt/redis-stack/lib/libredisgears_v8_plugin.so diff --git a/dockers/create_cluster.sh b/dockers/create_cluster.sh index da9a0cb606..af41192585 100644 --- a/dockers/create_cluster.sh +++ b/dockers/create_cluster.sh @@ -31,7 +31,7 @@ dir /nodes/$PORT EOF set -x - /opt/redis-stack/bin/redis-server /nodes/$PORT/redis.conf + /usr/local/bin/redis-server /nodes/$PORT/redis.conf sleep 1 if [ $? -ne 0 ]; then echo "Redis failed to start, exiting." @@ -40,8 +40,8 @@ EOF echo 127.0.0.1:$PORT >> /nodes/nodemap done if [ -z "${REDIS_PASSWORD}" ]; then - echo yes | /opt/redis-stack/bin/redis-cli --cluster create `seq -f 127.0.0.1:%g ${START_PORT} ${END_PORT}` --cluster-replicas 1 + echo yes | /usr/local/bin/redis-cli --cluster create `seq -f 127.0.0.1:%g ${START_PORT} ${END_PORT}` --cluster-replicas 1 else - echo yes | opt/redis-stack/bin/redis-cli -a ${REDIS_PASSWORD} --cluster create `seq -f 127.0.0.1:%g ${START_PORT} ${END_PORT}` --cluster-replicas 1 + echo yes | /usr/local/bin/redis-cli -a ${REDIS_PASSWORD} --cluster create `seq -f 127.0.0.1:%g ${START_PORT} ${END_PORT}` --cluster-replicas 1 fi tail -f /redis.log diff --git a/tasks.py b/tasks.py index c60fa2791e..7f26081150 100644 --- a/tasks.py +++ b/tasks.py @@ -13,7 +13,7 @@ def devenv(c): """Brings up the test environment, by wrapping docker compose.""" clean(c) - cmd = "docker-compose --profile all up -d" + cmd = "docker-compose --profile all up -d --build" run(cmd) diff --git a/tests/conftest.py b/tests/conftest.py index e783b6e8f9..9263c4353d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,7 +18,7 @@ REDIS_INFO = {} default_redis_url = "redis://localhost:6379/0" default_protocol = "2" -default_redismod_url = "redis://localhost:6379" +default_redismod_url = "redis://localhost:6479" # default ssl client ignores verification for the purpose of testing default_redis_ssl_url = "rediss://localhost:6666" @@ -341,6 +341,21 @@ def r(request): yield client +@pytest.fixture() +def stack_url(request): + stack_url = request.config.getoption("--redis-url", default=default_redismod_url) + if stack_url == default_redis_url: + return default_redismod_url + else: + return stack_url + + +@pytest.fixture() +def stack_r(request, stack_url): + with _get_client(redis.Redis, request, from_url=stack_url) as client: + yield client + + @pytest.fixture() def decoded_r(request): with _get_client(redis.Redis, request, decode_responses=True) as client: diff --git a/tests/test_asyncio/test_bloom.py b/tests/test_asyncio/test_bloom.py index 278844416f..c63559a31c 100644 --- a/tests/test_asyncio/test_bloom.py +++ b/tests/test_asyncio/test_bloom.py @@ -1,6 +1,7 @@ from math import inf import pytest +import pytest_asyncio import redis.asyncio as redis from redis.exceptions import ModuleError, RedisError from redis.utils import HIREDIS_AVAILABLE @@ -11,10 +12,16 @@ ) +@pytest_asyncio.fixture() +async def decoded_r(create_redis, stack_url): + return await create_redis(decode_responses=True, url=stack_url) + + def intlist(obj): return [int(v) for v in obj] +@pytest.mark.redismod async def test_create(decoded_r: redis.Redis): """Test CREATE/RESERVE calls""" assert await decoded_r.bf().create("bloom", 0.01, 1000) @@ -30,10 +37,12 @@ async def test_create(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod async def test_tdigest_create(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("tDigest", 100) +@pytest.mark.redismod async def test_bf_add(decoded_r: redis.Redis): assert await decoded_r.bf().create("bloom", 0.01, 1000) assert 1 == await decoded_r.bf().add("bloom", "foo") @@ -46,6 +55,7 @@ async def test_bf_add(decoded_r: redis.Redis): assert [1, 0] == intlist(await decoded_r.bf().mexists("bloom", "foo", "noexist")) +@pytest.mark.redismod async def test_bf_insert(decoded_r: redis.Redis): assert await decoded_r.bf().create("bloom", 0.01, 1000) assert [1] == intlist(await decoded_r.bf().insert("bloom", ["foo"])) @@ -76,6 +86,7 @@ async def test_bf_insert(decoded_r: redis.Redis): ) +@pytest.mark.redismod async def test_bf_scandump_and_loadchunk(decoded_r: redis.Redis): # Store a filter await decoded_r.bf().create("myBloom", "0.0001", "1000") @@ -127,6 +138,7 @@ async def do_verify(): await decoded_r.bf().create("myBloom", "0.0001", "10000000") +@pytest.mark.redismod async def test_bf_info(decoded_r: redis.Redis): expansion = 4 # Store a filter @@ -158,6 +170,7 @@ async def test_bf_info(decoded_r: redis.Redis): assert True +@pytest.mark.redismod async def test_bf_card(decoded_r: redis.Redis): # return 0 if the key does not exist assert await decoded_r.bf().card("not_exist") == 0 @@ -172,6 +185,7 @@ async def test_bf_card(decoded_r: redis.Redis): await decoded_r.bf().card("setKey") +@pytest.mark.redismod async def test_cf_add_and_insert(decoded_r: redis.Redis): assert await decoded_r.cf().create("cuckoo", 1000) assert await decoded_r.cf().add("cuckoo", "filter") @@ -197,6 +211,7 @@ async def test_cf_add_and_insert(decoded_r: redis.Redis): ) +@pytest.mark.redismod async def test_cf_exists_and_del(decoded_r: redis.Redis): assert await decoded_r.cf().create("cuckoo", 1000) assert await decoded_r.cf().add("cuckoo", "filter") @@ -208,6 +223,7 @@ async def test_cf_exists_and_del(decoded_r: redis.Redis): assert 0 == await decoded_r.cf().count("cuckoo", "filter") +@pytest.mark.redismod async def test_cms(decoded_r: redis.Redis): assert await decoded_r.cms().initbydim("dim", 1000, 5) assert await decoded_r.cms().initbyprob("prob", 0.01, 0.01) @@ -224,6 +240,7 @@ async def test_cms(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod async def test_cms_merge(decoded_r: redis.Redis): assert await decoded_r.cms().initbydim("A", 1000, 5) assert await decoded_r.cms().initbydim("B", 1000, 5) @@ -240,6 +257,7 @@ async def test_cms_merge(decoded_r: redis.Redis): assert [16, 15, 21] == await decoded_r.cms().query("C", "foo", "bar", "baz") +@pytest.mark.redismod async def test_topk(decoded_r: redis.Redis): # test list with empty buckets assert await decoded_r.topk().reserve("topk", 3, 50, 4, 0.9) @@ -320,6 +338,7 @@ async def test_topk(decoded_r: redis.Redis): assert 0.9 == round(float(info["decay"]), 1) +@pytest.mark.redismod async def test_topk_incrby(decoded_r: redis.Redis): await decoded_r.flushdb() assert await decoded_r.topk().reserve("topk", 3, 10, 3, 1) @@ -335,6 +354,7 @@ async def test_topk_incrby(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod async def test_tdigest_reset(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("tDigest", 10) # reset on empty histogram @@ -351,6 +371,7 @@ async def test_tdigest_reset(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod async def test_tdigest_merge(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("to-tDigest", 10) assert await decoded_r.tdigest().create("from-tDigest", 10) @@ -378,6 +399,7 @@ async def test_tdigest_merge(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod async def test_tdigest_min_and_max(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("tDigest", 100) # insert data-points into sketch @@ -388,6 +410,7 @@ async def test_tdigest_min_and_max(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod @skip_ifmodversion_lt("2.4.0", "bf") async def test_tdigest_quantile(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("tDigest", 500) @@ -416,6 +439,7 @@ async def test_tdigest_quantile(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod async def test_tdigest_cdf(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("tDigest", 100) # insert data-points into sketch @@ -427,6 +451,7 @@ async def test_tdigest_cdf(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod @skip_ifmodversion_lt("2.4.0", "bf") async def test_tdigest_trimmed_mean(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("tDigest", 100) @@ -437,6 +462,7 @@ async def test_tdigest_trimmed_mean(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod async def test_tdigest_rank(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("t-digest", 500) assert await decoded_r.tdigest().add("t-digest", list(range(0, 20))) @@ -447,6 +473,7 @@ async def test_tdigest_rank(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod async def test_tdigest_revrank(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("t-digest", 500) assert await decoded_r.tdigest().add("t-digest", list(range(0, 20))) @@ -456,6 +483,7 @@ async def test_tdigest_revrank(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod async def test_tdigest_byrank(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("t-digest", 500) assert await decoded_r.tdigest().add("t-digest", list(range(1, 11))) @@ -467,6 +495,7 @@ async def test_tdigest_byrank(decoded_r: redis.Redis): @pytest.mark.experimental +@pytest.mark.redismod async def test_tdigest_byrevrank(decoded_r: redis.Redis): assert await decoded_r.tdigest().create("t-digest", 500) assert await decoded_r.tdigest().add("t-digest", list(range(1, 11))) @@ -475,19 +504,3 @@ async def test_tdigest_byrevrank(decoded_r: redis.Redis): assert (await decoded_r.tdigest().byrevrank("t-digest", 100))[0] == -inf with pytest.raises(redis.ResponseError): (await decoded_r.tdigest().byrevrank("t-digest", -1))[0] - - -# # async def test_pipeline(decoded_r: redis.Redis): -# pipeline = await decoded_r.bf().pipeline() -# assert not await decoded_r.bf().execute_command("get pipeline") -# -# assert await decoded_r.bf().create("pipeline", 0.01, 1000) -# for i in range(100): -# pipeline.add("pipeline", i) -# for i in range(100): -# assert not (await decoded_r.bf().exists("pipeline", i)) -# -# pipeline.execute() -# -# for i in range(100): -# assert await decoded_r.bf().exists("pipeline", i) diff --git a/tests/test_asyncio/test_graph.py b/tests/test_asyncio/test_graph.py index 4caf79470e..9cd9149dcc 100644 --- a/tests/test_asyncio/test_graph.py +++ b/tests/test_asyncio/test_graph.py @@ -1,4 +1,5 @@ import pytest +import pytest_asyncio import redis.asyncio as redis from redis.commands.graph import Edge, Node, Path from redis.commands.graph.execution_plan import Operation @@ -6,12 +7,19 @@ from tests.conftest import skip_if_redis_enterprise +@pytest_asyncio.fixture() +async def decoded_r(create_redis, stack_url): + return await create_redis(decode_responses=True, url=stack_url) + + +@pytest.mark.redismod async def test_bulk(decoded_r): with pytest.raises(NotImplementedError): await decoded_r.graph().bulk() await decoded_r.graph().bulk(foo="bar!") +@pytest.mark.redismod async def test_graph_creation(decoded_r: redis.Redis): graph = decoded_r.graph() @@ -56,6 +64,7 @@ async def test_graph_creation(decoded_r: redis.Redis): await graph.delete() +@pytest.mark.redismod async def test_array_functions(decoded_r: redis.Redis): graph = decoded_r.graph() @@ -78,6 +87,7 @@ async def test_array_functions(decoded_r: redis.Redis): assert [a] == result.result_set[0][0] +@pytest.mark.redismod async def test_path(decoded_r: redis.Redis): node0 = Node(node_id=0, label="L1") node1 = Node(node_id=1, label="L1") @@ -97,6 +107,7 @@ async def test_path(decoded_r: redis.Redis): assert expected_results == result.result_set +@pytest.mark.redismod async def test_param(decoded_r: redis.Redis): params = [1, 2.3, "str", True, False, None, [0, 1, 2]] query = "RETURN $param" @@ -106,6 +117,7 @@ async def test_param(decoded_r: redis.Redis): assert expected_results == result.result_set +@pytest.mark.redismod async def test_map(decoded_r: redis.Redis): query = "RETURN {a:1, b:'str', c:NULL, d:[1,2,3], e:True, f:{x:1, y:2}}" @@ -122,6 +134,7 @@ async def test_map(decoded_r: redis.Redis): assert actual == expected +@pytest.mark.redismod async def test_point(decoded_r: redis.Redis): query = "RETURN point({latitude: 32.070794860, longitude: 34.820751118})" expected_lat = 32.070794860 @@ -138,6 +151,7 @@ async def test_point(decoded_r: redis.Redis): assert abs(actual["longitude"] - expected_lon) < 0.001 +@pytest.mark.redismod async def test_index_response(decoded_r: redis.Redis): result_set = await decoded_r.graph().query("CREATE INDEX ON :person(age)") assert 1 == result_set.indices_created @@ -152,6 +166,7 @@ async def test_index_response(decoded_r: redis.Redis): await decoded_r.graph().query("DROP INDEX ON :person(age)") +@pytest.mark.redismod async def test_stringify_query_result(decoded_r: redis.Redis): graph = decoded_r.graph() @@ -205,6 +220,7 @@ async def test_stringify_query_result(decoded_r: redis.Redis): await graph.delete() +@pytest.mark.redismod async def test_optional_match(decoded_r: redis.Redis): # Build a graph of form (a)-[R]->(b) node0 = Node(node_id=0, label="L1", properties={"value": "a"}) @@ -229,6 +245,7 @@ async def test_optional_match(decoded_r: redis.Redis): await graph.delete() +@pytest.mark.redismod async def test_cached_execution(decoded_r: redis.Redis): await decoded_r.graph().query("CREATE ()") @@ -248,6 +265,7 @@ async def test_cached_execution(decoded_r: redis.Redis): assert cached_result.cached_execution +@pytest.mark.redismod async def test_slowlog(decoded_r: redis.Redis): create_query = """CREATE (:Rider {name:'Valentino Rossi'})-[:rides]->(:Team {name:'Yamaha'}), @@ -261,6 +279,7 @@ async def test_slowlog(decoded_r: redis.Redis): @pytest.mark.xfail(strict=False) +@pytest.mark.redismod async def test_query_timeout(decoded_r: redis.Redis): # Build a sample graph with 1000 nodes. await decoded_r.graph().query("UNWIND range(0,1000) as val CREATE ({v: val})") @@ -274,6 +293,7 @@ async def test_query_timeout(decoded_r: redis.Redis): assert False is False +@pytest.mark.redismod async def test_read_only_query(decoded_r: redis.Redis): with pytest.raises(Exception): # Issue a write query, specifying read-only true, @@ -282,6 +302,7 @@ async def test_read_only_query(decoded_r: redis.Redis): assert False is False +@pytest.mark.redismod async def test_profile(decoded_r: redis.Redis): q = """UNWIND range(1, 3) AS x CREATE (p:Person {v:x})""" profile = (await decoded_r.graph().profile(q)).result_set @@ -297,6 +318,7 @@ async def test_profile(decoded_r: redis.Redis): @skip_if_redis_enterprise() +@pytest.mark.redismod async def test_config(decoded_r: redis.Redis): config_name = "RESULTSET_SIZE" config_value = 3 @@ -328,6 +350,7 @@ async def test_config(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod async def test_list_keys(decoded_r: redis.Redis): result = await decoded_r.graph().list_keys() assert result == [] @@ -350,6 +373,7 @@ async def test_list_keys(decoded_r: redis.Redis): assert result == [] +@pytest.mark.redismod async def test_multi_label(decoded_r: redis.Redis): redis_graph = decoded_r.graph("g") @@ -375,6 +399,7 @@ async def test_multi_label(decoded_r: redis.Redis): assert True +@pytest.mark.redismod async def test_execution_plan(decoded_r: redis.Redis): redis_graph = decoded_r.graph("execution_plan") create_query = """CREATE @@ -393,6 +418,7 @@ async def test_execution_plan(decoded_r: redis.Redis): await redis_graph.delete() +@pytest.mark.redismod async def test_explain(decoded_r: redis.Redis): redis_graph = decoded_r.graph("execution_plan") # graph creation / population diff --git a/tests/test_asyncio/test_json.py b/tests/test_asyncio/test_json.py index 920ec71dce..c713f1aca2 100644 --- a/tests/test_asyncio/test_json.py +++ b/tests/test_asyncio/test_json.py @@ -1,10 +1,17 @@ import pytest +import pytest_asyncio import redis.asyncio as redis from redis import exceptions from redis.commands.json.path import Path from tests.conftest import assert_resp_response, skip_ifmodversion_lt +@pytest_asyncio.fixture() +async def decoded_r(create_redis, stack_url): + return await create_redis(decode_responses=True, url=stack_url) + + +@pytest.mark.redismod async def test_json_setbinarykey(decoded_r: redis.Redis): d = {"hello": "world", b"some": "value"} with pytest.raises(TypeError): @@ -12,6 +19,7 @@ async def test_json_setbinarykey(decoded_r: redis.Redis): assert await decoded_r.json().set("somekey", Path.root_path(), d, decode_keys=True) +@pytest.mark.redismod async def test_json_setgetdeleteforget(decoded_r: redis.Redis): assert await decoded_r.json().set("foo", Path.root_path(), "bar") assert_resp_response(decoded_r, await decoded_r.json().get("foo"), "bar", [["bar"]]) @@ -21,11 +29,13 @@ async def test_json_setgetdeleteforget(decoded_r: redis.Redis): assert await decoded_r.exists("foo") == 0 +@pytest.mark.redismod async def test_jsonget(decoded_r: redis.Redis): await decoded_r.json().set("foo", Path.root_path(), "bar") assert_resp_response(decoded_r, await decoded_r.json().get("foo"), "bar", [["bar"]]) +@pytest.mark.redismod async def test_json_get_jset(decoded_r: redis.Redis): assert await decoded_r.json().set("foo", Path.root_path(), "bar") assert_resp_response(decoded_r, await decoded_r.json().get("foo"), "bar", [["bar"]]) @@ -34,6 +44,7 @@ async def test_json_get_jset(decoded_r: redis.Redis): assert await decoded_r.exists("foo") == 0 +@pytest.mark.redismod async def test_nonascii_setgetdelete(decoded_r: redis.Redis): assert await decoded_r.json().set("notascii", Path.root_path(), "hyvää-élève") res = "hyvää-élève" @@ -44,6 +55,7 @@ async def test_nonascii_setgetdelete(decoded_r: redis.Redis): assert await decoded_r.exists("notascii") == 0 +@pytest.mark.redismod @skip_ifmodversion_lt("2.6.0", "ReJSON") async def test_json_merge(decoded_r: redis.Redis): # Test with root path $ @@ -78,6 +90,7 @@ async def test_json_merge(decoded_r: redis.Redis): } +@pytest.mark.redismod async def test_jsonsetexistentialmodifiersshouldsucceed(decoded_r: redis.Redis): obj = {"foo": "bar"} assert await decoded_r.json().set("obj", Path.root_path(), obj) @@ -95,6 +108,7 @@ async def test_jsonsetexistentialmodifiersshouldsucceed(decoded_r: redis.Redis): await decoded_r.json().set("obj", Path("foo"), "baz", nx=True, xx=True) +@pytest.mark.redismod async def test_mgetshouldsucceed(decoded_r: redis.Redis): await decoded_r.json().set("1", Path.root_path(), 1) await decoded_r.json().set("2", Path.root_path(), 2) @@ -104,6 +118,7 @@ async def test_mgetshouldsucceed(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("2.6.0", "ReJSON") async def test_mset(decoded_r: redis.Redis): await decoded_r.json().mset( @@ -114,6 +129,7 @@ async def test_mset(decoded_r: redis.Redis): assert await decoded_r.json().mget(["1", "2"], Path.root_path()) == [1, 2] +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "ReJSON") # todo: update after the release async def test_clear(decoded_r: redis.Redis): await decoded_r.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4]) @@ -121,6 +137,7 @@ async def test_clear(decoded_r: redis.Redis): assert_resp_response(decoded_r, await decoded_r.json().get("arr"), [], [[[]]]) +@pytest.mark.redismod async def test_type(decoded_r: redis.Redis): await decoded_r.json().set("1", Path.root_path(), 1) assert_resp_response( @@ -134,6 +151,7 @@ async def test_type(decoded_r: redis.Redis): ) +@pytest.mark.redismod async def test_numincrby(decoded_r): await decoded_r.json().set("num", Path.root_path(), 1) assert_resp_response( @@ -145,6 +163,7 @@ async def test_numincrby(decoded_r): assert_resp_response(decoded_r, res, 1.25, [1.25]) +@pytest.mark.redismod async def test_nummultby(decoded_r: redis.Redis): await decoded_r.json().set("num", Path.root_path(), 1) @@ -157,6 +176,7 @@ async def test_nummultby(decoded_r: redis.Redis): assert_resp_response(decoded_r, res, 2.5, [2.5]) +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "ReJSON") # todo: update after the release async def test_toggle(decoded_r: redis.Redis): await decoded_r.json().set("bool", Path.root_path(), False) @@ -168,6 +188,7 @@ async def test_toggle(decoded_r: redis.Redis): await decoded_r.json().toggle("num", Path.root_path()) +@pytest.mark.redismod async def test_strappend(decoded_r: redis.Redis): await decoded_r.json().set("jsonkey", Path.root_path(), "foo") assert 6 == await decoded_r.json().strappend("jsonkey", "bar") @@ -175,6 +196,7 @@ async def test_strappend(decoded_r: redis.Redis): assert_resp_response(decoded_r, res, "foobar", [["foobar"]]) +@pytest.mark.redismod async def test_strlen(decoded_r: redis.Redis): await decoded_r.json().set("str", Path.root_path(), "foo") assert 3 == await decoded_r.json().strlen("str", Path.root_path()) @@ -183,6 +205,7 @@ async def test_strlen(decoded_r: redis.Redis): assert 6 == await decoded_r.json().strlen("str") +@pytest.mark.redismod async def test_arrappend(decoded_r: redis.Redis): await decoded_r.json().set("arr", Path.root_path(), [1]) assert 2 == await decoded_r.json().arrappend("arr", Path.root_path(), 2) @@ -190,6 +213,7 @@ async def test_arrappend(decoded_r: redis.Redis): assert 7 == await decoded_r.json().arrappend("arr", Path.root_path(), *[5, 6, 7]) +@pytest.mark.redismod async def test_arrindex(decoded_r: redis.Redis): r_path = Path.root_path() await decoded_r.json().set("arr", r_path, [0, 1, 2, 3, 4]) @@ -202,6 +226,7 @@ async def test_arrindex(decoded_r: redis.Redis): assert -1 == await decoded_r.json().arrindex("arr", r_path, 4, start=1, stop=3) +@pytest.mark.redismod async def test_arrinsert(decoded_r: redis.Redis): await decoded_r.json().set("arr", Path.root_path(), [0, 4]) assert 5 == await decoded_r.json().arrinsert("arr", Path.root_path(), 1, *[1, 2, 3]) @@ -215,6 +240,7 @@ async def test_arrinsert(decoded_r: redis.Redis): assert_resp_response(decoded_r, await decoded_r.json().get("val2"), res, [[res]]) +@pytest.mark.redismod async def test_arrlen(decoded_r: redis.Redis): await decoded_r.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4]) assert 5 == await decoded_r.json().arrlen("arr", Path.root_path()) @@ -222,6 +248,7 @@ async def test_arrlen(decoded_r: redis.Redis): assert await decoded_r.json().arrlen("fakekey") is None +@pytest.mark.redismod async def test_arrpop(decoded_r: redis.Redis): await decoded_r.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4]) assert 4 == await decoded_r.json().arrpop("arr", Path.root_path(), 4) @@ -239,6 +266,7 @@ async def test_arrpop(decoded_r: redis.Redis): assert await decoded_r.json().arrpop("arr") is None +@pytest.mark.redismod async def test_arrtrim(decoded_r: redis.Redis): await decoded_r.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4]) assert 3 == await decoded_r.json().arrtrim("arr", Path.root_path(), 1, 3) @@ -262,6 +290,7 @@ async def test_arrtrim(decoded_r: redis.Redis): assert 0 == await decoded_r.json().arrtrim("arr", Path.root_path(), 9, 11) +@pytest.mark.redismod async def test_resp(decoded_r: redis.Redis): obj = {"foo": "bar", "baz": 1, "qaz": True} await decoded_r.json().set("obj", Path.root_path(), obj) @@ -271,6 +300,7 @@ async def test_resp(decoded_r: redis.Redis): assert isinstance(await decoded_r.json().resp("obj"), list) +@pytest.mark.redismod async def test_objkeys(decoded_r: redis.Redis): obj = {"foo": "bar", "baz": "qaz"} await decoded_r.json().set("obj", Path.root_path(), obj) @@ -287,6 +317,7 @@ async def test_objkeys(decoded_r: redis.Redis): assert await decoded_r.json().objkeys("fakekey") is None +@pytest.mark.redismod async def test_objlen(decoded_r: redis.Redis): obj = {"foo": "bar", "baz": "qaz"} await decoded_r.json().set("obj", Path.root_path(), obj) @@ -320,6 +351,7 @@ async def test_objlen(decoded_r: redis.Redis): # assert await decoded_r.get("foo") is None +@pytest.mark.redismod async def test_json_delete_with_dollar(decoded_r: redis.Redis): doc1 = {"a": 1, "nested": {"a": 2, "b": 3}} assert await decoded_r.json().set("doc1", "$", doc1) @@ -373,6 +405,7 @@ async def test_json_delete_with_dollar(decoded_r: redis.Redis): await decoded_r.json().delete("not_a_document", "..a") +@pytest.mark.redismod async def test_json_forget_with_dollar(decoded_r: redis.Redis): doc1 = {"a": 1, "nested": {"a": 2, "b": 3}} assert await decoded_r.json().set("doc1", "$", doc1) @@ -426,6 +459,7 @@ async def test_json_forget_with_dollar(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod async def test_json_mget_dollar(decoded_r: redis.Redis): # Test mget with multi paths await decoded_r.json().set( @@ -461,6 +495,7 @@ async def test_json_mget_dollar(decoded_r: redis.Redis): assert res == [None, None] +@pytest.mark.redismod async def test_numby_commands_dollar(decoded_r: redis.Redis): # Test NUMINCRBY await decoded_r.json().set( @@ -515,6 +550,7 @@ async def test_numby_commands_dollar(decoded_r: redis.Redis): await decoded_r.json().nummultby("doc1", ".b[0].a", 3) == 6 +@pytest.mark.redismod async def test_strappend_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", "$", {"a": "foo", "nested1": {"a": "hello"}, "nested2": {"a": 31}} @@ -545,6 +581,7 @@ async def test_strappend_dollar(decoded_r: redis.Redis): await decoded_r.json().strappend("doc1", "piu") +@pytest.mark.redismod async def test_strlen_dollar(decoded_r: redis.Redis): # Test multi await decoded_r.json().set( @@ -565,6 +602,7 @@ async def test_strlen_dollar(decoded_r: redis.Redis): await decoded_r.json().strlen("non_existing_doc", "$..a") +@pytest.mark.redismod async def test_arrappend_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", @@ -638,6 +676,7 @@ async def test_arrappend_dollar(decoded_r: redis.Redis): await decoded_r.json().arrappend("non_existing_doc", "$..a") +@pytest.mark.redismod async def test_arrinsert_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", @@ -676,6 +715,7 @@ async def test_arrinsert_dollar(decoded_r: redis.Redis): await decoded_r.json().arrappend("non_existing_doc", "$..a") +@pytest.mark.redismod async def test_arrlen_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", @@ -721,6 +761,7 @@ async def test_arrlen_dollar(decoded_r: redis.Redis): assert await decoded_r.json().arrlen("non_existing_doc", "..a") is None +@pytest.mark.redismod async def test_arrpop_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", @@ -762,6 +803,7 @@ async def test_arrpop_dollar(decoded_r: redis.Redis): await decoded_r.json().arrpop("non_existing_doc", "..a") +@pytest.mark.redismod async def test_arrtrim_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", @@ -813,6 +855,7 @@ async def test_arrtrim_dollar(decoded_r: redis.Redis): await decoded_r.json().arrtrim("non_existing_doc", "..a", 1, 1) +@pytest.mark.redismod async def test_objkeys_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", @@ -842,6 +885,7 @@ async def test_objkeys_dollar(decoded_r: redis.Redis): assert await decoded_r.json().objkeys("doc1", "$..nowhere") == [] +@pytest.mark.redismod async def test_objlen_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", @@ -896,6 +940,7 @@ def load_types_data(nested_key_name): return jdata, types +@pytest.mark.redismod async def test_type_dollar(decoded_r: redis.Redis): jdata, jtypes = load_types_data("a") await decoded_r.json().set("doc1", "$", jdata) @@ -914,6 +959,7 @@ async def test_type_dollar(decoded_r: redis.Redis): ) +@pytest.mark.redismod async def test_clear_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", @@ -967,6 +1013,7 @@ async def test_clear_dollar(decoded_r: redis.Redis): await decoded_r.json().clear("non_existing_doc", "$..a") +@pytest.mark.redismod async def test_toggle_dollar(decoded_r: redis.Redis): await decoded_r.json().set( "doc1", diff --git a/tests/test_asyncio/test_search.py b/tests/test_asyncio/test_search.py index 8d42d08b66..4cc00c8e5f 100644 --- a/tests/test_asyncio/test_search.py +++ b/tests/test_asyncio/test_search.py @@ -5,6 +5,7 @@ from io import TextIOWrapper import pytest +import pytest_asyncio import redis.asyncio as redis import redis.commands.search import redis.commands.search.aggregation as aggregations @@ -31,6 +32,11 @@ ) +@pytest_asyncio.fixture() +async def decoded_r(create_redis, stack_url): + return await create_redis(decode_responses=True, url=stack_url) + + async def waitForIndex(env, idx, timeout=None): delay = 0.1 while True: diff --git a/tests/test_asyncio/test_timeseries.py b/tests/test_asyncio/test_timeseries.py index b44219707e..0c78ce0941 100644 --- a/tests/test_asyncio/test_timeseries.py +++ b/tests/test_asyncio/test_timeseries.py @@ -2,6 +2,7 @@ from time import sleep import pytest +import pytest_asyncio import redis.asyncio as redis from tests.conftest import ( assert_resp_response, @@ -10,6 +11,12 @@ ) +@pytest_asyncio.fixture() +async def decoded_r(create_redis, stack_url): + return await create_redis(decode_responses=True, url=stack_url) + + +@pytest.mark.redismod async def test_create(decoded_r: redis.Redis): assert await decoded_r.ts().create(1) assert await decoded_r.ts().create(2, retention_msecs=5) @@ -27,6 +34,7 @@ async def test_create(decoded_r: redis.Redis): assert_resp_response(decoded_r, 128, info.get("chunk_size"), info.get("chunkSize")) +@pytest.mark.redismod @skip_ifmodversion_lt("1.4.0", "timeseries") async def test_create_duplicate_policy(decoded_r: redis.Redis): # Test for duplicate policy @@ -42,6 +50,7 @@ async def test_create_duplicate_policy(decoded_r: redis.Redis): ) +@pytest.mark.redismod async def test_alter(decoded_r: redis.Redis): assert await decoded_r.ts().create(1) res = await decoded_r.ts().info(1) @@ -64,6 +73,7 @@ async def test_alter(decoded_r: redis.Redis): ) +@pytest.mark.redismod @skip_ifmodversion_lt("1.4.0", "timeseries") async def test_alter_diplicate_policy(decoded_r: redis.Redis): assert await decoded_r.ts().create(1) @@ -78,6 +88,7 @@ async def test_alter_diplicate_policy(decoded_r: redis.Redis): ) +@pytest.mark.redismod async def test_add(decoded_r: redis.Redis): assert 1 == await decoded_r.ts().add(1, 1, 1) assert 2 == await decoded_r.ts().add(2, 2, 3, retention_msecs=10) @@ -100,6 +111,7 @@ async def test_add(decoded_r: redis.Redis): assert_resp_response(decoded_r, 128, info.get("chunk_size"), info.get("chunkSize")) +@pytest.mark.redismod @skip_ifmodversion_lt("1.4.0", "timeseries") async def test_add_duplicate_policy(r: redis.Redis): # Test for duplicate policy BLOCK @@ -140,6 +152,7 @@ async def test_add_duplicate_policy(r: redis.Redis): assert 5.0 == res[1] +@pytest.mark.redismod async def test_madd(decoded_r: redis.Redis): await decoded_r.ts().create("a") assert [1, 2, 3] == await decoded_r.ts().madd( @@ -147,6 +160,7 @@ async def test_madd(decoded_r: redis.Redis): ) +@pytest.mark.redismod async def test_incrby_decrby(decoded_r: redis.Redis): for _ in range(100): assert await decoded_r.ts().incrby(1, 1) @@ -175,6 +189,7 @@ async def test_incrby_decrby(decoded_r: redis.Redis): assert_resp_response(decoded_r, 128, info.get("chunk_size"), info.get("chunkSize")) +@pytest.mark.redismod async def test_create_and_delete_rule(decoded_r: redis.Redis): # test rule creation time = 100 @@ -198,6 +213,7 @@ async def test_create_and_delete_rule(decoded_r: redis.Redis): assert not info["rules"] +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") async def test_del_range(decoded_r: redis.Redis): try: @@ -214,20 +230,24 @@ async def test_del_range(decoded_r: redis.Redis): ) -async def test_range(r: redis.Redis): +@pytest.mark.redismod +async def test_range(decoded_r: redis.Redis): for i in range(100): - await r.ts().add(1, i, i % 7) - assert 100 == len(await r.ts().range(1, 0, 200)) + await decoded_r.ts().add(1, i, i % 7) + assert 100 == len(await decoded_r.ts().range(1, 0, 200)) for i in range(100): - await r.ts().add(1, i + 200, i % 7) - assert 200 == len(await r.ts().range(1, 0, 500)) + await decoded_r.ts().add(1, i + 200, i % 7) + assert 200 == len(await decoded_r.ts().range(1, 0, 500)) # last sample isn't returned assert 20 == len( - await r.ts().range(1, 0, 500, aggregation_type="avg", bucket_size_msec=10) + await decoded_r.ts().range( + 1, 0, 500, aggregation_type="avg", bucket_size_msec=10 + ) ) - assert 10 == len(await r.ts().range(1, 0, 500, count=10)) + assert 10 == len(await decoded_r.ts().range(1, 0, 500, count=10)) +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") async def test_range_advanced(decoded_r: redis.Redis): for i in range(100): @@ -258,6 +278,7 @@ async def test_range_advanced(decoded_r: redis.Redis): assert_resp_response(decoded_r, res, [(0, 2.55), (10, 3.0)], [[0, 2.55], [10, 3.0]]) +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") async def test_rev_range(decoded_r: redis.Redis): for i in range(100): @@ -302,6 +323,7 @@ async def test_rev_range(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod async def test_multi_range(decoded_r: redis.Redis): await decoded_r.ts().create(1, labels={"Test": "This", "team": "ny"}) await decoded_r.ts().create( @@ -356,6 +378,7 @@ async def test_multi_range(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") async def test_multi_range_advanced(decoded_r: redis.Redis): await decoded_r.ts().create(1, labels={"Test": "This", "team": "ny"}) @@ -473,6 +496,7 @@ async def test_multi_range_advanced(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") async def test_multi_reverse_range(decoded_r: redis.Redis): await decoded_r.ts().create(1, labels={"Test": "This", "team": "ny"}) @@ -635,6 +659,7 @@ async def test_multi_reverse_range(decoded_r: redis.Redis): assert [[1, 10.0], [0, 1.0]] == res["1"][2] +@pytest.mark.redismod async def test_get(decoded_r: redis.Redis): name = "test" await decoded_r.ts().create(name) @@ -646,6 +671,7 @@ async def test_get(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod async def test_mget(decoded_r: redis.Redis): await decoded_r.ts().create(1, labels={"Test": "This"}) await decoded_r.ts().create(2, labels={"Test": "This", "Taste": "That"}) @@ -680,6 +706,7 @@ async def test_mget(decoded_r: redis.Redis): assert {"Taste": "That", "Test": "This"} == res["2"][0] +@pytest.mark.redismod async def test_info(decoded_r: redis.Redis): await decoded_r.ts().create( 1, retention_msecs=5, labels={"currentLabel": "currentData"} @@ -691,8 +718,9 @@ async def test_info(decoded_r: redis.Redis): assert info["labels"]["currentLabel"] == "currentData" +@pytest.mark.redismod @skip_ifmodversion_lt("1.4.0", "timeseries") -async def testInfoDuplicatePolicy(decoded_r: redis.Redis): +async def test_info_duplicate_policy(decoded_r: redis.Redis): await decoded_r.ts().create( 1, retention_msecs=5, labels={"currentLabel": "currentData"} ) @@ -709,6 +737,7 @@ async def testInfoDuplicatePolicy(decoded_r: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod async def test_query_index(decoded_r: redis.Redis): await decoded_r.ts().create(1, labels={"Test": "This"}) await decoded_r.ts().create(2, labels={"Test": "This", "Taste": "That"}) @@ -719,19 +748,7 @@ async def test_query_index(decoded_r: redis.Redis): ) -# # async def test_pipeline(r: redis.Redis): -# pipeline = await r.ts().pipeline() -# pipeline.create("with_pipeline") -# for i in range(100): -# pipeline.add("with_pipeline", i, 1.1 * i) -# pipeline.execute() - -# info = await r.ts().info("with_pipeline") -# assert info.lastTimeStamp == 99 -# assert info.total_samples == 100 -# assert await r.ts().get("with_pipeline")[1] == 99 * 1.1 - - +@pytest.mark.redismod async def test_uncompressed(decoded_r: redis.Redis): await decoded_r.ts().create("compressed") await decoded_r.ts().create("uncompressed", uncompressed=True) diff --git a/tests/test_bloom.py b/tests/test_bloom.py index 464a946f54..d1a0484225 100644 --- a/tests/test_bloom.py +++ b/tests/test_bloom.py @@ -5,7 +5,20 @@ from redis.exceptions import ModuleError, RedisError from redis.utils import HIREDIS_AVAILABLE -from .conftest import assert_resp_response, is_resp2_connection, skip_ifmodversion_lt +from .conftest import ( + _get_client, + assert_resp_response, + is_resp2_connection, + skip_ifmodversion_lt, +) + + +@pytest.fixture() +def decoded_r(request, stack_url): + with _get_client( + redis.Redis, request, decode_responses=True, from_url=stack_url + ) as client: + yield client def intlist(obj): @@ -24,6 +37,7 @@ def client(decoded_r): return decoded_r +@pytest.mark.redismod def test_create(client): """Test CREATE/RESERVE calls""" assert client.bf().create("bloom", 0.01, 1000) @@ -38,6 +52,7 @@ def test_create(client): assert client.topk().reserve("topk", 5, 100, 5, 0.9) +@pytest.mark.redismod def test_bf_reserve(client): """Testing BF.RESERVE""" assert client.bf().reserve("bloom", 0.01, 1000) @@ -53,10 +68,12 @@ def test_bf_reserve(client): @pytest.mark.experimental +@pytest.mark.redismod def test_tdigest_create(client): assert client.tdigest().create("tDigest", 100) +@pytest.mark.redismod def test_bf_add(client): assert client.bf().create("bloom", 0.01, 1000) assert 1 == client.bf().add("bloom", "foo") @@ -69,6 +86,7 @@ def test_bf_add(client): assert [1, 0] == intlist(client.bf().mexists("bloom", "foo", "noexist")) +@pytest.mark.redismod def test_bf_insert(client): assert client.bf().create("bloom", 0.01, 1000) assert [1] == intlist(client.bf().insert("bloom", ["foo"])) @@ -99,6 +117,7 @@ def test_bf_insert(client): ) +@pytest.mark.redismod def test_bf_scandump_and_loadchunk(client): # Store a filter client.bf().create("myBloom", "0.0001", "1000") @@ -150,6 +169,7 @@ def do_verify(): client.bf().create("myBloom", "0.0001", "10000000") +@pytest.mark.redismod def test_bf_info(client): expansion = 4 # Store a filter @@ -181,6 +201,7 @@ def test_bf_info(client): assert True +@pytest.mark.redismod def test_bf_card(client): # return 0 if the key does not exist assert client.bf().card("not_exist") == 0 @@ -195,6 +216,7 @@ def test_bf_card(client): client.bf().card("setKey") +@pytest.mark.redismod def test_cf_add_and_insert(client): assert client.cf().create("cuckoo", 1000) assert client.cf().add("cuckoo", "filter") @@ -220,6 +242,7 @@ def test_cf_add_and_insert(client): ) +@pytest.mark.redismod def test_cf_exists_and_del(client): assert client.cf().create("cuckoo", 1000) assert client.cf().add("cuckoo", "filter") @@ -232,6 +255,7 @@ def test_cf_exists_and_del(client): assert 0 == client.cf().count("cuckoo", "filter") +@pytest.mark.redismod def test_cms(client): assert client.cms().initbydim("dim", 1000, 5) assert client.cms().initbyprob("prob", 0.01, 0.01) @@ -248,6 +272,7 @@ def test_cms(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod def test_cms_merge(client): assert client.cms().initbydim("A", 1000, 5) assert client.cms().initbydim("B", 1000, 5) @@ -264,6 +289,7 @@ def test_cms_merge(client): assert [16, 15, 21] == client.cms().query("C", "foo", "bar", "baz") +@pytest.mark.redismod def test_topk(client): # test list with empty buckets assert client.topk().reserve("topk", 3, 50, 4, 0.9) @@ -343,6 +369,7 @@ def test_topk(client): assert 0.9 == round(float(info["decay"]), 1) +@pytest.mark.redismod def test_topk_incrby(client): client.flushdb() assert client.topk().reserve("topk", 3, 10, 3, 1) @@ -357,6 +384,7 @@ def test_topk_incrby(client): @pytest.mark.experimental +@pytest.mark.redismod def test_tdigest_reset(client): assert client.tdigest().create("tDigest", 10) # reset on empty histogram @@ -373,6 +401,7 @@ def test_tdigest_reset(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod def test_tdigest_merge(client): assert client.tdigest().create("to-tDigest", 10) assert client.tdigest().create("from-tDigest", 10) @@ -400,6 +429,7 @@ def test_tdigest_merge(client): @pytest.mark.experimental +@pytest.mark.redismod def test_tdigest_min_and_max(client): assert client.tdigest().create("tDigest", 100) # insert data-points into sketch @@ -410,6 +440,7 @@ def test_tdigest_min_and_max(client): @pytest.mark.experimental +@pytest.mark.redismod @skip_ifmodversion_lt("2.4.0", "bf") def test_tdigest_quantile(client): assert client.tdigest().create("tDigest", 500) @@ -431,6 +462,7 @@ def test_tdigest_quantile(client): @pytest.mark.experimental +@pytest.mark.redismod def test_tdigest_cdf(client): assert client.tdigest().create("tDigest", 100) # insert data-points into sketch @@ -442,6 +474,7 @@ def test_tdigest_cdf(client): @pytest.mark.experimental +@pytest.mark.redismod @skip_ifmodversion_lt("2.4.0", "bf") def test_tdigest_trimmed_mean(client): assert client.tdigest().create("tDigest", 100) @@ -452,6 +485,7 @@ def test_tdigest_trimmed_mean(client): @pytest.mark.experimental +@pytest.mark.redismod def test_tdigest_rank(client): assert client.tdigest().create("t-digest", 500) assert client.tdigest().add("t-digest", list(range(0, 20))) @@ -462,6 +496,7 @@ def test_tdigest_rank(client): @pytest.mark.experimental +@pytest.mark.redismod def test_tdigest_revrank(client): assert client.tdigest().create("t-digest", 500) assert client.tdigest().add("t-digest", list(range(0, 20))) @@ -471,6 +506,7 @@ def test_tdigest_revrank(client): @pytest.mark.experimental +@pytest.mark.redismod def test_tdigest_byrank(client): assert client.tdigest().create("t-digest", 500) assert client.tdigest().add("t-digest", list(range(1, 11))) @@ -482,6 +518,7 @@ def test_tdigest_byrank(client): @pytest.mark.experimental +@pytest.mark.redismod def test_tdigest_byrevrank(client): assert client.tdigest().create("t-digest", 500) assert client.tdigest().add("t-digest", list(range(1, 11))) diff --git a/tests/test_cluster.py b/tests/test_cluster.py index 1f505b816d..d41ebcd506 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -2450,6 +2450,7 @@ def try_delete_libs(self, r, *lib_names): except Exception: pass + @pytest.mark.redismod @skip_if_server_version_lt("7.1.140") def test_tfunction_load_delete(self, r): r.gears_refresh_cluster() @@ -2458,6 +2459,7 @@ def test_tfunction_load_delete(self, r): assert r.tfunction_load(lib_code) assert r.tfunction_delete("lib1") + @pytest.mark.redismod @skip_if_server_version_lt("7.1.140") def test_tfunction_list(self, r): r.gears_refresh_cluster() @@ -2481,6 +2483,7 @@ def test_tfunction_list(self, r): assert r.tfunction_delete("lib2") assert r.tfunction_delete("lib3") + @pytest.mark.redismod @skip_if_server_version_lt("7.1.140") def test_tfcall(self, r): r.gears_refresh_cluster() diff --git a/tests/test_commands.py b/tests/test_commands.py index 54df183fc6..8fbec5fb7e 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -1818,44 +1818,44 @@ def try_delete_libs(self, r, *lib_names): @pytest.mark.onlynoncluster @skip_if_server_version_lt("7.1.140") - def test_tfunction_load_delete(self, r): - self.try_delete_libs(r, "lib1") + def test_tfunction_load_delete(self, stack_r): + self.try_delete_libs(stack_r, "lib1") lib_code = self.generate_lib_code("lib1") - assert r.tfunction_load(lib_code) - assert r.tfunction_delete("lib1") + assert stack_r.tfunction_load(lib_code) + assert stack_r.tfunction_delete("lib1") @pytest.mark.onlynoncluster @skip_if_server_version_lt("7.1.140") - def test_tfunction_list(self, r): - self.try_delete_libs(r, "lib1", "lib2", "lib3") - assert r.tfunction_load(self.generate_lib_code("lib1")) - assert r.tfunction_load(self.generate_lib_code("lib2")) - assert r.tfunction_load(self.generate_lib_code("lib3")) + def test_tfunction_list(self, stack_r): + self.try_delete_libs(stack_r, "lib1", "lib2", "lib3") + assert stack_r.tfunction_load(self.generate_lib_code("lib1")) + assert stack_r.tfunction_load(self.generate_lib_code("lib2")) + assert stack_r.tfunction_load(self.generate_lib_code("lib3")) # test error thrown when verbose > 4 with pytest.raises(redis.exceptions.DataError): - assert r.tfunction_list(verbose=8) + assert stack_r.tfunction_list(verbose=8) - functions = r.tfunction_list(verbose=1) + functions = stack_r.tfunction_list(verbose=1) assert len(functions) == 3 expected_names = [b"lib1", b"lib2", b"lib3"] actual_names = [functions[0][13], functions[1][13], functions[2][13]] assert sorted(expected_names) == sorted(actual_names) - assert r.tfunction_delete("lib1") - assert r.tfunction_delete("lib2") - assert r.tfunction_delete("lib3") + assert stack_r.tfunction_delete("lib1") + assert stack_r.tfunction_delete("lib2") + assert stack_r.tfunction_delete("lib3") @pytest.mark.onlynoncluster @skip_if_server_version_lt("7.1.140") - def test_tfcall(self, r): - self.try_delete_libs(r, "lib1") - assert r.tfunction_load(self.generate_lib_code("lib1")) - assert r.tfcall("lib1", "foo") == b"bar" - assert r.tfcall_async("lib1", "foo") == b"bar" + def test_tfcall(self, stack_r): + self.try_delete_libs(stack_r, "lib1") + assert stack_r.tfunction_load(self.generate_lib_code("lib1")) + assert stack_r.tfcall("lib1", "foo") == b"bar" + assert stack_r.tfcall_async("lib1", "foo") == b"bar" - assert r.tfunction_delete("lib1") + assert stack_r.tfunction_delete("lib1") def test_ttl(self, r): r["a"] = "1" @@ -5022,25 +5022,27 @@ def test_command_getkeysandflags(self, r: redis.Redis): @pytest.mark.onlynoncluster @skip_if_server_version_lt("4.0.0") @skip_if_redis_enterprise() - def test_module(self, r): + def test_module(self, stack_r): with pytest.raises(redis.exceptions.ModuleError) as excinfo: - r.module_load("/some/fake/path") + stack_r.module_load("/some/fake/path") assert "Error loading the extension." in str(excinfo.value) with pytest.raises(redis.exceptions.ModuleError) as excinfo: - r.module_load("/some/fake/path", "arg1", "arg2", "arg3", "arg4") + stack_r.module_load("/some/fake/path", "arg1", "arg2", "arg3", "arg4") assert "Error loading the extension." in str(excinfo.value) @pytest.mark.onlynoncluster @skip_if_server_version_lt("7.0.0") @skip_if_redis_enterprise() - def test_module_loadex(self, r: redis.Redis): + def test_module_loadex(self, stack_r: redis.Redis): with pytest.raises(redis.exceptions.ModuleError) as excinfo: - r.module_loadex("/some/fake/path") + stack_r.module_loadex("/some/fake/path") assert "Error loading the extension." in str(excinfo.value) with pytest.raises(redis.exceptions.ModuleError) as excinfo: - r.module_loadex("/some/fake/path", ["name", "value"], ["arg1", "arg2"]) + stack_r.module_loadex( + "/some/fake/path", ["name", "value"], ["arg1", "arg2"] + ) assert "Error loading the extension." in str(excinfo.value) @skip_if_server_version_lt("2.6.0") diff --git a/tests/test_graph.py b/tests/test_graph.py index c6d128908e..2eace0181c 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -24,18 +24,20 @@ @pytest.fixture -def client(request): - r = _get_client(Redis, request, decode_responses=True) +def client(request, stack_url): + r = _get_client(Redis, request, decode_responses=True, from_url=stack_url) r.flushdb() return r +@pytest.mark.redismod def test_bulk(client): with pytest.raises(NotImplementedError): client.graph().bulk() client.graph().bulk(foo="bar!") +@pytest.mark.redismod def test_graph_creation(client): graph = client.graph() @@ -80,6 +82,7 @@ def test_graph_creation(client): graph.delete() +@pytest.mark.redismod def test_array_functions(client): query = """CREATE (p:person{name:'a',age:32, array:[0,1,2]})""" client.graph().query(query) @@ -100,6 +103,7 @@ def test_array_functions(client): assert [a] == result.result_set[0][0] +@pytest.mark.redismod def test_path(client): node0 = Node(node_id=0, label="L1") node1 = Node(node_id=1, label="L1") @@ -119,6 +123,7 @@ def test_path(client): assert expected_results == result.result_set +@pytest.mark.redismod def test_param(client): params = [1, 2.3, "str", True, False, None, [0, 1, 2], r"\" RETURN 1337 //"] query = "RETURN $param" @@ -128,6 +133,7 @@ def test_param(client): assert expected_results == result.result_set +@pytest.mark.redismod def test_map(client): query = "RETURN {a:1, b:'str', c:NULL, d:[1,2,3], e:True, f:{x:1, y:2}}" @@ -144,6 +150,7 @@ def test_map(client): assert actual == expected +@pytest.mark.redismod def test_point(client): query = "RETURN point({latitude: 32.070794860, longitude: 34.820751118})" expected_lat = 32.070794860 @@ -160,6 +167,7 @@ def test_point(client): assert abs(actual["longitude"] - expected_lon) < 0.001 +@pytest.mark.redismod def test_index_response(client): result_set = client.graph().query("CREATE INDEX ON :person(age)") assert 1 == result_set.indices_created @@ -174,6 +182,7 @@ def test_index_response(client): client.graph().query("DROP INDEX ON :person(age)") +@pytest.mark.redismod def test_stringify_query_result(client): graph = client.graph() @@ -227,6 +236,7 @@ def test_stringify_query_result(client): graph.delete() +@pytest.mark.redismod def test_optional_match(client): # Build a graph of form (a)-[R]->(b) node0 = Node(node_id=0, label="L1", properties={"value": "a"}) @@ -251,6 +261,7 @@ def test_optional_match(client): graph.delete() +@pytest.mark.redismod def test_cached_execution(client): client.graph().query("CREATE ()") @@ -268,6 +279,7 @@ def test_cached_execution(client): assert cached_result.cached_execution +@pytest.mark.redismod def test_slowlog(client): create_query = """CREATE (:Rider {name:'Valentino Rossi'})-[:rides]->(:Team {name:'Yamaha'}), @@ -280,6 +292,7 @@ def test_slowlog(client): assert results[0][2] == create_query +@pytest.mark.redismod @pytest.mark.xfail(strict=False) def test_query_timeout(client): # Build a sample graph with 1000 nodes. @@ -294,6 +307,7 @@ def test_query_timeout(client): assert False is False +@pytest.mark.redismod def test_read_only_query(client): with pytest.raises(Exception): # Issue a write query, specifying read-only true, @@ -302,6 +316,7 @@ def test_read_only_query(client): assert False is False +@pytest.mark.redismod def test_profile(client): q = """UNWIND range(1, 3) AS x CREATE (p:Person {v:x})""" profile = client.graph().profile(q).result_set @@ -316,6 +331,7 @@ def test_profile(client): assert "Node By Label Scan | (p:Person) | Records produced: 3" in profile +@pytest.mark.redismod @skip_if_redis_enterprise() def test_config(client): config_name = "RESULTSET_SIZE" @@ -348,6 +364,7 @@ def test_config(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod def test_list_keys(client): result = client.graph().list_keys() assert result == [] @@ -370,6 +387,7 @@ def test_list_keys(client): assert result == [] +@pytest.mark.redismod def test_multi_label(client): redis_graph = client.graph("g") @@ -395,6 +413,7 @@ def test_multi_label(client): assert True +@pytest.mark.redismod def test_cache_sync(client): pass return @@ -467,6 +486,7 @@ def test_cache_sync(client): assert A._relationship_types[1] == "R" +@pytest.mark.redismod def test_execution_plan(client): redis_graph = client.graph("execution_plan") create_query = """CREATE @@ -485,6 +505,7 @@ def test_execution_plan(client): redis_graph.delete() +@pytest.mark.redismod def test_explain(client): redis_graph = client.graph("execution_plan") # graph creation / population @@ -573,6 +594,7 @@ def test_explain(client): redis_graph.delete() +@pytest.mark.redismod def test_resultset_statistics(client): with patch.object(target=QueryResult, attribute="_get_stat") as mock_get_stats: result = client.graph().query("RETURN 1") diff --git a/tests/test_json.py b/tests/test_json.py index 73d72b8cc9..5cf9b11e17 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -8,12 +8,13 @@ @pytest.fixture -def client(request): - r = _get_client(Redis, request, decode_responses=True) +def client(request, stack_url): + r = _get_client(Redis, request, decode_responses=True, from_url=stack_url) r.flushdb() return r +@pytest.mark.redismod def test_json_setbinarykey(client): d = {"hello": "world", b"some": "value"} with pytest.raises(TypeError): @@ -21,6 +22,7 @@ def test_json_setbinarykey(client): assert client.json().set("somekey", Path.root_path(), d, decode_keys=True) +@pytest.mark.redismod def test_json_setgetdeleteforget(client): assert client.json().set("foo", Path.root_path(), "bar") assert_resp_response(client, client.json().get("foo"), "bar", [["bar"]]) @@ -30,11 +32,13 @@ def test_json_setgetdeleteforget(client): assert client.exists("foo") == 0 +@pytest.mark.redismod def test_jsonget(client): client.json().set("foo", Path.root_path(), "bar") assert_resp_response(client, client.json().get("foo"), "bar", [["bar"]]) +@pytest.mark.redismod def test_json_get_jset(client): assert client.json().set("foo", Path.root_path(), "bar") assert_resp_response(client, client.json().get("foo"), "bar", [["bar"]]) @@ -43,6 +47,7 @@ def test_json_get_jset(client): assert client.exists("foo") == 0 +@pytest.mark.redismod @skip_ifmodversion_lt("2.06.00", "ReJSON") # todo: update after the release def test_json_merge(client): # Test with root path $ @@ -75,6 +80,7 @@ def test_json_merge(client): } +@pytest.mark.redismod def test_nonascii_setgetdelete(client): assert client.json().set("notascii", Path.root_path(), "hyvää-élève") res = "hyvää-élève" @@ -85,6 +91,7 @@ def test_nonascii_setgetdelete(client): assert client.exists("notascii") == 0 +@pytest.mark.redismod def test_jsonsetexistentialmodifiersshouldsucceed(client): obj = {"foo": "bar"} assert client.json().set("obj", Path.root_path(), obj) @@ -102,6 +109,7 @@ def test_jsonsetexistentialmodifiersshouldsucceed(client): client.json().set("obj", Path("foo"), "baz", nx=True, xx=True) +@pytest.mark.redismod def test_mgetshouldsucceed(client): client.json().set("1", Path.root_path(), 1) client.json().set("2", Path.root_path(), 2) @@ -111,6 +119,7 @@ def test_mgetshouldsucceed(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("2.06.00", "ReJSON") def test_mset(client): client.json().mset([("1", Path.root_path(), 1), ("2", Path.root_path(), 2)]) @@ -119,6 +128,7 @@ def test_mset(client): assert client.json().mget(["1", "2"], Path.root_path()) == [1, 2] +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "ReJSON") # todo: update after the release def test_clear(client): client.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4]) @@ -126,6 +136,7 @@ def test_clear(client): assert_resp_response(client, client.json().get("arr"), [], [[[]]]) +@pytest.mark.redismod def test_type(client): client.json().set("1", Path.root_path(), 1) assert_resp_response( @@ -134,6 +145,7 @@ def test_type(client): assert_resp_response(client, client.json().type("1"), "integer", ["integer"]) +@pytest.mark.redismod def test_numincrby(client): client.json().set("num", Path.root_path(), 1) assert_resp_response( @@ -147,6 +159,7 @@ def test_numincrby(client): ) +@pytest.mark.redismod def test_nummultby(client): client.json().set("num", Path.root_path(), 1) @@ -162,6 +175,7 @@ def test_nummultby(client): ) +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "ReJSON") # todo: update after the release def test_toggle(client): client.json().set("bool", Path.root_path(), False) @@ -173,6 +187,7 @@ def test_toggle(client): client.json().toggle("num", Path.root_path()) +@pytest.mark.redismod def test_strappend(client): client.json().set("jsonkey", Path.root_path(), "foo") assert 6 == client.json().strappend("jsonkey", "bar") @@ -181,15 +196,7 @@ def test_strappend(client): ) -# # def test_debug(client): -# client.json().set("str", Path.root_path(), "foo") -# assert 24 == client.json().debug("MEMORY", "str", Path.root_path()) -# assert 24 == client.json().debug("MEMORY", "str") -# -# # technically help is valid -# assert isinstance(client.json().debug("HELP"), list) - - +@pytest.mark.redismod def test_strlen(client): client.json().set("str", Path.root_path(), "foo") assert 3 == client.json().strlen("str", Path.root_path()) @@ -198,6 +205,7 @@ def test_strlen(client): assert 6 == client.json().strlen("str") +@pytest.mark.redismod def test_arrappend(client): client.json().set("arr", Path.root_path(), [1]) assert 2 == client.json().arrappend("arr", Path.root_path(), 2) @@ -205,6 +213,7 @@ def test_arrappend(client): assert 7 == client.json().arrappend("arr", Path.root_path(), *[5, 6, 7]) +@pytest.mark.redismod def test_arrindex(client): client.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4]) assert 1 == client.json().arrindex("arr", Path.root_path(), 1) @@ -216,6 +225,7 @@ def test_arrindex(client): assert -1 == client.json().arrindex("arr", Path.root_path(), 4, start=1, stop=3) +@pytest.mark.redismod def test_arrinsert(client): client.json().set("arr", Path.root_path(), [0, 4]) assert 5 - -client.json().arrinsert("arr", Path.root_path(), 1, *[1, 2, 3]) @@ -229,6 +239,7 @@ def test_arrinsert(client): assert_resp_response(client, client.json().get("val2"), res, [[res]]) +@pytest.mark.redismod def test_arrlen(client): client.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4]) assert 5 == client.json().arrlen("arr", Path.root_path()) @@ -236,6 +247,7 @@ def test_arrlen(client): assert client.json().arrlen("fakekey") is None +@pytest.mark.redismod def test_arrpop(client): client.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4]) assert 4 == client.json().arrpop("arr", Path.root_path(), 4) @@ -253,6 +265,7 @@ def test_arrpop(client): assert client.json().arrpop("arr") is None +@pytest.mark.redismod def test_arrtrim(client): client.json().set("arr", Path.root_path(), [0, 1, 2, 3, 4]) assert 3 == client.json().arrtrim("arr", Path.root_path(), 1, 3) @@ -275,6 +288,7 @@ def test_arrtrim(client): assert 0 == client.json().arrtrim("arr", Path.root_path(), 9, 11) +@pytest.mark.redismod def test_resp(client): obj = {"foo": "bar", "baz": 1, "qaz": True} client.json().set("obj", Path.root_path(), obj) @@ -284,6 +298,7 @@ def test_resp(client): assert isinstance(client.json().resp("obj"), list) +@pytest.mark.redismod def test_objkeys(client): obj = {"foo": "bar", "baz": "qaz"} client.json().set("obj", Path.root_path(), obj) @@ -300,6 +315,7 @@ def test_objkeys(client): assert client.json().objkeys("fakekey") is None +@pytest.mark.redismod def test_objlen(client): obj = {"foo": "bar", "baz": "qaz"} client.json().set("obj", Path.root_path(), obj) @@ -309,6 +325,7 @@ def test_objlen(client): assert len(obj) == client.json().objlen("obj") +@pytest.mark.redismod def test_json_commands_in_pipeline(client): p = client.json().pipeline() p.set("foo", Path.root_path(), "bar") @@ -332,6 +349,7 @@ def test_json_commands_in_pipeline(client): assert client.get("foo") is None +@pytest.mark.redismod def test_json_delete_with_dollar(client): doc1 = {"a": 1, "nested": {"a": 2, "b": 3}} assert client.json().set("doc1", "$", doc1) @@ -383,6 +401,7 @@ def test_json_delete_with_dollar(client): client.json().delete("not_a_document", "..a") +@pytest.mark.redismod def test_json_forget_with_dollar(client): doc1 = {"a": 1, "nested": {"a": 2, "b": 3}} assert client.json().set("doc1", "$", doc1) @@ -434,6 +453,7 @@ def test_json_forget_with_dollar(client): client.json().forget("not_a_document", "..a") +@pytest.mark.redismod def test_json_mget_dollar(client): # Test mget with multi paths client.json().set( @@ -463,6 +483,7 @@ def test_json_mget_dollar(client): assert res == [None, None] +@pytest.mark.redismod def test_numby_commands_dollar(client): # Test NUMINCRBY client.json().set("doc1", "$", {"a": "b", "b": [{"a": 2}, {"a": 5.0}, {"a": "c"}]}) @@ -506,6 +527,7 @@ def test_numby_commands_dollar(client): client.json().nummultby("doc1", ".b[0].a", 3) == 6 +@pytest.mark.redismod def test_strappend_dollar(client): client.json().set( "doc1", "$", {"a": "foo", "nested1": {"a": "hello"}, "nested2": {"a": 31}} @@ -536,6 +558,7 @@ def test_strappend_dollar(client): client.json().strappend("doc1", "piu") +@pytest.mark.redismod def test_strlen_dollar(client): # Test multi client.json().set( @@ -556,6 +579,7 @@ def test_strlen_dollar(client): client.json().strlen("non_existing_doc", "$..a") +@pytest.mark.redismod def test_arrappend_dollar(client): client.json().set( "doc1", @@ -630,6 +654,7 @@ def test_arrappend_dollar(client): client.json().arrappend("non_existing_doc", "$..a") +@pytest.mark.redismod def test_arrinsert_dollar(client): client.json().set( "doc1", @@ -668,6 +693,7 @@ def test_arrinsert_dollar(client): client.json().arrappend("non_existing_doc", "$..a") +@pytest.mark.redismod def test_arrlen_dollar(client): client.json().set( "doc1", @@ -716,6 +742,7 @@ def test_arrlen_dollar(client): assert client.json().arrlen("non_existing_doc", "..a") is None +@pytest.mark.redismod def test_arrpop_dollar(client): client.json().set( "doc1", @@ -757,6 +784,7 @@ def test_arrpop_dollar(client): client.json().arrpop("non_existing_doc", "..a") +@pytest.mark.redismod def test_arrtrim_dollar(client): client.json().set( "doc1", @@ -809,6 +837,7 @@ def test_arrtrim_dollar(client): client.json().arrtrim("non_existing_doc", "..a", 1, 1) +@pytest.mark.redismod def test_objkeys_dollar(client): client.json().set( "doc1", @@ -838,6 +867,7 @@ def test_objkeys_dollar(client): assert client.json().objkeys("doc1", "$..nowhere") == [] +@pytest.mark.redismod def test_objlen_dollar(client): client.json().set( "doc1", @@ -892,6 +922,7 @@ def load_types_data(nested_key_name): return jdata, types +@pytest.mark.redismod def test_type_dollar(client): jdata, jtypes = load_types_data("a") client.json().set("doc1", "$", jdata) @@ -909,6 +940,7 @@ def test_type_dollar(client): ) +@pytest.mark.redismod def test_clear_dollar(client): client.json().set( "doc1", @@ -959,6 +991,7 @@ def test_clear_dollar(client): client.json().clear("non_existing_doc", "$..a") +@pytest.mark.redismod def test_toggle_dollar(client): client.json().set( "doc1", @@ -987,28 +1020,7 @@ def test_toggle_dollar(client): client.json().toggle("non_existing_doc", "$..a") -# # def test_debug_dollar(client): -# -# jdata, jtypes = load_types_data("a") -# -# client.json().set("doc1", "$", jdata) -# -# # Test multi -# assert client.json().debug("MEMORY", "doc1", "$..a") == [72, 24, 24, 16, 16, 1, 0] -# -# # Test single -# assert client.json().debug("MEMORY", "doc1", "$.nested2.a") == [24] -# -# # Test legacy -# assert client.json().debug("MEMORY", "doc1", "..a") == 72 -# -# # Test missing path (defaults to root) -# assert client.json().debug("MEMORY", "doc1") == 72 -# -# # Test missing key -# assert client.json().debug("MEMORY", "non_existing_doc", "$..a") == [] - - +@pytest.mark.redismod def test_resp_dollar(client): data = { "L1": { @@ -1237,6 +1249,7 @@ def test_resp_dollar(client): client.json().resp("non_existing_doc", "$..a") +@pytest.mark.redismod def test_arrindex_dollar(client): client.json().set( "store", @@ -1462,6 +1475,7 @@ def test_arrindex_dollar(client): assert client.json().arrindex("test_None", "..nested2_not_found.arr", "None") == 0 +@pytest.mark.redismod def test_decoders_and_unstring(): assert unstring("4") == 4 assert unstring("45.55") == 45.55 @@ -1472,6 +1486,7 @@ def test_decoders_and_unstring(): assert decode_list(["hello", b"world"]) == ["hello", "world"] +@pytest.mark.redismod def test_custom_decoder(client): import json @@ -1487,6 +1502,7 @@ def test_custom_decoder(client): assert not isinstance(cj.__decoder__, json.JSONDecoder) +@pytest.mark.redismod def test_set_file(client): import json import tempfile @@ -1505,6 +1521,7 @@ def test_set_file(client): client.json().set_file("test2", Path.root_path(), nojsonfile.name) +@pytest.mark.redismod def test_set_path(client): import json import tempfile diff --git a/tests/test_search.py b/tests/test_search.py index f19c193891..6b40c5129d 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -107,8 +107,8 @@ def createIndex(client, num_docs=100, definition=None): @pytest.fixture -def client(request): - r = _get_client(redis.Redis, request, decode_responses=True) +def client(request, stack_url): + r = _get_client(redis.Redis, request, decode_responses=True, from_url=stack_url) r.flushdb() return r diff --git a/tests/test_timeseries.py b/tests/test_timeseries.py index 6b59967f3c..5318818e79 100644 --- a/tests/test_timeseries.py +++ b/tests/test_timeseries.py @@ -5,7 +5,20 @@ import pytest import redis -from .conftest import assert_resp_response, is_resp2_connection, skip_ifmodversion_lt +from .conftest import ( + _get_client, + assert_resp_response, + is_resp2_connection, + skip_ifmodversion_lt, +) + + +@pytest.fixture() +def decoded_r(request, stack_url): + with _get_client( + redis.Redis, request, decode_responses=True, from_url=stack_url + ) as client: + yield client @pytest.fixture @@ -14,6 +27,7 @@ def client(decoded_r): return decoded_r +@pytest.mark.redismod def test_create(client): assert client.ts().create(1) assert client.ts().create(2, retention_msecs=5) @@ -31,6 +45,7 @@ def test_create(client): assert_resp_response(client, 128, info.get("chunk_size"), info.get("chunkSize")) +@pytest.mark.redismod @skip_ifmodversion_lt("1.4.0", "timeseries") def test_create_duplicate_policy(client): # Test for duplicate policy @@ -46,6 +61,7 @@ def test_create_duplicate_policy(client): ) +@pytest.mark.redismod def test_alter(client): assert client.ts().create(1) info = client.ts().info(1) @@ -66,6 +82,7 @@ def test_alter(client): ) +@pytest.mark.redismod @skip_ifmodversion_lt("1.4.0", "timeseries") def test_alter_diplicate_policy(client): assert client.ts().create(1) @@ -80,6 +97,7 @@ def test_alter_diplicate_policy(client): ) +@pytest.mark.redismod def test_add(client): assert 1 == client.ts().add(1, 1, 1) assert 2 == client.ts().add(2, 2, 3, retention_msecs=10) @@ -102,6 +120,7 @@ def test_add(client): assert_resp_response(client, 128, info.get("chunk_size"), info.get("chunkSize")) +@pytest.mark.redismod @skip_ifmodversion_lt("1.4.0", "timeseries") def test_add_duplicate_policy(client): # Test for duplicate policy BLOCK @@ -138,11 +157,13 @@ def test_add_duplicate_policy(client): assert 5.0 == client.ts().get("time-serie-add-ooo-min")[1] +@pytest.mark.redismod def test_madd(client): client.ts().create("a") assert [1, 2, 3] == client.ts().madd([("a", 1, 5), ("a", 2, 10), ("a", 3, 15)]) +@pytest.mark.redismod def test_incrby_decrby(client): for _ in range(100): assert client.ts().incrby(1, 1) @@ -171,6 +192,7 @@ def test_incrby_decrby(client): assert_resp_response(client, 128, info.get("chunk_size"), info.get("chunkSize")) +@pytest.mark.redismod def test_create_and_delete_rule(client): # test rule creation time = 100 @@ -194,6 +216,7 @@ def test_create_and_delete_rule(client): assert not info["rules"] +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") def test_del_range(client): try: @@ -208,6 +231,7 @@ def test_del_range(client): assert_resp_response(client, client.ts().range(1, 22, 22), [(22, 1.0)], [[22, 1.0]]) +@pytest.mark.redismod def test_range(client): for i in range(100): client.ts().add(1, i, i % 7) @@ -222,6 +246,7 @@ def test_range(client): assert 10 == len(client.ts().range(1, 0, 500, count=10)) +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") def test_range_advanced(client): for i in range(100): @@ -251,6 +276,7 @@ def test_range_advanced(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_range_latest(client: redis.Redis): timeseries = client.ts() @@ -275,6 +301,7 @@ def test_range_latest(client: redis.Redis): ) +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_range_bucket_timestamp(client: redis.Redis): timeseries = client.ts() @@ -308,6 +335,7 @@ def test_range_bucket_timestamp(client: redis.Redis): ) +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_range_empty(client: redis.Redis): timeseries = client.ts() @@ -352,6 +380,7 @@ def test_range_empty(client: redis.Redis): assert_resp_response(client, res, resp2_expected, resp3_expected) +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") def test_rev_range(client): for i in range(100): @@ -400,6 +429,7 @@ def test_rev_range(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_revrange_latest(client: redis.Redis): timeseries = client.ts() @@ -418,6 +448,7 @@ def test_revrange_latest(client: redis.Redis): assert_resp_response(client, res, [(0, 4.0)], [[0, 4.0]]) +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_revrange_bucket_timestamp(client: redis.Redis): timeseries = client.ts() @@ -451,6 +482,7 @@ def test_revrange_bucket_timestamp(client: redis.Redis): ) +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_revrange_empty(client: redis.Redis): timeseries = client.ts() @@ -496,6 +528,7 @@ def test_revrange_empty(client: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod def test_mrange(client): client.ts().create(1, labels={"Test": "This", "team": "ny"}) client.ts().create(2, labels={"Test": "This", "Taste": "That", "team": "sf"}) @@ -544,6 +577,7 @@ def test_mrange(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") def test_multi_range_advanced(client): client.ts().create(1, labels={"Test": "This", "team": "ny"}) @@ -657,6 +691,7 @@ def test_multi_range_advanced(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_mrange_latest(client: redis.Redis): timeseries = client.ts() @@ -686,6 +721,7 @@ def test_mrange_latest(client: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("99.99.99", "timeseries") def test_multi_reverse_range(client): client.ts().create(1, labels={"Test": "This", "team": "ny"}) @@ -804,6 +840,7 @@ def test_multi_reverse_range(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_mrevrange_latest(client: redis.Redis): timeseries = client.ts() @@ -832,6 +869,7 @@ def test_mrevrange_latest(client: redis.Redis): ) +@pytest.mark.redismod def test_get(client): name = "test" client.ts().create(name) @@ -843,6 +881,7 @@ def test_get(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_get_latest(client: redis.Redis): timeseries = client.ts() @@ -860,6 +899,7 @@ def test_get_latest(client: redis.Redis): @pytest.mark.onlynoncluster +@pytest.mark.redismod def test_mget(client): client.ts().create(1, labels={"Test": "This"}) client.ts().create(2, labels={"Test": "This", "Taste": "That"}) @@ -895,6 +935,7 @@ def test_mget(client): @pytest.mark.onlynoncluster +@pytest.mark.redismod @skip_ifmodversion_lt("1.8.0", "timeseries") def test_mget_latest(client: redis.Redis): timeseries = client.ts() @@ -911,6 +952,7 @@ def test_mget_latest(client: redis.Redis): assert_resp_response(client, res, [{"t2": [{}, 10, 8.0]}], {"t2": [{}, [10, 8.0]]}) +@pytest.mark.redismod def test_info(client): client.ts().create(1, retention_msecs=5, labels={"currentLabel": "currentData"}) info = client.ts().info(1) @@ -920,8 +962,9 @@ def test_info(client): assert info["labels"]["currentLabel"] == "currentData" +@pytest.mark.redismod @skip_ifmodversion_lt("1.4.0", "timeseries") -def testInfoDuplicatePolicy(client): +def test_info_duplicate_policy(client): client.ts().create(1, retention_msecs=5, labels={"currentLabel": "currentData"}) info = client.ts().info(1) assert_resp_response( @@ -935,6 +978,7 @@ def testInfoDuplicatePolicy(client): ) +@pytest.mark.redismod @pytest.mark.onlynoncluster def test_query_index(client): client.ts().create(1, labels={"Test": "This"}) @@ -944,6 +988,7 @@ def test_query_index(client): assert_resp_response(client, client.ts().queryindex(["Taste=That"]), [2], {"2"}) +@pytest.mark.redismod def test_pipeline(client): pipeline = client.ts().pipeline() pipeline.create("with_pipeline") @@ -961,6 +1006,7 @@ def test_pipeline(client): assert client.ts().get("with_pipeline")[1] == 99 * 1.1 +@pytest.mark.redismod def test_uncompressed(client): client.ts().create("compressed") client.ts().create("uncompressed", uncompressed=True)