diff --git a/redis/commands/bf/commands.py b/redis/commands/bf/commands.py index fa242365aa..0f2af2d37e 100644 --- a/redis/commands/bf/commands.py +++ b/redis/commands/bf/commands.py @@ -470,7 +470,10 @@ def scandump( (0, NULL) to indicate completion. For more information see `CF.SCANDUMP `_. """ # noqa - return self.execute_command(CF_SCANDUMP, key, iter) + params = [key, iter] + options = {} + options[NEVER_DECODE] = [] + return self.execute_command(CF_SCANDUMP, *params, **options) @overload def loadchunk(self: SyncClientProtocol, key, iter, data) -> bytes | str: ... diff --git a/tests/test_asyncio/test_bloom.py b/tests/test_asyncio/test_bloom.py index 21d4a96b4e..977b72f674 100644 --- a/tests/test_asyncio/test_bloom.py +++ b/tests/test_asyncio/test_bloom.py @@ -157,6 +157,29 @@ async def do_verify(): await decoded_r.bf().client.delete("myBloom") +@pytest.mark.redismod +async def test_cf_scandump_and_loadchunk(decoded_r: redis.Redis): + # The client decodes responses, but the dumped chunks are binary. + await decoded_r.cf().create("myCuckoo", 1000) + for x in range(100): + await decoded_r.cf().add("myCuckoo", x) + + chunks = [] + it = 0 + while True: + it, data = await decoded_r.cf().scandump("myCuckoo", it) + if it == 0: + break + assert isinstance(data, bytes) + chunks.append((it, data)) + + await decoded_r.delete("myCuckoo") + for it, data in chunks: + await decoded_r.cf().loadchunk("myCuckoo", it, data) + + assert all(await decoded_r.cf().mexists("myCuckoo", *range(100))) + + @pytest.mark.redismod async def test_bf_info(decoded_r: redis.Redis): expansion = 4 diff --git a/tests/test_bloom.py b/tests/test_bloom.py index 1f2e89cd37..d2a37e73b4 100644 --- a/tests/test_bloom.py +++ b/tests/test_bloom.py @@ -1,7 +1,9 @@ from math import inf +from unittest.mock import Mock import pytest import redis.commands.bf +from redis.client import NEVER_DECODE from redis.exceptions import RedisError from .conftest import ( @@ -188,6 +190,38 @@ def do_verify(): client.bf().client.delete("myBloom") +@pytest.mark.redismod +@skip_if_redis_enterprise() +def test_cf_scandump_and_loadchunk(client): + # The client decodes responses, but the dumped chunks are binary. + client.cf().create("myCuckoo", 1000) + for x in range(100): + client.cf().add("myCuckoo", x) + + chunks = [] + it = 0 + while True: + it, data = client.cf().scandump("myCuckoo", it) + if it == 0: + break + assert isinstance(data, bytes) + chunks.append((it, data)) + + client.delete("myCuckoo") + for it, data in chunks: + client.cf().loadchunk("myCuckoo", it, data) + + assert all(client.cf().mexists("myCuckoo", *range(100))) + + +def test_cf_scandump_does_not_decode_response(): + mock_client = Mock() + redis.commands.bf.CFBloom(mock_client).scandump("myCuckoo", 0) + mock_client.execute_command.assert_called_once_with( + "CF.SCANDUMP", "myCuckoo", 0, **{NEVER_DECODE: []} + ) + + @pytest.mark.redismod def test_bf_info(client): expansion = 4