Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
2667c412
Unverified
Commit
2667c412
authored
Jun 08, 2022
by
Oran Agra
Committed by
GitHub
Jun 08, 2022
Browse files
Merge pull request #10829 from oranagra/release-7.0.1
Release 7.0.1
parents
d375595d
595e725d
Changes
110
Hide whitespace changes
Inline
Side-by-side
tests/unit/pubsubshard.tcl
View file @
2667c412
...
...
@@ -7,14 +7,14 @@ start_server {tags {"pubsubshard external:skip"}} {
assert_equal
{
2
}
[
ssubscribe $rd1
{
chan2
}]
assert_equal 1
[
r SPUBLISH chan1 hello
]
assert_equal 1
[
r SPUBLISH chan2 world
]
assert_equal
{
message chan1 hello
}
[
$rd1
read
]
assert_equal
{
message chan2 world
}
[
$rd1
read
]
assert_equal
{
s
message chan1 hello
}
[
$rd1
read
]
assert_equal
{
s
message chan2 world
}
[
$rd1
read
]
# unsubscribe from one of the channels
sunsubscribe $rd1
{
chan1
}
assert_equal 0
[
r SPUBLISH chan1 hello
]
assert_equal 1
[
r SPUBLISH chan2 world
]
assert_equal
{
message chan2 world
}
[
$rd1
read
]
assert_equal
{
s
message chan2 world
}
[
$rd1
read
]
# unsubscribe from the remaining channel
sunsubscribe $rd1
{
chan2
}
...
...
@@ -32,8 +32,8 @@ start_server {tags {"pubsubshard external:skip"}} {
assert_equal
{
1
}
[
ssubscribe $rd1
{
chan1
}]
assert_equal
{
1
}
[
ssubscribe $rd2
{
chan1
}]
assert_equal 2
[
r SPUBLISH chan1 hello
]
assert_equal
{
message chan1 hello
}
[
$rd1
read
]
assert_equal
{
message chan1 hello
}
[
$rd2
read
]
assert_equal
{
s
message chan1 hello
}
[
$rd1
read
]
assert_equal
{
s
message chan1 hello
}
[
$rd2
read
]
# clean up clients
$rd1 close
...
...
@@ -58,7 +58,7 @@ start_server {tags {"pubsubshard external:skip"}} {
set rd1
[
redis_deferring_client
]
assert_equal
{
1 1 1
}
[
ssubscribe $rd1
{
chan1 chan1 chan1
}]
assert_equal 1
[
r SPUBLISH chan1 hello
]
assert_equal
{
message chan1 hello
}
[
$rd1
read
]
assert_equal
{
s
message chan1 hello
}
[
$rd1
read
]
# clean up clients
$rd1 close
...
...
@@ -129,9 +129,9 @@ start_server {tags {"pubsubshard external:skip"}} {
assert_equal
{
1
}
[
ssubscribe $rd1
{
chan1
}]
$rd0 SPUBLISH chan1 hello
assert_equal
{
message chan1 hello
}
[
$rd1
read
]
assert_equal
{
s
message chan1 hello
}
[
$rd1
read
]
$rd0 SPUBLISH chan1 world
assert_equal
{
message chan1 world
}
[
$rd1
read
]
assert_equal
{
s
message chan1 world
}
[
$rd1
read
]
}
}
}
\ No newline at end of file
tests/unit/scripting.tcl
View file @
2667c412
...
...
@@ -1416,18 +1416,49 @@ start_server {tags {"scripting"}} {
]
{
123
}
# Fail to execute regardless of script content when we use default flags in OOM condition
assert_error
{
OOM
allow-oom flag is not set on the script, can not run it when used memory > 'maxmemory'
}
{
assert_error
{
OOM
*
}
{
r eval
{
#!lua flags=
return 1
}
0
}
# Script with allow-oom can write despite being in OOM state
assert_equal
[
r eval
{
#!lua flags=allow-oom
redis.call
(
'set','x',1
)
return 1
}
1 x
]
1
# read-only scripts implies allow-oom
assert_equal
[
r eval
{
#!lua flags=no-writes
redis.call
(
'get','x'
)
return 1
}
0
]
1
assert_equal
[
r eval_ro
{
#!lua flags=no-writes
redis.call
(
'get','x'
)
return 1
}
1 x
]
1
# Script with no shebang can read in OOM state
assert_equal
[
r eval
{
redis.call
(
'get','x'
)
return 1
}
1 x
]
1
# Script with no shebang can read in OOM state
(
eval_ro variant
)
assert_equal
[
r eval_ro
{
redis.call
(
'get','x'
)
return 1
}
1 x
]
1
r config set maxmemory 0
}
{
OK
}
{
needs:config-maxmemory
}
...
...
@@ -1458,12 +1489,85 @@ start_server {tags {"scripting"}} {
}
1 x
]
"some value"
assert_error
{
ERR Can not run script with write flag on
readonly replica
}
{
assert_error
{
READONLY You can't write against a
read
only replica
.
}
{
r eval
{
#!lua
return redis.call
(
'get','x'
)
}
1 x
}
# test no-write inside multi-exec
r multi
r eval
{
#!lua flags=no-writes
redis.call
(
'get','x'
)
return 1
}
1 x
assert_equal
[
r exec
]
1
# test no shebang without write inside multi-exec
r multi
r eval
{
redis.call
(
'get','x'
)
return 1
}
1 x
assert_equal
[
r exec
]
1
# temporarily set the server to master, so it doesn't block the queuing
# and we can test the evaluation of the flags on exec
r replicaof no one
set rr
[
redis_client
]
set rr2
[
redis_client
]
$rr multi
$rr2 multi
# test write inside multi-exec
# we don't need to do any actual write
$rr eval
{
#!lua
return 1
}
0
# test no shebang with write inside multi-exec
$rr2 eval
{
redis.call
(
'set','x',1
)
return 1
}
1 x
r replicaof
[
srv -1 host
]
[
srv -1 port
]
assert_error
{
EXECABORT Transaction discarded because of: READONLY *
}
{
$rr
exec
}
assert_error
{
READONLY You can't write against a read only replica. script: *
}
{
$rr2
exec
}
$rr close
$rr2 close
}
}
test
"not enough good replicas"
{
r set x
"some value"
r config set min-replicas-to-write 1
assert_equal
[
r eval
{
#!lua flags=no-writes
return redis.call
(
'get','x'
)
}
1 x
]
"some value"
assert_equal
[
r eval
{
return redis.call
(
'get','x'
)
}
1 x
]
"some value"
assert_error
{
NOREPLICAS *
}
{
r eval
{
#!lua
return redis.call
(
'get','x'
)
}
1 x
}
assert_error
{
NOREPLICAS *
}
{
r eval
{
return redis.call
(
'set','x', 1
)
}
1 x
}
r config set min-replicas-to-write 0
}
test
"allow-stale shebang flag"
{
...
...
@@ -1476,7 +1580,7 @@ start_server {tags {"scripting"}} {
}
1 x
}
assert_error
{
*'allow-stale' flag is not set on the script*
}
{
assert_error
{
MASTERDOWN Link with MASTER is down and replica-serve-stale-data is set to 'no'.
}
{
r eval
{
#!lua flags=no-writes
return 1
}
0
...
...
@@ -1517,7 +1621,7 @@ start_server {tags {"scripting"}} {
test
"reject script do not cause a Lua stack leak"
{
r config set maxmemory 1
for
{
set i 0
}
{
$i
< 50
}
{
incr i
}
{
assert_error
{
OOM
allow-oom flag is not set on the script, can not run it when used memory > 'maxmemory'
}
{
r eval
{
#!lua
assert_error
{
OOM
*
}
{
r eval
{
#!lua
return 1
}
0
}
}
...
...
tests/unit/tracking.tcl
View file @
2667c412
...
...
@@ -208,6 +208,33 @@ start_server {tags {"tracking network"}} {
assert
{
$res
eq
{
key1
}}
}
test
{
Tracking only occurs for scripts when a command calls a read-only command
}
{
r CLIENT TRACKING off
r CLIENT TRACKING on
$rd_sg MSET key2
{
t
}
1 key2
{
t
}
1
# If a script doesn't call any read command, don't track any keys
r EVAL
"redis.call('set', 'key3{t}', 'bar')"
2 key1
{
t
}
key2
{
t
}
$rd_sg MSET key2
{
t
}
2 key1
{
t
}
2
# If a script calls a read command, track all declared keys
r EVAL
"redis.call('get', 'key3{t}')"
2 key1
{
t
}
key2
{
t
}
$rd_sg MSET key2
{
t
}
2 key1
{
t
}
2
assert_equal
{
invalidate key2
{
t
}}
[
r read
]
assert_equal
{
invalidate key1
{
t
}}
[
r read
]
# RO variants work like the normal variants
r EVAL_RO
"redis.call('ping')"
2 key1
{
t
}
key2
{
t
}
$rd_sg MSET key2
{
t
}
2 key1
{
t
}
2
r EVAL_RO
"redis.call('get', 'key1{t}')"
2 key1
{
t
}
key2
{
t
}
$rd_sg MSET key2
{
t
}
3 key1
{
t
}
3
assert_equal
{
invalidate key2
{
t
}}
[
r read
]
assert_equal
{
invalidate key1
{
t
}}
[
r read
]
assert_equal
"PONG"
[
r ping
]
}
test
{
RESP3 Client gets tracking-redir-broken push message after cached key changed when rediretion client is terminated
}
{
r CLIENT TRACKING on REDIRECT $redir_id
$rd_sg SET key1 1
...
...
@@ -369,7 +396,7 @@ start_server {tags {"tracking network"}} {
$r CLIENT TRACKING OFF
}
test
{
hdel deliver invlidate message after response in the same connection
}
{
test
{
hdel deliver inv
a
lidate message after response in the same connection
}
{
r CLIENT TRACKING off
r HELLO 3
r CLIENT TRACKING on
...
...
tests/unit/type/list.tcl
View file @
2667c412
...
...
@@ -389,12 +389,13 @@ start_server {
assert
{[
r LPOS mylist c
]
== 2
}
}
test
{
LPOS RANK
(
positive
and
negative rank
)
option
}
{
test
{
LPOS RANK
(
positive
,
negative
and zero
rank
)
option
}
{
assert
{[
r LPOS mylist c RANK 1
]
== 2
}
assert
{[
r LPOS mylist c RANK 2
]
== 6
}
assert
{[
r LPOS mylist c RANK 4
]
eq
""
}
assert
{[
r LPOS mylist c RANK -1
]
== 7
}
assert
{[
r LPOS mylist c RANK -2
]
== 6
}
assert_error
"*RANK can't be zero: use 1 to start from the first match, 2 from the second ... or use negative to start*"
{
r LPOS mylist c RANK 0
}
}
test
{
LPOS COUNT option
}
{
...
...
tests/unit/type/set.tcl
View file @
2667c412
...
...
@@ -285,6 +285,13 @@ start_server {
}
assert_equal
{
1 2 3 4
}
[
lsort
[
r smembers setres
{
t
}]]
}
test
"SINTER/SUNION/SDIFF with three same sets -
$type
"
{
set expected
[
lsort
"
[
r smembers set1
{
t
}]
"
]
assert_equal $expected
[
lsort
[
r sinter set1
{
t
}
set1
{
t
}
set1
{
t
}]]
assert_equal $expected
[
lsort
[
r sunion set1
{
t
}
set1
{
t
}
set1
{
t
}]]
assert_equal
{}
[
lsort
[
r sdiff set1
{
t
}
set1
{
t
}
set1
{
t
}]]
}
}
test
"SDIFF with first set empty"
{
...
...
tests/unit/type/zset.tcl
View file @
2667c412
...
...
@@ -2065,6 +2065,33 @@ start_server {tags {"zset"}} {
close_replication_stream $repl
}
{}
{
needs:repl
}
test
"BZMPOP should not blocks on non key arguments - #10762"
{
set rd1
[
redis_deferring_client
]
set rd2
[
redis_deferring_client
]
r del myzset myzset2 myzset3
$rd1 bzmpop 0 1 myzset min count 10
wait_for_blocked_clients_count 1
$rd2 bzmpop 0 2 myzset2 myzset3 max count 10
wait_for_blocked_clients_count 2
# These non-key keys will not unblock the clients.
r zadd 0 100 timeout_value
r zadd 1 200 numkeys_value
r zadd min 300 min_token
r zadd max 400 max_token
r zadd count 500 count_token
r zadd 10 600 count_value
r zadd myzset 1 zset
r zadd myzset3 1 zset3
assert_equal
{
myzset
{{
zset 1
}}}
[
$rd1
read
]
assert_equal
{
myzset3
{{
zset3 1
}}}
[
$rd2
read
]
$rd1 close
$rd2 close
}
{
0
}
{
cluster:skip
}
test
{
ZSET skiplist order consistency when elements are moved
}
{
set original_max
[
lindex
[
r config get zset-max-ziplist-entries
]
1
]
r config set zset-max-ziplist-entries 0
...
...
@@ -2181,6 +2208,15 @@ start_server {tags {"zset"}} {
assert_match
"*syntax*"
$err
}
test
{
ZRANGESTORE with zset-max-listpack-entries 0 dst key should use skiplist encoding
}
{
set original_max
[
lindex
[
r config get zset-max-listpack-entries
]
1
]
r config set zset-max-listpack-entries 0
r del z1
{
t
}
z2
{
t
}
r zadd z1
{
t
}
1 a
assert_equal 1
[
r zrangestore z2
{
t
}
z1
{
t
}
0 -1
]
r config set zset-max-listpack-entries $original_max
}
test
{
ZRANGE invalid syntax
}
{
catch
{
r zrange z1
{
t
}
0 -1 limit 1 2
}
err
assert_match
"*syntax*"
$err
...
...
utils/generate-command-code.py
View file @
2667c412
#!/usr/bin/env python3
import
os
import
glob
import
json
import
os
ARG_TYPES
=
{
"string"
:
"ARG_TYPE_STRING"
,
...
...
@@ -68,6 +67,55 @@ def get_optional_desc_string(desc, field, force_uppercase=False):
return
ret
.
replace
(
"
\n
"
,
"
\\
n"
)
def
check_command_args_key_specs
(
args
,
command_key_specs_index_set
,
command_arg_key_specs_index_set
):
if
not
args
:
return
True
for
arg
in
args
:
if
arg
.
key_spec_index
is
not
None
:
assert
isinstance
(
arg
.
key_spec_index
,
int
)
if
arg
.
key_spec_index
not
in
command_key_specs_index_set
:
print
(
"command: %s arg: %s key_spec_index error"
%
(
command
.
fullname
(),
arg
.
name
))
return
False
command_arg_key_specs_index_set
.
add
(
arg
.
key_spec_index
)
if
not
check_command_args_key_specs
(
arg
.
subargs
,
command_key_specs_index_set
,
command_arg_key_specs_index_set
):
return
False
return
True
def
check_command_key_specs
(
command
):
if
not
command
.
key_specs
:
return
True
assert
isinstance
(
command
.
key_specs
,
list
)
for
cmd_key_spec
in
command
.
key_specs
:
if
"flags"
not
in
cmd_key_spec
:
print
(
"command: %s key_specs missing flags"
%
command
.
fullname
())
return
False
if
"NOT_KEY"
in
cmd_key_spec
[
"flags"
]:
# Like SUNSUBSCRIBE / SPUBLISH / SSUBSCRIBE
return
True
command_key_specs_index_set
=
set
(
range
(
len
(
command
.
key_specs
)))
command_arg_key_specs_index_set
=
set
()
# Collect key_spec used for each arg, including arg.subarg
if
not
check_command_args_key_specs
(
command
.
args
,
command_key_specs_index_set
,
command_arg_key_specs_index_set
):
return
False
# Check if we have key_specs not used
if
command_key_specs_index_set
!=
command_arg_key_specs_index_set
:
print
(
"command: %s may have unused key_spec"
%
command
.
fullname
())
return
False
return
True
# Globals
subcommands
=
{}
# container_name -> dict(subcommand_name -> Subcommand) - Only subcommands
commands
=
{}
# command_name -> Command - Only commands
...
...
@@ -132,6 +180,7 @@ class Argument(object):
self
.
desc
=
desc
self
.
name
=
self
.
desc
[
"name"
].
lower
()
self
.
type
=
self
.
desc
[
"type"
]
self
.
key_spec_index
=
self
.
desc
.
get
(
"key_spec_index"
,
None
)
self
.
parent_name
=
parent_name
self
.
subargs
=
[]
self
.
subargs_name
=
None
...
...
@@ -200,6 +249,7 @@ class Command(object):
self
.
name
=
name
.
upper
()
self
.
desc
=
desc
self
.
group
=
self
.
desc
[
"group"
]
self
.
key_specs
=
self
.
desc
.
get
(
"key_specs"
,
[])
self
.
subcommands
=
[]
self
.
args
=
[]
for
arg_desc
in
self
.
desc
.
get
(
"arguments"
,
[]):
...
...
@@ -271,7 +321,7 @@ class Command(object):
def
_key_specs_code
():
s
=
""
for
spec
in
self
.
desc
.
get
(
"
key_specs
"
,
[])
:
for
spec
in
self
.
key_specs
:
s
+=
"{%s},"
%
KeySpec
(
spec
).
struct_code
()
return
s
[:
-
1
]
...
...
@@ -398,6 +448,17 @@ for command in commands.values():
subcommand
.
group
=
command
.
group
command
.
subcommands
.
append
(
subcommand
)
check_command_error_counter
=
0
# An error counter is used to count errors in command checking.
print
(
"Checking all commands..."
)
for
command
in
commands
.
values
():
if
not
check_command_key_specs
(
command
):
check_command_error_counter
+=
1
if
check_command_error_counter
!=
0
:
print
(
"Error: There are errors in the commands check, please check the above logs."
)
exit
(
1
)
print
(
"Generating commands.c..."
)
with
open
(
"%s/commands.c"
%
srcdir
,
"w"
)
as
f
:
f
.
write
(
"/* Automatically generated by %s, do not edit. */
\n\n
"
%
os
.
path
.
basename
(
__file__
))
...
...
utils/generate-command-help.rb
View file @
2667c412
...
...
@@ -45,7 +45,11 @@ def argument arg
name
=
arg
[
"name"
].
is_a?
(
Array
)
?
arg
[
"name"
].
join
(
" "
)
:
arg
[
"name"
]
end
if
arg
[
"multiple"
]
name
=
"
#{
name
}
[
#{
name
}
...]"
if
arg
[
"multiple_token"
]
name
=
"
#{
name
}
[
#{
arg
[
"token"
]
}
#{
name
}
...]"
else
name
=
"
#{
name
}
[
#{
name
}
...]"
end
end
if
arg
[
"token"
]
name
=
[
arg
[
"token"
],
name
].
compact
.
join
" "
...
...
utils/generate-commands-json.py
View file @
2667c412
#!/usr/bin/env python3
import
argparse
import
json
import
os
import
subprocess
from
collections
import
OrderedDict
from
sys
import
argv
,
stdin
import
os
from
sys
import
argv
def
convert_flags_to_boolean_dict
(
flags
):
...
...
@@ -118,7 +118,8 @@ if __name__ == '__main__':
stdout
,
stderr
=
p
.
communicate
()
commands
=
json
.
loads
(
stdout
)
p
=
subprocess
.
Popen
([
args
.
cli
,
'-h'
,
args
.
host
,
'-p'
,
str
(
args
.
port
),
'--json'
,
'command'
,
'docs'
],
stdout
=
subprocess
.
PIPE
)
p
=
subprocess
.
Popen
([
args
.
cli
,
'-h'
,
args
.
host
,
'-p'
,
str
(
args
.
port
),
'--json'
,
'command'
,
'docs'
],
stdout
=
subprocess
.
PIPE
)
stdout
,
stderr
=
p
.
communicate
()
docs
=
json
.
loads
(
stdout
)
...
...
utils/generate-module-api-doc.rb
View file @
2667c412
#!/usr/bin/env ruby
# coding: utf-8
# gendoc.rb -- Converts the top-comments inside module.c to modules API
# reference documentation in markdown format.
...
...
@@ -80,7 +79,7 @@ def docufy(src,i)
puts
"<span id=
\"
#{
name
}
\"
></span>
\n\n
"
puts
"### `
#{
name
}
`
\n\n
"
puts
"
#{
proto
}
\n
"
puts
"**Available since:**
#{
$since
[
name
]
}
\n\n
"
if
$since
[
name
]
puts
"**Available since:**
#{
$since
[
name
]
or
"unreleased"
}
\n\n
"
comment
=
""
while
true
i
=
i
-
1
...
...
@@ -137,7 +136,16 @@ def is_func_line(src, i)
src
[
i
-
1
]
=~
/\*\//
end
puts
"# Modules API reference
\n\n
"
puts
"---
\n
"
puts
"title:
\"
Modules API reference
\"\n
"
puts
"linkTitle:
\"
API reference
\"\n
"
puts
"weight: 1
\n
"
puts
"description: >
\n
"
puts
" Reference for the Redis Modules API
\n
"
puts
"aliases:
\n
"
puts
" - /topics/modules-api-ref
\n
"
puts
"---
\n
"
puts
"
\n
"
puts
"<!-- This file is generated from module.c using
\n
"
puts
" utils/generate-module-api-doc.rb -->
\n\n
"
src
=
File
.
open
(
File
.
dirname
(
__FILE__
)
++
"/../src/module.c"
).
to_a
...
...
Prev
1
2
3
4
5
6
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment