From e1efdf624c39bfd3cc56f5b076405ec5a6e5e92c Mon Sep 17 00:00:00 2001 From: dvora-h Date: Thu, 12 May 2022 18:29:03 +0300 Subject: [PATCH 1/2] fix tests --- redis/cluster.py | 1 + redis/commands/parser.py | 2 +- tests/test_cluster.py | 37 ++++++++++++++++++-------- tests/test_command_parser.py | 4 --- tests/test_commands.py | 30 ++++++++++++--------- tests/test_encoding.py | 2 +- tests/test_function.py | 51 ++++++++++++++++++------------------ tests/test_scripting.py | 4 +-- 8 files changed, 73 insertions(+), 58 deletions(-) diff --git a/redis/cluster.py b/redis/cluster.py index fa1322f10..f17093ed9 100644 --- a/redis/cluster.py +++ b/redis/cluster.py @@ -300,6 +300,7 @@ class AbstractRedisCluster: "CLUSTER KEYSLOT", "COMMAND", "COMMAND COUNT", + "COMMAND LIST", "COMMAND GETKEYS", "CONFIG GET", "DEBUG", diff --git a/redis/commands/parser.py b/redis/commands/parser.py index 7560603d7..115230a9d 100644 --- a/redis/commands/parser.py +++ b/redis/commands/parser.py @@ -79,7 +79,7 @@ def get_keys(self, redis_conn, *args): command = self.commands.get(cmd_name) if "movablekeys" in command["flags"]: keys = self._get_moveable_keys(redis_conn, *args) - elif "pubsub" in command["flags"]: + elif "pubsub" in command["flags"] or command["name"] == "pubsub": keys = self._get_pubsub_keys(*args) else: if ( diff --git a/tests/test_cluster.py b/tests/test_cluster.py index de41a107d..d141f12c1 100644 --- a/tests/test_cluster.py +++ b/tests/test_cluster.py @@ -863,15 +863,15 @@ def test_cluster_shards(self, r): assert isinstance(cluster_shards, list) assert isinstance(cluster_shards[0], dict) attributes = [ - "id", - "endpoint", - "ip", - "hostname", - "port", - "tls-port", - "role", - "replication-offset", - "health", + b"id", + b"endpoint", + b"ip", + b"hostname", + b"port", + b"tls-port", + b"role", + b"replication-offset", + b"health", ] for x in cluster_shards: assert list(x.keys()) == ["slots", "nodes"] @@ -928,9 +928,24 @@ def test_cluster_delslots(self): @skip_if_server_version_lt("7.0.0") @skip_if_redis_enterprise() - def test_cluster_delslotsrange(self, r): + def test_cluster_delslotsrange(self): + cluster_slots = [ + [ + 0, + 8191, + ["127.0.0.1", 7000, "node_0"], + ], + [ + 8192, + 16383, + ["127.0.0.1", 7001, "node_1"], + ], + ] + r = get_mocked_redis_client( + host=default_host, port=default_port, cluster_slots=cluster_slots + ) + mock_all_nodes_resp(r, "OK") node = r.get_random_node() - mock_node_resp(node, "OK") r.cluster_addslots(node, 1, 2, 3, 4, 5) assert r.cluster_delslotsrange(1, 5) diff --git a/tests/test_command_parser.py b/tests/test_command_parser.py index 1457e2753..928e41ca5 100644 --- a/tests/test_command_parser.py +++ b/tests/test_command_parser.py @@ -50,8 +50,6 @@ def test_get_moveable_keys(self, r): "key3", ] args7 = ["MIGRATE", "192.168.1.34", 6379, "key1", 0, 5000] - args8 = ["STRALGO", "LCS", "STRINGS", "string_a", "string_b"] - args9 = ["STRALGO", "LCS", "KEYS", "key1", "key2"] assert commands_parser.get_keys(r, *args1).sort() == ["key1", "key2"].sort() assert ( @@ -68,8 +66,6 @@ def test_get_moveable_keys(self, r): == ["key1", "key2", "key3"].sort() ) assert commands_parser.get_keys(r, *args7).sort() == ["key1"].sort() - assert commands_parser.get_keys(r, *args8) is None - assert commands_parser.get_keys(r, *args9).sort() == ["key1", "key2"].sort() # A bug in redis<7.0 causes this to fail: https://github.com/redis/redis/issues/9493 @skip_if_server_version_lt("7.0.0") diff --git a/tests/test_commands.py b/tests/test_commands.py index d5ab4e369..58c791522 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -677,7 +677,7 @@ def test_client_unpause(self, r): @pytest.mark.onlynoncluster @skip_if_server_version_lt("7.0.0") def test_client_no_evict(self, r): - assert r.client_no_evict("ON") == "OK" + assert r.client_no_evict("ON") with pytest.raises(TypeError): r.client_no_evict() @@ -1096,9 +1096,9 @@ def test_unlink_with_multiple_keys(self, r): @skip_if_server_version_lt("7.0.0") def test_lcs(self, r): r.mset({"foo": "ohmytext", "bar": "mynewtext"}) - assert r.lcs("foo", "bar") == "mytext" + assert r.lcs("foo", "bar") == b"mytext" assert r.lcs("foo", "bar", len=True) == 6 - result = ["matches", [[[4, 7], [5, 8]]], "len", 6] + result = [b"matches", [[[4, 7], [5, 8]]], b"len", 6] assert r.lcs("foo", "bar", idx=True, minmatchlen=3) == result with pytest.raises(redis.ResponseError): assert r.lcs("foo", "bar", len=True, idx=True) @@ -1771,24 +1771,24 @@ def test_brpoplpush_empty_string(self, r): @skip_if_server_version_lt("7.0.0") def test_blmpop(self, r): r.rpush("a", "1", "2", "3", "4", "5") - res = ["a", ["1", "2"]] + res = [b"a", [b"1", b"2"]] assert r.blmpop(1, "2", "b", "a", direction="LEFT", count=2) == res with pytest.raises(TypeError): r.blmpop(1, "2", "b", "a", count=2) r.rpush("b", "6", "7", "8", "9") - assert r.blmpop(0, "2", "b", "a", direction="LEFT") == ["b", ["6"]] + assert r.blmpop(0, "2", "b", "a", direction="LEFT") == [b"b", [b"6"]] assert r.blmpop(1, "2", "foo", "bar", direction="RIGHT") is None @pytest.mark.onlynoncluster @skip_if_server_version_lt("7.0.0") def test_lmpop(self, r): r.rpush("foo", "1", "2", "3", "4", "5") - result = ["foo", ["1", "2"]] + result = [b"foo", [b"1", b"2"]] assert r.lmpop("2", "bar", "foo", direction="LEFT", count=2) == result with pytest.raises(redis.ResponseError): r.lmpop("2", "bar", "foo", direction="up", count=2) r.rpush("bar", "a", "b", "c", "d") - assert r.lmpop("2", "bar", "foo", direction="LEFT") == ["bar", ["a"]] + assert r.lmpop("2", "bar", "foo", direction="LEFT") == [b"bar", [b"a"]] def test_lindex(self, r): r.rpush("a", "1", "2", "3") @@ -2399,23 +2399,23 @@ def test_bzpopmin(self, r): @skip_if_server_version_lt("7.0.0") def test_zmpop(self, r): r.zadd("a", {"a1": 1, "a2": 2, "a3": 3}) - res = ["a", [["a1", "1"], ["a2", "2"]]] + res = [b"a", [[b"a1", b"1"], [b"a2", b"2"]]] assert r.zmpop("2", ["b", "a"], min=True, count=2) == res with pytest.raises(redis.DataError): r.zmpop("2", ["b", "a"], count=2) r.zadd("b", {"b1": 10, "ab": 9, "b3": 8}) - assert r.zmpop("2", ["b", "a"], max=True) == ["b", [["b1", "10"]]] + assert r.zmpop("2", ["b", "a"], max=True) == [b"b", [[b"b1", b"10"]]] @pytest.mark.onlynoncluster @skip_if_server_version_lt("7.0.0") def test_bzmpop(self, r): r.zadd("a", {"a1": 1, "a2": 2, "a3": 3}) - res = ["a", [["a1", "1"], ["a2", "2"]]] + res = [b"a", [[b"a1", b"1"], [b"a2", b"2"]]] assert r.bzmpop(1, "2", ["b", "a"], min=True, count=2) == res with pytest.raises(redis.DataError): r.bzmpop(1, "2", ["b", "a"], count=2) r.zadd("b", {"b1": 10, "ab": 9, "b3": 8}) - res = ["b", [["b1", "10"]]] + res = [b"b", [[b"b1", b"10"]]] assert r.bzmpop(0, "2", ["b", "a"], max=True) == res assert r.bzmpop(1, "2", ["foo", "bar"], max=True) is None @@ -3106,6 +3106,7 @@ def test_cluster_slaves(self, mock_cluster_resp_slaves): @pytest.mark.onlynoncluster @skip_if_server_version_lt("3.0.0") + @skip_if_server_version_gte("7.0.0") @skip_if_redis_enterprise() def test_readwrite(self, r): assert r.readwrite() @@ -4557,7 +4558,7 @@ def test_command_list(self, r: redis.Redis): assert len(r.command_list()) > 300 assert len(r.command_list(module="fakemod")) == 0 assert len(r.command_list(category="list")) > 15 - assert "lpop" in r.command_list(pattern="l*") + assert b"lpop" in r.command_list(pattern="l*") with pytest.raises(redis.ResponseError): r.command_list(category="list", pattern="l*") @@ -4593,7 +4594,10 @@ def test_command(self, r): @skip_if_server_version_lt("7.0.0") @skip_if_redis_enterprise() def test_command_getkeysandflags(self, r: redis.Redis): - res = [["mylist1", ["RW", "access", "delete"]], ["mylist2", ["RW", "insert"]]] + res = [ + [b"mylist1", [b"RW", b"access", b"delete"]], + [b"mylist2", [b"RW", b"insert"]], + ] assert res == r.command_getkeysandflags( "LMOVE", "mylist1", "mylist2", "left", "left" ) diff --git a/tests/test_encoding.py b/tests/test_encoding.py index bd0f09fcc..a9e94c05f 100644 --- a/tests/test_encoding.py +++ b/tests/test_encoding.py @@ -94,7 +94,7 @@ def test_memoryviews_are_not_packed(self): class TestCommandsAreNotEncoded: @pytest.fixture() def r(self, request): - return _get_client(redis.Redis, request=request, encoding="utf-16") + return _get_client(redis.Redis, request=request, encoding="utf-8") def test_basic_command(self, r): r.set("hello", "world") diff --git a/tests/test_function.py b/tests/test_function.py index e6c4bcd58..575e76625 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -22,10 +22,10 @@ class TestFunction: def reset_functions(self, r): r.function_flush() + @pytest.mark.onlynoncluster def test_function_load(self, r): - print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - assert lib == r.function_load(f"#!{engine} name={lib} \n {function}") - assert lib == r.function_load( + assert b"mylib" == r.function_load(f"#!{engine} name={lib} \n {function}") + assert b"mylib" == r.function_load( f"#!{engine} name={lib} \n {function}", replace=True ) with pytest.raises(ResponseError): @@ -37,15 +37,14 @@ def test_function_delete(self, r): r.function_load(f"#!{engine} name={lib} \n {set_function}") with pytest.raises(ResponseError): r.function_load(f"#!{engine} name={lib} \n {set_function}") - assert r.fcall("set", 1, "foo", "bar") == "OK" + assert r.fcall("set", 1, "foo", "bar") == b"OK" assert r.function_delete("mylib") with pytest.raises(ResponseError): r.fcall("set", 1, "foo", "bar") - assert lib == r.function_load(f"#!{engine} name={lib} \n {set_function}") def test_function_flush(self, r): r.function_load(f"#!{engine} name={lib} \n {function}") - assert r.fcall("myfunc", 0, "hello") == "hello" + assert r.fcall("myfunc", 0, "hello") == b"hello" assert r.function_flush() with pytest.raises(ResponseError): r.fcall("myfunc", 0, "hello") @@ -57,19 +56,19 @@ def test_function_list(self, r): r.function_load(f"#!{engine} name={lib} \n {function}") res = [ [ - "library_name", - "mylib", - "engine", - "LUA", - "functions", - [["name", "myfunc", "description", None, "flags", ["no-writes"]]], + b"library_name", + b"mylib", + b"engine", + b"LUA", + b"functions", + [[b"name", b"myfunc", b"description", None, b"flags", [b"no-writes"]]], ], ] assert r.function_list() == res assert r.function_list(library="*lib") == res assert ( r.function_list(withcode=True)[0][7] - == f"#!{engine} name={lib} \n {function}" + == f"#!{engine} name={lib} \n {function}".encode() ) @pytest.mark.onlycluster @@ -77,12 +76,12 @@ def test_function_list_on_cluster(self, r): r.function_load(f"#!{engine} name={lib} \n {function}") function_list = [ [ - "library_name", - "mylib", - "engine", - "LUA", - "functions", - [["name", "myfunc", "description", None, "flags", ["no-writes"]]], + b"library_name", + b"mylib", + b"engine", + b"LUA", + b"functions", + [[b"name", b"myfunc", b"description", None, b"flags", [b"no-writes"]]], ], ] primaries = r.get_primaries() @@ -94,20 +93,20 @@ def test_function_list_on_cluster(self, r): node = primaries[0].name assert ( r.function_list(withcode=True)[node][0][7] - == f"#!{engine} name={lib} \n {function}" + == f"#!{engine} name={lib} \n {function}".encode() ) def test_fcall(self, r): r.function_load(f"#!{engine} name={lib} \n {set_function}") r.function_load(f"#!{engine} name={lib2} \n {get_function}") - assert r.fcall("set", 1, "foo", "bar") == "OK" - assert r.fcall("get", 1, "foo") == "bar" + assert r.fcall("set", 1, "foo", "bar") == b"OK" + assert r.fcall("get", 1, "foo") == b"bar" with pytest.raises(ResponseError): r.fcall("myfunc", 0, "hello") def test_fcall_ro(self, r): r.function_load(f"#!{engine} name={lib} \n {function}") - assert r.fcall_ro("myfunc", 0, "hello") == "hello" + assert r.fcall_ro("myfunc", 0, "hello") == b"hello" r.function_load(f"#!{engine} name={lib2} \n {set_function}") with pytest.raises(ResponseError): r.fcall_ro("set", 1, "foo", "bar") @@ -115,14 +114,14 @@ def test_fcall_ro(self, r): def test_function_dump_restore(self, r): r.function_load(f"#!{engine} name={lib} \n {set_function}") payload = r.function_dump() - assert r.fcall("set", 1, "foo", "bar") == "OK" + assert r.fcall("set", 1, "foo", "bar") == b"OK" r.function_delete("mylib") with pytest.raises(ResponseError): r.fcall("set", 1, "foo", "bar") assert r.function_restore(payload) - assert r.fcall("set", 1, "foo", "bar") == "OK" + assert r.fcall("set", 1, "foo", "bar") == b"OK" r.function_load(f"#!{engine} name={lib2} \n {get_function}") - assert r.fcall("get", 1, "foo") == "bar" + assert r.fcall("get", 1, "foo") == b"bar" r.function_delete("mylib") assert r.function_restore(payload, "FLUSH") with pytest.raises(ResponseError): diff --git a/tests/test_scripting.py b/tests/test_scripting.py index 1ccd99a00..bbe845c0d 100644 --- a/tests/test_scripting.py +++ b/tests/test_scripting.py @@ -70,7 +70,7 @@ def test_eval_multiply(self, r): @pytest.mark.onlynoncluster def test_eval_ro(self, r): r.set("a", "b") - assert r.eval_ro("return redis.call('GET', KEYS[1])", 1, "a") == "b" + assert r.eval_ro("return redis.call('GET', KEYS[1])", 1, "a") == b"b" with pytest.raises(redis.ResponseError): r.eval_ro("return redis.call('DEL', KEYS[1])", 1, "a") @@ -162,7 +162,7 @@ def test_evalsha_ro(self, r): r.set("a", "b") get_sha = r.script_load("return redis.call('GET', KEYS[1])") del_sha = r.script_load("return redis.call('DEL', KEYS[1])") - assert r.evalsha_ro(get_sha, 1, "a") == "b" + assert r.evalsha_ro(get_sha, 1, "a") == b"b" with pytest.raises(redis.ResponseError): r.evalsha_ro(del_sha, 1, "a") From 4491225433bb61c357f15caa3a63cce9750a9f13 Mon Sep 17 00:00:00 2001 From: dvora-h Date: Thu, 12 May 2022 18:30:55 +0300 Subject: [PATCH 2/2] async --- tests/test_asyncio/test_commands.py | 36 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/tests/test_asyncio/test_commands.py b/tests/test_asyncio/test_commands.py index 650ce2795..9fd4991c6 100644 --- a/tests/test_asyncio/test_commands.py +++ b/tests/test_asyncio/test_commands.py @@ -517,13 +517,10 @@ async def test_config_resetstat(self, r: redis.Redis): assert reset_commands_processed < prior_commands_processed async def test_config_set(self, r: redis.Redis): - data = await r.config_get() - rdbname = data["dbfilename"] - try: - assert await r.config_set("dbfilename", "redis_py_test.rdb") - assert (await r.config_get())["dbfilename"] == "redis_py_test.rdb" - finally: - assert await r.config_set("dbfilename", rdbname) + await r.config_set("timeout", 70) + assert (await r.config_get())["timeout"] == "70" + assert await r.config_set("timeout", 0) + assert (await r.config_get())["timeout"] == "0" @pytest.mark.onlynoncluster async def test_dbsize(self, r: redis.Redis): @@ -541,7 +538,8 @@ async def test_info(self, r: redis.Redis): await r.set("b", "bar") info = await r.info() assert isinstance(info, dict) - assert info["db9"]["keys"] == 2 + assert "arch_bits" in info.keys() + assert "redis_version" in info.keys() @pytest.mark.onlynoncluster async def test_lastsave(self, r: redis.Redis): @@ -2180,6 +2178,7 @@ async def test_cluster_slaves(self, mock_cluster_resp_slaves): ) @skip_if_server_version_lt("3.0.0") + @skip_if_server_version_gte("7.0.0") @pytest.mark.onlynoncluster async def test_readwrite(self, r: redis.Redis): assert await r.readwrite() @@ -2546,7 +2545,7 @@ async def test_xclaim(self, r: redis.Redis): == [message_id] ) - @skip_if_server_version_lt("5.0.0") + @skip_if_server_version_lt("7.0.0") async def test_xclaim_trimmed(self, r: redis.Redis): # xclaim should not raise an exception if the item is not there stream = "stream" @@ -2567,9 +2566,8 @@ async def test_xclaim_trimmed(self, r: redis.Redis): # xclaim them from consumer2 # the item that is still in the stream should be returned item = await r.xclaim(stream, group, "consumer2", 0, [sid1, sid2]) - assert len(item) == 2 - assert item[0] == (None, None) - assert item[1][0] == sid2 + assert len(item) == 1 + assert item[0][0] == sid2 @skip_if_server_version_lt("5.0.0") async def test_xdel(self, r: redis.Redis): @@ -2586,7 +2584,7 @@ async def test_xdel(self, r: redis.Redis): assert await r.xdel(stream, m1) == 1 assert await r.xdel(stream, m2, m3) == 2 - @skip_if_server_version_lt("5.0.0") + @skip_if_server_version_lt("7.0.0") async def test_xgroup_create(self, r: redis.Redis): # tests xgroup_create and xinfo_groups stream = "stream" @@ -2603,11 +2601,13 @@ async def test_xgroup_create(self, r: redis.Redis): "consumers": 0, "pending": 0, "last-delivered-id": b"0-0", + "entries-read": None, + "lag": 1, } ] assert await r.xinfo_groups(stream) == expected - @skip_if_server_version_lt("5.0.0") + @skip_if_server_version_lt("7.0.0") async def test_xgroup_create_mkstream(self, r: redis.Redis): # tests xgroup_create and xinfo_groups stream = "stream" @@ -2627,6 +2627,8 @@ async def test_xgroup_create_mkstream(self, r: redis.Redis): "consumers": 0, "pending": 0, "last-delivered-id": b"0-0", + "entries-read": None, + "lag": 0, } ] assert await r.xinfo_groups(stream) == expected @@ -2661,7 +2663,7 @@ async def test_xgroup_destroy(self, r: redis.Redis): await r.xgroup_create(stream, group, 0) assert await r.xgroup_destroy(stream, group) - @skip_if_server_version_lt("5.0.0") + @skip_if_server_version_lt("7.0.0") async def test_xgroup_setid(self, r: redis.Redis): stream = "stream" group = "group" @@ -2669,13 +2671,15 @@ async def test_xgroup_setid(self, r: redis.Redis): await r.xgroup_create(stream, group, 0) # advance the last_delivered_id to the message_id - await r.xgroup_setid(stream, group, message_id) + await r.xgroup_setid(stream, group, message_id, entries_read=2) expected = [ { "name": group.encode(), "consumers": 0, "pending": 0, "last-delivered-id": message_id, + "entries-read": 2, + "lag": -1, } ] assert await r.xinfo_groups(stream) == expected