feat: add support for script (#13)
feat: add support for script and function Signed-off-by: Pengda Yang <daz-3ux@proton.me> Co-authored-by: bodong.ybd <bodong.ybd@alibaba-inc.com>
This commit is contained in:
parent
4b0296f02a
commit
b6033c0eda
|
@ -2,3 +2,4 @@
|
||||||
test.json
|
test.json
|
||||||
venv
|
venv
|
||||||
html
|
html
|
||||||
|
__pycache__
|
262
cts.json
262
cts.json
|
@ -5114,17 +5114,275 @@
|
||||||
],
|
],
|
||||||
"since": "2.2.0"
|
"since": "2.2.0"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "eval command",
|
||||||
|
"command": [
|
||||||
|
"eval return 0 hello"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"since": "2.6.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "eval_ro command",
|
||||||
|
"command": [
|
||||||
|
"eval_ro return 0 hello"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"since": "7.0.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "evalsha command",
|
||||||
|
"command": [
|
||||||
|
"script load return",
|
||||||
|
"evalsha 63143b6f8007b98c53ca2149822777b3566f9241 0",
|
||||||
|
"script flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"63143b6f8007b98c53ca2149822777b3566f9241",
|
||||||
|
null,
|
||||||
|
"True"
|
||||||
|
],
|
||||||
|
"since": "2.6.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "evalsha_ro command",
|
||||||
|
"command": [
|
||||||
|
"script load return",
|
||||||
|
"evalsha_ro 63143b6f8007b98c53ca2149822777b3566f9241 0",
|
||||||
|
"script flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"63143b6f8007b98c53ca2149822777b3566f9241",
|
||||||
|
null,
|
||||||
|
"True"
|
||||||
|
],
|
||||||
|
"since": "7.0.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "fcall command",
|
||||||
|
"command": [
|
||||||
|
"function flush",
|
||||||
|
"function load \"#!lua name=mylib \n redis.register_function('myfunc', function(keys, args) return args[1] end)\"",
|
||||||
|
"fcall myfunc 0 hello",
|
||||||
|
"function flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"OK",
|
||||||
|
"mylib",
|
||||||
|
"hello",
|
||||||
|
"OK"
|
||||||
|
],
|
||||||
|
"since": "7.0.0",
|
||||||
|
"command_split": true
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "fcall_ro command",
|
||||||
|
"command": [
|
||||||
|
"function flush",
|
||||||
|
"function load \"#!lua name=mylib \n local function ret(keys, args) return args[1] end \n redis.register_function{function_name='ret', callback=ret, flags={ 'no-writes' }}\"",
|
||||||
|
"fcall_ro ret 0 hello",
|
||||||
|
"function flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"OK",
|
||||||
|
"mylib",
|
||||||
|
"hello",
|
||||||
|
"OK"
|
||||||
|
],
|
||||||
|
"since": "7.0.0",
|
||||||
|
"command_split": true
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "function delete command",
|
||||||
|
"command": [
|
||||||
|
"function flush",
|
||||||
|
"function load \"#!lua name=mylib \n redis.register_function('myfunc', function(keys, args) return args[1] end)\"",
|
||||||
|
"function delete mylib",
|
||||||
|
"function flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"OK",
|
||||||
|
"mylib",
|
||||||
|
"OK",
|
||||||
|
"OK"
|
||||||
|
],
|
||||||
|
"since": "7.0.0",
|
||||||
|
"command_split": true
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "function flush command",
|
||||||
|
"command": [
|
||||||
|
"function flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"True"
|
||||||
|
],
|
||||||
|
"since": "7.0.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "function list command",
|
||||||
|
"command": [
|
||||||
|
"function flush",
|
||||||
|
"function load \"#!lua name=mylib \n redis.register_function('myfunc', function(keys, args) return args[1] end)\"",
|
||||||
|
"function list",
|
||||||
|
"function flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"OK",
|
||||||
|
"mylib",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"library_name", "mylib", "engine", "LUA", "functions",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"name", "myfunc", "description", null, "flags",
|
||||||
|
[]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"OK"
|
||||||
|
],
|
||||||
|
"since": "7.0.0",
|
||||||
|
"command_split": true
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "function load command",
|
"name": "function load command",
|
||||||
"command": [
|
"command": [
|
||||||
"function flush",
|
"function flush",
|
||||||
"function load \"#!lua name=mylib \n redis.register_function('myfunc', function(keys, args) return args[1] end)\""
|
"function load \"#!lua name=mylib \n redis.register_function('myfunc', function(keys, args) return args[1] end)\"",
|
||||||
|
"fcall myfunc 0 hello",
|
||||||
|
"function flush"
|
||||||
],
|
],
|
||||||
"result": [
|
"result": [
|
||||||
"OK",
|
"OK",
|
||||||
"mylib"
|
"mylib",
|
||||||
|
"hello",
|
||||||
|
"OK"
|
||||||
],
|
],
|
||||||
"since": "7.0.0",
|
"since": "7.0.0",
|
||||||
"command_split": true
|
"command_split": true
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "function restore command",
|
||||||
|
"command": [
|
||||||
|
"function flush",
|
||||||
|
"function restore \"\\xf5\\xc3@X@]\\x1f#!lua name=mylib \\n redis.registe\\rr_function('my@\\x0b\\x02', @\\x06`\\x12\\nkeys, args) 6\\x03turn`\\x0c\\a[1] end)\\n\\x00q\\xee\\xf6b\\xe9$\\xbaN\" flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"OK",
|
||||||
|
"OK"
|
||||||
|
],
|
||||||
|
"since": "7.0.0",
|
||||||
|
"command_split": true,
|
||||||
|
"command_binary": true
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "function stats command",
|
||||||
|
"command": [
|
||||||
|
"function flush",
|
||||||
|
"function stats"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"True",
|
||||||
|
[
|
||||||
|
"running_script", null,
|
||||||
|
"engines",
|
||||||
|
[
|
||||||
|
"LUA",
|
||||||
|
[
|
||||||
|
"libraries_count", 0,
|
||||||
|
"functions_count", 0
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"since": "7.0.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "script exists command",
|
||||||
|
"command": [
|
||||||
|
"script load return",
|
||||||
|
"script exists 63143b6f8007b98c53ca2149822777b3566f9241",
|
||||||
|
"script flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"63143b6f8007b98c53ca2149822777b3566f9241",
|
||||||
|
[
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"True"
|
||||||
|
],
|
||||||
|
"since": "2.6.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "script flush command",
|
||||||
|
"command": [
|
||||||
|
"script load return",
|
||||||
|
"script flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"63143b6f8007b98c53ca2149822777b3566f9241",
|
||||||
|
"True"
|
||||||
|
],
|
||||||
|
"since": "2.6.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "script flush with sync",
|
||||||
|
"command": [
|
||||||
|
"script load return",
|
||||||
|
"script flush sync"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"63143b6f8007b98c53ca2149822777b3566f9241",
|
||||||
|
"OK"
|
||||||
|
],
|
||||||
|
"since": "6.2.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "script flush with async",
|
||||||
|
"command": [
|
||||||
|
"script load return",
|
||||||
|
"script flush async"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"63143b6f8007b98c53ca2149822777b3566f9241",
|
||||||
|
"OK"
|
||||||
|
],
|
||||||
|
"since": "6.2.0"
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "script load command",
|
||||||
|
"command": [
|
||||||
|
"script load return",
|
||||||
|
"script flush"
|
||||||
|
],
|
||||||
|
"result": [
|
||||||
|
"63143b6f8007b98c53ca2149822777b3566f9241",
|
||||||
|
"True"
|
||||||
|
],
|
||||||
|
"since": "2.6.0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -104,7 +104,7 @@ def trans_result_to_bytes(result):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def trans_cmd(test, cmd):
|
def trans_cmd_to_binary(test, cmd):
|
||||||
if 'command_binary' in test:
|
if 'command_binary' in test:
|
||||||
array = bytearray()
|
array = bytearray()
|
||||||
i = 0
|
i = 0
|
||||||
|
@ -137,21 +137,28 @@ def trans_cmd(test, cmd):
|
||||||
array.append(ord(cmd[i]))
|
array.append(ord(cmd[i]))
|
||||||
i += 1
|
i += 1
|
||||||
return bytes(array)
|
return bytes(array)
|
||||||
elif 'command_split' in test:
|
else:
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
|
def split_cmd_as_list(test, cmd):
|
||||||
|
if 'command_split' in test:
|
||||||
# split command by ""
|
# split command by ""
|
||||||
# input: 'hello "world of python" example'
|
# input: 'hello "world of python" example'
|
||||||
# output: ['hello', 'world of python', 'example']
|
# output: ['hello', 'world of python', 'example']
|
||||||
parts = []
|
parts = []
|
||||||
in_quote = False
|
in_quote = False
|
||||||
current_part = ''
|
current_part = b''
|
||||||
for char in cmd:
|
for char in cmd:
|
||||||
if char == '"':
|
# If command_binary is true, then char is `int`, otherwise char is str.
|
||||||
|
byte = ord(char) if isinstance(char, str) else char
|
||||||
|
if byte == ord('"'):
|
||||||
in_quote = not in_quote
|
in_quote = not in_quote
|
||||||
elif char == ' ' and not in_quote:
|
elif byte == ord(' ') and not in_quote:
|
||||||
parts.append(current_part)
|
parts.append(current_part)
|
||||||
current_part = ''
|
current_part = b''
|
||||||
else:
|
else:
|
||||||
current_part += char
|
current_part += char.encode() if isinstance(char, str) else bytes([char])
|
||||||
parts.append(current_part)
|
parts.append(current_part)
|
||||||
return parts
|
return parts
|
||||||
else:
|
else:
|
||||||
|
@ -190,11 +197,12 @@ def run_test(test):
|
||||||
trans_result_to_bytes(result)
|
trans_result_to_bytes(result)
|
||||||
try:
|
try:
|
||||||
for idx, cmd in enumerate(command):
|
for idx, cmd in enumerate(command):
|
||||||
tcmd = trans_cmd(test, cmd)
|
cmd = trans_cmd_to_binary(test, cmd)
|
||||||
if (isinstance(tcmd, list)):
|
tcmd = split_cmd_as_list(test, cmd)
|
||||||
ret = trans_result_to_bytes(r.execute_command(*trans_cmd(test, cmd)))
|
if isinstance(tcmd, list):
|
||||||
|
ret = trans_result_to_bytes(r.execute_command(*tcmd))
|
||||||
else:
|
else:
|
||||||
ret = trans_result_to_bytes(r.execute_command(trans_cmd(test, cmd)))
|
ret = trans_result_to_bytes(r.execute_command(tcmd))
|
||||||
if 'sort_result' in test and isinstance(result[idx], list):
|
if 'sort_result' in test and isinstance(result[idx], list):
|
||||||
sort_nested_list(ret)
|
sort_nested_list(ret)
|
||||||
sort_nested_list(result[idx])
|
sort_nested_list(result[idx])
|
||||||
|
|
Loading…
Reference in New Issue