Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SCRIPT EXISTS and SCRIPT FLUSH subcommands #281

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.rst
Expand Up @@ -310,8 +310,6 @@ scripting
---------

* script debug
* script exists
* script flush
* script kill


Expand Down
10 changes: 8 additions & 2 deletions fakeredis/_server.py
Expand Up @@ -2316,8 +2316,7 @@ def time(self):
return [str(now_s).encode(), str(now_us).encode()]

# Script commands
# TODO: script exists, script flush
# (script debug and script kill will probably not be supported)
# script debug and script kill will probably not be supported

def _convert_redis_arg(self, lua_runtime, value):
# Type checks are exact to avoid issues like bool being a subclass of int.
Expand Down Expand Up @@ -2475,6 +2474,13 @@ def script(self, subcmd, *args):
sha1 = hashlib.sha1(script).hexdigest().encode()
self._server.script_cache[sha1] = script
return sha1
elif casematch(subcmd, b'exists'):
return [int(sha1 in self._server.script_cache) for sha1 in args]
elif casematch(subcmd, b'flush'):
if len(args) != 0:
raise SimpleError(BAD_SUBCOMMAND_MSG.format('SCRIPT'))
self._server.script_cache = {}
return OK
else:
raise SimpleError(BAD_SUBCOMMAND_MSG.format('SCRIPT'))

Expand Down
40 changes: 40 additions & 0 deletions test/test_fakeredis.py
Expand Up @@ -4486,6 +4486,46 @@ def test_script(r):
assert result == b'42'


def test_script_exists(r):
# test response for no arguments by bypassing the py-redis command
# as it requires at least one argument
assert raw_command(r, "SCRIPT EXISTS") == []

# use single character characters for non-existing scripts, as those
# will never be equal to an actual sha1 hash digest
assert r.script_exists("a") == [0]
assert r.script_exists("a", "b", "c", "d", "e", "f") == [0, 0, 0, 0, 0, 0]

sha1_one = r.script_load("return 'a'")
assert r.script_exists(sha1_one) == [1]
assert r.script_exists(sha1_one, "a") == [1, 0]
assert r.script_exists("a", "b", "c", sha1_one, "e") == [0, 0, 0, 1, 0]

sha1_two = r.script_load("return 'b'")
assert r.script_exists(sha1_one, sha1_two) == [1, 1]
assert r.script_exists("a", sha1_one, "c", sha1_two, "e", "f") == [0, 1, 0, 1, 0, 0]


@pytest.mark.parametrize("args", [("a",), tuple("abcdefghijklmn")])
def test_script_flush_errors_with_args(r, args):
with pytest.raises(redis.ResponseError):
raw_command(r, "SCRIPT FLUSH %s" % " ".join(args))


def test_script_flush(r):
# generate/load six unique scripts and store their sha1 hash values
sha1_values = [r.script_load("return '%s'" % char) for char in "abcdef"]

# assert the scripts all exist prior to flushing
assert r.script_exists(*sha1_values) == [1] * len(sha1_values)

# flush and assert OK response
assert r.script_flush() is True

# assert none of the scripts exists after flushing
assert r.script_exists(*sha1_values) == [0] * len(sha1_values)


@fake_only
def test_lua_log(r, caplog):
logger = fakeredis._server.LOGGER
Expand Down