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
a5d2df34
Commit
a5d2df34
authored
Jun 08, 2022
by
Oran Agra
Browse files
Merge remote-tracking branch 'origin/unstable' into 7.0
parents
d375595d
f22bfe86
Changes
108
Hide whitespace changes
Inline
Side-by-side
tests/unit/tracking.tcl
View file @
a5d2df34
...
@@ -208,6 +208,33 @@ start_server {tags {"tracking network"}} {
...
@@ -208,6 +208,33 @@ start_server {tags {"tracking network"}} {
assert
{
$res
eq
{
key1
}}
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
}
{
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
r CLIENT TRACKING on REDIRECT $redir_id
$rd_sg SET key1 1
$rd_sg SET key1 1
...
@@ -369,7 +396,7 @@ start_server {tags {"tracking network"}} {
...
@@ -369,7 +396,7 @@ start_server {tags {"tracking network"}} {
$r CLIENT TRACKING OFF
$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 CLIENT TRACKING off
r HELLO 3
r HELLO 3
r CLIENT TRACKING on
r CLIENT TRACKING on
...
...
tests/unit/type/list.tcl
View file @
a5d2df34
...
@@ -389,12 +389,13 @@ start_server {
...
@@ -389,12 +389,13 @@ start_server {
assert
{[
r LPOS mylist c
]
== 2
}
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 1
]
== 2
}
assert
{[
r LPOS mylist c RANK 2
]
== 6
}
assert
{[
r LPOS mylist c RANK 2
]
== 6
}
assert
{[
r LPOS mylist c RANK 4
]
eq
""
}
assert
{[
r LPOS mylist c RANK 4
]
eq
""
}
assert
{[
r LPOS mylist c RANK -1
]
== 7
}
assert
{[
r LPOS mylist c RANK -1
]
== 7
}
assert
{[
r LPOS mylist c RANK -2
]
== 6
}
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
}
{
test
{
LPOS COUNT option
}
{
...
...
tests/unit/type/set.tcl
View file @
a5d2df34
...
@@ -285,6 +285,13 @@ start_server {
...
@@ -285,6 +285,13 @@ start_server {
}
}
assert_equal
{
1 2 3 4
}
[
lsort
[
r smembers setres
{
t
}]]
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"
{
test
"SDIFF with first set empty"
{
...
...
tests/unit/type/zset.tcl
View file @
a5d2df34
...
@@ -2065,6 +2065,33 @@ start_server {tags {"zset"}} {
...
@@ -2065,6 +2065,33 @@ start_server {tags {"zset"}} {
close_replication_stream $repl
close_replication_stream $repl
}
{}
{
needs: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
}
{
test
{
ZSET skiplist order consistency when elements are moved
}
{
set original_max
[
lindex
[
r config get zset-max-ziplist-entries
]
1
]
set original_max
[
lindex
[
r config get zset-max-ziplist-entries
]
1
]
r config set zset-max-ziplist-entries 0
r config set zset-max-ziplist-entries 0
...
@@ -2181,6 +2208,15 @@ start_server {tags {"zset"}} {
...
@@ -2181,6 +2208,15 @@ start_server {tags {"zset"}} {
assert_match
"*syntax*"
$err
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
}
{
test
{
ZRANGE invalid syntax
}
{
catch
{
r zrange z1
{
t
}
0 -1 limit 1 2
}
err
catch
{
r zrange z1
{
t
}
0 -1 limit 1 2
}
err
assert_match
"*syntax*"
$err
assert_match
"*syntax*"
$err
...
...
utils/generate-command-code.py
View file @
a5d2df34
#!/usr/bin/env python3
#!/usr/bin/env python3
import
os
import
glob
import
glob
import
json
import
json
import
os
ARG_TYPES
=
{
ARG_TYPES
=
{
"string"
:
"ARG_TYPE_STRING"
,
"string"
:
"ARG_TYPE_STRING"
,
...
@@ -68,6 +67,55 @@ def get_optional_desc_string(desc, field, force_uppercase=False):
...
@@ -68,6 +67,55 @@ def get_optional_desc_string(desc, field, force_uppercase=False):
return
ret
.
replace
(
"
\n
"
,
"
\\
n"
)
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
# Globals
subcommands
=
{}
# container_name -> dict(subcommand_name -> Subcommand) - Only subcommands
subcommands
=
{}
# container_name -> dict(subcommand_name -> Subcommand) - Only subcommands
commands
=
{}
# command_name -> Command - Only commands
commands
=
{}
# command_name -> Command - Only commands
...
@@ -132,6 +180,7 @@ class Argument(object):
...
@@ -132,6 +180,7 @@ class Argument(object):
self
.
desc
=
desc
self
.
desc
=
desc
self
.
name
=
self
.
desc
[
"name"
].
lower
()
self
.
name
=
self
.
desc
[
"name"
].
lower
()
self
.
type
=
self
.
desc
[
"type"
]
self
.
type
=
self
.
desc
[
"type"
]
self
.
key_spec_index
=
self
.
desc
.
get
(
"key_spec_index"
,
None
)
self
.
parent_name
=
parent_name
self
.
parent_name
=
parent_name
self
.
subargs
=
[]
self
.
subargs
=
[]
self
.
subargs_name
=
None
self
.
subargs_name
=
None
...
@@ -200,6 +249,7 @@ class Command(object):
...
@@ -200,6 +249,7 @@ class Command(object):
self
.
name
=
name
.
upper
()
self
.
name
=
name
.
upper
()
self
.
desc
=
desc
self
.
desc
=
desc
self
.
group
=
self
.
desc
[
"group"
]
self
.
group
=
self
.
desc
[
"group"
]
self
.
key_specs
=
self
.
desc
.
get
(
"key_specs"
,
[])
self
.
subcommands
=
[]
self
.
subcommands
=
[]
self
.
args
=
[]
self
.
args
=
[]
for
arg_desc
in
self
.
desc
.
get
(
"arguments"
,
[]):
for
arg_desc
in
self
.
desc
.
get
(
"arguments"
,
[]):
...
@@ -271,7 +321,7 @@ class Command(object):
...
@@ -271,7 +321,7 @@ class Command(object):
def
_key_specs_code
():
def
_key_specs_code
():
s
=
""
s
=
""
for
spec
in
self
.
desc
.
get
(
"
key_specs
"
,
[])
:
for
spec
in
self
.
key_specs
:
s
+=
"{%s},"
%
KeySpec
(
spec
).
struct_code
()
s
+=
"{%s},"
%
KeySpec
(
spec
).
struct_code
()
return
s
[:
-
1
]
return
s
[:
-
1
]
...
@@ -398,6 +448,17 @@ for command in commands.values():
...
@@ -398,6 +448,17 @@ for command in commands.values():
subcommand
.
group
=
command
.
group
subcommand
.
group
=
command
.
group
command
.
subcommands
.
append
(
subcommand
)
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..."
)
print
(
"Generating commands.c..."
)
with
open
(
"%s/commands.c"
%
srcdir
,
"w"
)
as
f
:
with
open
(
"%s/commands.c"
%
srcdir
,
"w"
)
as
f
:
f
.
write
(
"/* Automatically generated by %s, do not edit. */
\n\n
"
%
os
.
path
.
basename
(
__file__
))
f
.
write
(
"/* Automatically generated by %s, do not edit. */
\n\n
"
%
os
.
path
.
basename
(
__file__
))
...
...
utils/generate-command-help.rb
View file @
a5d2df34
...
@@ -45,7 +45,11 @@ def argument arg
...
@@ -45,7 +45,11 @@ def argument arg
name
=
arg
[
"name"
].
is_a?
(
Array
)
?
arg
[
"name"
].
join
(
" "
)
:
arg
[
"name"
]
name
=
arg
[
"name"
].
is_a?
(
Array
)
?
arg
[
"name"
].
join
(
" "
)
:
arg
[
"name"
]
end
end
if
arg
[
"multiple"
]
if
arg
[
"multiple"
]
name
=
"
#{
name
}
[
#{
name
}
...]"
if
arg
[
"multiple_token"
]
name
=
"
#{
name
}
[
#{
arg
[
"token"
]
}
#{
name
}
...]"
else
name
=
"
#{
name
}
[
#{
name
}
...]"
end
end
end
if
arg
[
"token"
]
if
arg
[
"token"
]
name
=
[
arg
[
"token"
],
name
].
compact
.
join
" "
name
=
[
arg
[
"token"
],
name
].
compact
.
join
" "
...
...
utils/generate-commands-json.py
View file @
a5d2df34
#!/usr/bin/env python3
#!/usr/bin/env python3
import
argparse
import
argparse
import
json
import
json
import
os
import
subprocess
import
subprocess
from
collections
import
OrderedDict
from
collections
import
OrderedDict
from
sys
import
argv
,
stdin
from
sys
import
argv
import
os
def
convert_flags_to_boolean_dict
(
flags
):
def
convert_flags_to_boolean_dict
(
flags
):
...
@@ -118,7 +118,8 @@ if __name__ == '__main__':
...
@@ -118,7 +118,8 @@ if __name__ == '__main__':
stdout
,
stderr
=
p
.
communicate
()
stdout
,
stderr
=
p
.
communicate
()
commands
=
json
.
loads
(
stdout
)
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
()
stdout
,
stderr
=
p
.
communicate
()
docs
=
json
.
loads
(
stdout
)
docs
=
json
.
loads
(
stdout
)
...
...
utils/generate-module-api-doc.rb
View file @
a5d2df34
#!/usr/bin/env ruby
#!/usr/bin/env ruby
# coding: utf-8
# coding: utf-8
# gendoc.rb -- Converts the top-comments inside module.c to modules API
# gendoc.rb -- Converts the top-comments inside module.c to modules API
# reference documentation in markdown format.
# reference documentation in markdown format.
...
@@ -80,7 +79,7 @@ def docufy(src,i)
...
@@ -80,7 +79,7 @@ def docufy(src,i)
puts
"<span id=
\"
#{
name
}
\"
></span>
\n\n
"
puts
"<span id=
\"
#{
name
}
\"
></span>
\n\n
"
puts
"### `
#{
name
}
`
\n\n
"
puts
"### `
#{
name
}
`
\n\n
"
puts
"
#{
proto
}
\n
"
puts
"
#{
proto
}
\n
"
puts
"**Available since:**
#{
$since
[
name
]
}
\n\n
"
if
$since
[
name
]
puts
"**Available since:**
#{
$since
[
name
]
or
"unreleased"
}
\n\n
"
comment
=
""
comment
=
""
while
true
while
true
i
=
i
-
1
i
=
i
-
1
...
@@ -137,7 +136,16 @@ def is_func_line(src, i)
...
@@ -137,7 +136,16 @@ def is_func_line(src, i)
src
[
i
-
1
]
=~
/\*\//
src
[
i
-
1
]
=~
/\*\//
end
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
"<!-- This file is generated from module.c using
\n
"
puts
" utils/generate-module-api-doc.rb -->
\n\n
"
puts
" utils/generate-module-api-doc.rb -->
\n\n
"
src
=
File
.
open
(
File
.
dirname
(
__FILE__
)
++
"/../src/module.c"
).
to_a
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