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
b34fc03e
Commit
b34fc03e
authored
Jan 12, 2021
by
Oran Agra
Browse files
Merge unstable into 6.2
parents
b8c67ce4
4f8458d8
Changes
86
Hide whitespace changes
Inline
Side-by-side
src/zmalloc.c
View file @
b34fc03e
...
...
@@ -580,15 +580,18 @@ size_t zmalloc_get_smap_bytes_by_field(char *field, long pid) {
size_t
zmalloc_get_smap_bytes_by_field
(
char
*
field
,
long
pid
)
{
#if defined(__APPLE__)
struct
proc_regioninfo
pri
;
if
(
proc_pidinfo
(
pid
,
PROC_PIDREGIONINFO
,
0
,
&
pri
,
PROC_PIDREGIONINFO_SIZE
)
==
PROC_PIDREGIONINFO_SIZE
)
{
if
(
!
strcmp
(
field
,
"Private_Dirty:"
))
{
return
(
size_t
)
pri
.
pri_pages_dirtied
*
4096
;
}
else
if
(
!
strcmp
(
field
,
"Rss:"
))
{
return
(
size_t
)
pri
.
pri_pages_resident
*
4096
;
}
else
if
(
!
strcmp
(
field
,
"AnonHugePages:"
))
{
if
(
pid
==
-
1
)
pid
=
getpid
();
if
(
proc_pidinfo
(
pid
,
PROC_PIDREGIONINFO
,
0
,
&
pri
,
PROC_PIDREGIONINFO_SIZE
)
==
PROC_PIDREGIONINFO_SIZE
)
{
int
pagesize
=
getpagesize
();
if
(
!
strcmp
(
field
,
"Private_Dirty:"
))
{
return
(
size_t
)
pri
.
pri_pages_dirtied
*
pagesize
;
}
else
if
(
!
strcmp
(
field
,
"Rss:"
))
{
return
(
size_t
)
pri
.
pri_pages_resident
*
pagesize
;
}
else
if
(
!
strcmp
(
field
,
"AnonHugePages:"
))
{
return
0
;
}
}
}
return
0
;
#endif
...
...
tests/cluster/cluster.tcl
View file @
b34fc03e
...
...
@@ -57,6 +57,11 @@ proc CI {n field} {
get_info_field
[
R $n cluster info
]
$field
}
# Return the value of the specified INFO field.
proc s
{
n field
}
{
get_info_field
[
R $n info
]
$field
}
# Assuming nodes are reest, this function performs slots allocation.
# Only the first 'n' nodes are used.
proc cluster_allocate_slots
{
n
}
{
...
...
tests/cluster/tests/16-transactions-on-replica.tcl
View file @
b34fc03e
...
...
@@ -15,6 +15,7 @@ set replica [Rn 1]
test
"Cant read from replica without READONLY"
{
$primary SET a 1
wait_for_ofs_sync $primary $replica
catch
{
$replica
GET a
}
err
assert
{[
string range $err 0 4
]
eq
{
MOVED
}}
}
...
...
@@ -28,6 +29,7 @@ test "Can preform HSET primary and HGET from replica" {
$primary HSET h a 1
$primary HSET h b 2
$primary HSET h c 3
wait_for_ofs_sync $primary $replica
assert
{[
$replica
HGET h a
]
eq
{
1
}}
assert
{[
$replica
HGET h b
]
eq
{
2
}}
assert
{[
$replica
HGET h c
]
eq
{
3
}}
...
...
tests/cluster/tests/17-diskless-load-swapdb.tcl
View file @
b34fc03e
...
...
@@ -22,6 +22,8 @@ test "Right to restore backups when fail to diskless load " {
$replica READONLY
$replica config set repl-diskless-load swapdb
$replica config set appendonly no
$replica config set save
""
$replica config rewrite
$master config set repl-backlog-size 1024
$master config set repl-diskless-sync yes
...
...
@@ -38,7 +40,8 @@ test "Right to restore backups when fail to diskless load " {
assert_equal
{
1
}
[
$replica
get $slot0_key
]
assert_equal $slot0_key
[
$replica
CLUSTER GETKEYSINSLOT 0 1
]
# Kill the replica
# Save an RDB and kill the replica
$replica save
kill_instance redis $replica_id
# Delete the key from master
...
...
@@ -60,13 +63,12 @@ test "Right to restore backups when fail to diskless load " {
restart_instance redis $replica_id
$replica READONLY
# Start full sync
# Start full sync
, wait till after db is flushed
(
backed up
)
wait_for_condition 500 10
{
[
s
tring match
"*sync*"
[
$replica
role
]]
[
s
$replica_id loading
]
eq 1
}
else
{
fail
"Fail to full sync"
}
after 100
# Kill master, abort full sync
kill_instance redis $master_id
...
...
@@ -74,4 +76,4 @@ test "Right to restore backups when fail to diskless load " {
# Replica keys and keys to slots map still both are right
assert_equal
{
1
}
[
$replica
get $slot0_key
]
assert_equal $slot0_key
[
$replica
CLUSTER GETKEYSINSLOT 0 1
]
}
\ No newline at end of file
}
tests/cluster/tests/18-info.tcl
0 → 100644
View file @
b34fc03e
# Check cluster info stats
source
"../tests/includes/init-tests.tcl"
test
"Create a primary with a replica"
{
create_cluster 2 0
}
test
"Cluster should start ok"
{
assert_cluster_state ok
}
set primary1
[
Rn 0
]
set primary2
[
Rn 1
]
proc cmdstat
{
instace cmd
}
{
return
[
cmdrstat $cmd $instace
]
}
proc errorstat
{
instace cmd
}
{
return
[
errorrstat $cmd $instace
]
}
test
"errorstats: rejected call due to MOVED Redirection"
{
$primary1 config resetstat
$primary2 config resetstat
assert_match
{}
[
errorstat $primary1 MOVED
]
assert_match
{}
[
errorstat $primary2 MOVED
]
# we know that one will have a MOVED reply and one will succeed
catch
{
$primary1
set key b
}
replyP1
catch
{
$primary2
set key b
}
replyP2
# sort servers so we know which one failed
if
{
$reply
P1 eq
{
OK
}}
{
assert_match
{
MOVED*
}
$replyP2
set pok $primary1
set perr $primary2
}
else
{
assert_match
{
MOVED*
}
$replyP1
set pok $primary2
set perr $primary1
}
assert_match
{}
[
errorstat $pok MOVED
]
assert_match
{
*count=1*
}
[
errorstat $perr MOVED
]
assert_match
{
*calls=0,*,rejected_calls=1,failed_calls=0
}
[
cmdstat $perr set
]
}
tests/integration/rdb.tcl
View file @
b34fc03e
...
...
@@ -198,3 +198,94 @@ test {client freed during loading} {
exec kill
[
srv 0 pid
]
}
}
# Our COW metrics
(
Private_Dirty
)
work only on Linux
set system_name
[
string tolower
[
exec uname -s
]]
if
{
$system
_name eq
{
linux
}}
{
start_server
{
overrides
{
save
""
}}
{
test
{
Test child sending COW info
}
{
# make sure that rdb_last_cow_size and current_cow_size are zero
(
the test using new server
)
,
# so that the comparisons during the test will be valid
assert
{[
s current_cow_size
]
== 0
}
assert
{[
s rdb_last_cow_size
]
== 0
}
# using a 200us delay, the bgsave is empirically taking about 10 seconds.
# we need it to take more than some 5 seconds, since redis only report COW once a second.
r config set rdb-key-save-delay 200
r config set loglevel debug
# populate the db with 10k keys of 4k each
set rd
[
redis_deferring_client 0
]
set size 4096
set cmd_count 10000
for
{
set k 0
}
{
$k
< $cmd_count
}
{
incr k
}
{
$rd set key$k
[
string repeat A $size
]
}
for
{
set k 0
}
{
$k
< $cmd_count
}
{
incr k
}
{
catch
{
$rd read
}
}
$rd close
# start background rdb save
r bgsave
# on each iteration, we will write some key to the server to trigger copy-on-write, and
# wait to see that it reflected in INFO.
set iteration 1
while 1
{
# take a sample before writing new data to the server
set cow_size
[
s current_cow_size
]
if
{
$::verbose
}
{
puts
"COW info before copy-on-write:
$cow
_size"
}
# trigger copy-on-write
r setrange key$iteration 0
[
string repeat B $size
]
# wait to see that current_cow_size value updated
(
as long as the child is in progress
)
wait_for_condition 80 100
{
[
s rdb_bgsave_in_progress
]
== 0 ||
[
s current_cow_size
]
>= $cow_size + $size
}
else
{
if
{
$::verbose
}
{
puts
"COW info on fail:
[
s current_cow_size
]
"
puts
[
exec tail -n 100 <
[
srv 0 stdout
]]
}
fail
"COW info wasn't reported"
}
# for no accurate, stop after 2 iterations
if
{
!$::accurate && $iteration == 2
}
{
break
}
# stop iterating if the bgsave completed
if
{
[
s rdb_bgsave_in_progress
]
== 0
}
{
break
}
incr iteration 1
}
# make sure we saw report of current_cow_size
if
{
$iteration
< 2 && $::verbose
}
{
puts
[
exec tail -n 100 <
[
srv 0 stdout
]]
}
assert_morethan_equal $iteration 2
# if bgsave completed, check that rdb_last_cow_size
(
fork exit report
)
# is at least 90% of last rdb_active_cow_size.
if
{
[
s rdb_bgsave_in_progress
]
== 0
}
{
set final_cow
[
s rdb_last_cow_size
]
set cow_size
[
expr $cow_size * 0.9
]
if
{
$final
_cow < $cow_size && $::verbose
}
{
puts
[
exec tail -n 100 <
[
srv 0 stdout
]]
}
assert_morethan_equal $final_cow $cow_size
}
}
}
}
;
# system_name
tests/modules/propagate.c
View file @
b34fc03e
...
...
@@ -51,18 +51,31 @@ void timerHandler(RedisModuleCtx *ctx, void *data) {
RedisModule_Replicate
(
ctx
,
"INCR"
,
"c"
,
"timer"
);
times
++
;
if
(
times
<
10
)
if
(
times
<
3
)
RedisModule_CreateTimer
(
ctx
,
100
,
timerHandler
,
NULL
);
else
times
=
0
;
}
int
propagateTestTimerCommand
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
RedisModuleTimerID
timer_id
=
RedisModule_CreateTimer
(
ctx
,
100
,
timerHandler
,
NULL
);
REDISMODULE_NOT_USED
(
timer_id
);
RedisModule_ReplyWithSimpleString
(
ctx
,
"OK"
);
return
REDISMODULE_OK
;
}
/* The thread entry point. */
void
*
threadMain
(
void
*
arg
)
{
REDISMODULE_NOT_USED
(
arg
);
RedisModuleCtx
*
ctx
=
RedisModule_GetThreadSafeContext
(
NULL
);
RedisModule_SelectDb
(
ctx
,
9
);
/* Tests ran in database number 9. */
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
RedisModule_ThreadSafeContextLock
(
ctx
);
RedisModule_Replicate
(
ctx
,
"INCR"
,
"c"
,
"a-from-thread"
);
RedisModule_Replicate
(
ctx
,
"INCR"
,
"c"
,
"b-from-thread"
);
...
...
@@ -72,15 +85,11 @@ void *threadMain(void *arg) {
return
NULL
;
}
int
propagateTestCommand
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
int
propagateTest
Thread
Command
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
RedisModuleTimerID
timer_id
=
RedisModule_CreateTimer
(
ctx
,
100
,
timerHandler
,
NULL
);
REDISMODULE_NOT_USED
(
timer_id
);
pthread_t
tid
;
if
(
pthread_create
(
&
tid
,
NULL
,
threadMain
,
NULL
)
!=
0
)
return
RedisModule_ReplyWithError
(
ctx
,
"-ERR Can't start thread"
);
...
...
@@ -90,7 +99,7 @@ int propagateTestCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc
return
REDISMODULE_OK
;
}
int
propagateTest
2
Command
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
int
propagateTest
Simple
Command
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
...
...
@@ -102,7 +111,7 @@ int propagateTest2Command(RedisModuleCtx *ctx, RedisModuleString **argv, int arg
return
REDISMODULE_OK
;
}
int
propagateTest
3
Command
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
int
propagateTest
Mixed
Command
(
RedisModuleCtx
*
ctx
,
RedisModuleString
**
argv
,
int
argc
)
{
REDISMODULE_NOT_USED
(
argv
);
REDISMODULE_NOT_USED
(
argc
);
...
...
@@ -129,18 +138,23 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
if
(
RedisModule_Init
(
ctx
,
"propagate-test"
,
1
,
REDISMODULE_APIVER_1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"propagate-test"
,
propagateTestCommand
,
if
(
RedisModule_CreateCommand
(
ctx
,
"propagate-test.timer"
,
propagateTestTimerCommand
,
""
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"propagate-test.thread"
,
propagateTestThreadCommand
,
""
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"propagate-test
-2
"
,
propagateTest
2
Command
,
if
(
RedisModule_CreateCommand
(
ctx
,
"propagate-test
.simple
"
,
propagateTest
Simple
Command
,
""
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
if
(
RedisModule_CreateCommand
(
ctx
,
"propagate-test
-3
"
,
propagateTest
3
Command
,
if
(
RedisModule_CreateCommand
(
ctx
,
"propagate-test
.mixed
"
,
propagateTest
Mixed
Command
,
""
,
1
,
1
,
1
)
==
REDISMODULE_ERR
)
return
REDISMODULE_ERR
;
...
...
tests/support/redis.tcl
View file @
b34fc03e
...
...
@@ -214,20 +214,19 @@ proc ::redis::redis_multi_bulk_read {id fd} {
proc ::redis::redis_read_map
{
id fd
}
{
set count
[
redis_read_line $fd
]
if
{
$count
== -1
}
return
{}
set
l
{}
set
d
{}
set err
{}
for
{
set i 0
}
{
$i
< $count
}
{
incr i
}
{
if
{[
catch
{
set t
{}
lappend t
[
redis_read_reply $id $fd
]
;
# key
lappend t
[
redis_read_reply $id $fd
]
;
# value
lappend l $t
set k
[
redis_read_reply $id $fd
]
;
# key
set v
[
redis_read_reply $id $fd
]
;
# value
dict set d $k $v
}
e
]
&& $err eq
{}}
{
set err $e
}
}
if
{
$err
ne
{}}
{
return -code error $err
}
return $
l
return $
d
}
proc ::redis::redis_read_line fd
{
...
...
tests/support/server.tcl
View file @
b34fc03e
...
...
@@ -50,11 +50,17 @@ proc kill_server config {
tags
{
"leaks"
}
{
test
"Check for memory leaks (pid
$pid
)"
{
set output
{
0 leaks
}
catch
{
exec leaks $pid
}
output
if
{[
string match
{
*process does not exist*
}
$output
]
||
[
string match
{
*cannot examine*
}
$output
]}
{
# In a few tests we kill the server process.
set output
"0 leaks"
catch
{
exec leaks $pid
}
output option
# In a few tests we kill the server process, so leaks will not find it.
# It'll exits with exit code >1 on error, so we ignore these.
if
{[
dict exists $option -errorcode
]}
{
set details
[
dict get $option -errorcode
]
if
{[
lindex $details 0
]
eq
"CHILDSTATUS"
}
{
set status
[
lindex $details 2
]
if
{
$status
> 1
}
{
set output
"0 leaks"
}
}
}
set output
}
{
*0 leaks*
}
...
...
tests/support/test.tcl
View file @
b34fc03e
...
...
@@ -31,36 +31,48 @@ proc assert_match {pattern value} {
}
}
proc assert_failed
{
expected_err detail
}
{
if
{
$detail
ne
""
}
{
set detail
"(detail:
$detail
)"
}
else
{
set detail
"(context:
[
info frame -2
]
)"
}
error
"assertion:
$expected
_err
$detail
"
}
proc assert_equal
{
value expected
{
detail
""
}}
{
if
{
$expected
ne $value
}
{
if
{
$detail
ne
""
}
{
set detail
"(detail:
$detail
)"
}
else
{
set detail
"(context:
[
info frame -1
]
)"
}
error
"assertion:Expected '
$value
' to be equal to '
$expected
'
$detail
"
assert_failed
"Expected '
$value
' to be equal to '
$expected
'"
$detail
}
}
proc assert_lessthan
{
value expected
{
detail
""
}}
{
if
{
!
(
$value
< $expected
)}
{
if
{
$detail
ne
""
}
{
set detail
"(detail:
$detail
)"
}
else
{
set detail
"(context:
[
info frame -1
]
)"
}
error
"assertion:Expected '
$value
' to be lessthan to '
$expected
'
$detail
"
assert_failed
"Expected '
$value
' to be less than '
$expected
'"
$detail
}
}
proc assert_lessthan_equal
{
value expected
{
detail
""
}}
{
if
{
!
(
$value
<= $expected
)}
{
assert_failed
"Expected '
$value
' to be less than or equal to '
$expected
'"
$detail
}
}
proc assert_morethan
{
value expected
{
detail
""
}}
{
if
{
!
(
$value
> $expected
)}
{
assert_failed
"Expected '
$value
' to be more than '
$expected
'"
$detail
}
}
proc assert_morethan_equal
{
value expected
{
detail
""
}}
{
if
{
!
(
$value
>= $expected
)}
{
assert_failed
"Expected '
$value
' to be more than or equal to '
$expected
'"
$detail
}
}
proc assert_range
{
value min max
{
detail
""
}}
{
if
{
!
(
$value
<= $max && $value >= $min
)}
{
if
{
$detail
ne
""
}
{
set detail
"(detail:
$detail
)"
}
else
{
set detail
"(context:
[
info frame -1
]
)"
}
error
"assertion:Expected '
$value
' to be between to '
$min
' and '
$max
'
$detail
"
assert_failed
"Expected '
$value
' to be between to '
$min
' and '
$max
'"
$detail
}
}
...
...
tests/support/util.tcl
View file @
b34fc03e
...
...
@@ -561,6 +561,12 @@ proc cmdrstat {cmd r} {
}
}
proc errorrstat
{
cmd r
}
{
if
{[
regexp
"
\r\n
errorstat_
$cmd:
(.*?)
\r\n
"
[
$r
info errorstats
]
_ value
]}
{
set _ $value
}
}
proc generate_fuzzy_traffic_on_key
{
key duration
}
{
# Commands per type, blocking commands removed
# TODO: extract these from help.h or elsewhere, and improve to include other types
...
...
tests/test_helper.tcl
View file @
b34fc03e
...
...
@@ -18,6 +18,7 @@ set ::all_tests {
unit/protocol
unit/keyspace
unit/scan
unit/info
unit/type/string
unit/type/incr
unit/type/list
...
...
tests/unit/auth.tcl
View file @
b34fc03e
...
...
@@ -25,3 +25,44 @@ start_server {tags {"auth"} overrides {requirepass foobar}} {
r incr foo
}
{
101
}
}
start_server
{
tags
{
"auth_binary_password"
}}
{
test
{
AUTH fails when binary password is wrong
}
{
r config set requirepass
"abc
\x00
def"
catch
{
r auth abc
}
err
set _ $err
}
{
WRONGPASS*
}
test
{
AUTH succeeds when binary password is correct
}
{
r config set requirepass
"abc
\x00
def"
r auth
"abc
\x00
def"
}
{
OK
}
start_server
{
tags
{
"masterauth"
}}
{
set master
[
srv -1 client
]
set master_host
[
srv -1 host
]
set master_port
[
srv -1 port
]
set slave
[
srv 0 client
]
test
{
MASTERAUTH test with binary password
}
{
$master config set requirepass
"abc
\x00
def"
# Configure the replica with masterauth
set loglines
[
count_log_lines 0
]
$slave slaveof $master_host $master_port
$slave config set masterauth
"abc"
# Verify replica is not able to sync with master
wait_for_log_messages 0
{
"*Unable to AUTH to MASTER*"
}
$loglines 1000 10
assert_equal
{
down
}
[
s 0 master_link_status
]
# Test replica with the correct masterauth
$slave config set masterauth
"abc
\x00
def"
wait_for_condition 50 100
{
[
s 0 master_link_status
]
eq
{
up
}
}
else
{
fail
"Can't turn the instance into a replica"
}
}
}
}
tests/unit/geo.tcl
View file @
b34fc03e
...
...
@@ -74,6 +74,49 @@ start_server {tags {"geo"}} {
r geoadd nyc -73.9454966 40.747533
"lic market"
}
{
0
}
test
{
GEOADD update with CH option
}
{
assert_equal 1
[
r geoadd nyc CH 40.747533 -73.9454966
"lic market"
]
lassign
[
lindex
[
r geopos nyc
"lic market"
]
0
]
x1 y1
assert
{
abs
(
$x1
)
- 40.747 < 0.001
}
assert
{
abs
(
$y1
)
- 73.945 < 0.001
}
}
{}
test
{
GEOADD update with NX option
}
{
assert_equal 0
[
r geoadd nyc NX -73.9454966 40.747533
"lic market"
]
lassign
[
lindex
[
r geopos nyc
"lic market"
]
0
]
x1 y1
assert
{
abs
(
$x1
)
- 40.747 < 0.001
}
assert
{
abs
(
$y1
)
- 73.945 < 0.001
}
}
{}
test
{
GEOADD update with XX option
}
{
assert_equal 0
[
r geoadd nyc XX -83.9454966 40.747533
"lic market"
]
lassign
[
lindex
[
r geopos nyc
"lic market"
]
0
]
x1 y1
assert
{
abs
(
$x1
)
- 83.945 < 0.001
}
assert
{
abs
(
$y1
)
- 40.747 < 0.001
}
}
{}
test
{
GEOADD update with CH NX option
}
{
r geoadd nyc CH NX -73.9454966 40.747533
"lic market"
}
{
0
}
test
{
GEOADD update with CH XX option
}
{
r geoadd nyc CH XX -73.9454966 40.747533
"lic market"
}
{
1
}
test
{
GEOADD update with XX NX option will return syntax error
}
{
catch
{
r geoadd nyc xx nx -73.9454966 40.747533
"lic market"
}
err
set err
}
{
ERR*syntax*
}
test
{
GEOADD update with invalid option
}
{
catch
{
r geoadd nyc ch xx foo -73.9454966 40.747533
"lic market"
}
err
set err
}
{
ERR*syntax*
}
test
{
GEOADD invalid coordinates
}
{
catch
{
r geoadd nyc -73.9454966 40.747533
"lic market"
\
...
...
@@ -135,6 +178,19 @@ start_server {tags {"geo"}} {
r georadius nyc -73.9798091 40.7598464 10 km COUNT 3
}
{{
central park n/q/r
}
4545
{
union square
}}
test
{
GEORADIUS with ANY not sorted by default
}
{
r georadius nyc -73.9798091 40.7598464 10 km COUNT 3 ANY
}
{{
wtc one
}
{
union square
}
{
central park n/q/r
}}
test
{
GEORADIUS with ANY sorted by ASC
}
{
r georadius nyc -73.9798091 40.7598464 10 km COUNT 3 ANY ASC
}
{{
central park n/q/r
}
{
union square
}
{
wtc one
}}
test
{
GEORADIUS with ANY but no COUNT
}
{
catch
{
r georadius nyc -73.9798091 40.7598464 10 km ANY ASC
}
e
set e
}
{
ERR*ANY*requires*COUNT*
}
test
{
GEORADIUS with COUNT but missing integer argument
}
{
catch
{
r georadius nyc -73.9798091 40.7598464 10 km COUNT
}
e
set e
...
...
tests/unit/info.tcl
0 → 100644
View file @
b34fc03e
proc cmdstat
{
cmd
}
{
return
[
cmdrstat $cmd r
]
}
proc errorstat
{
cmd
}
{
return
[
errorrstat $cmd r
]
}
start_server
{
tags
{
"info"
}}
{
start_server
{}
{
test
{
errorstats: failed call authentication error
}
{
r config resetstat
assert_match
{}
[
errorstat ERR
]
assert_equal
[
s total_error_replies
]
0
catch
{
r auth k
}
e
assert_match
{
ERR AUTH*
}
$e
assert_match
{
*count=1*
}
[
errorstat ERR
]
assert_match
{
*calls=1,*,rejected_calls=0,failed_calls=1
}
[
cmdstat auth
]
assert_equal
[
s total_error_replies
]
1
r config resetstat
assert_match
{}
[
errorstat ERR
]
}
test
{
errorstats: failed call within MULTI/EXEC
}
{
r config resetstat
assert_match
{}
[
errorstat ERR
]
assert_equal
[
s total_error_replies
]
0
r multi
r set a b
r auth a
catch
{
r exec
}
e
assert_match
{
ERR AUTH*
}
$e
assert_match
{
*count=1*
}
[
errorstat ERR
]
assert_match
{
*calls=1,*,rejected_calls=0,failed_calls=0
}
[
cmdstat set
]
assert_match
{
*calls=1,*,rejected_calls=0,failed_calls=1
}
[
cmdstat auth
]
assert_match
{
*calls=1,*,rejected_calls=0,failed_calls=0
}
[
cmdstat exec
]
assert_equal
[
s total_error_replies
]
1
# MULTI/EXEC command errors should still be pinpointed to him
catch
{
r exec
}
e
assert_match
{
ERR EXEC without MULTI
}
$e
assert_match
{
*calls=2,*,rejected_calls=0,failed_calls=1
}
[
cmdstat exec
]
assert_match
{
*count=2*
}
[
errorstat ERR
]
assert_equal
[
s total_error_replies
]
2
}
test
{
errorstats: failed call within LUA
}
{
r config resetstat
assert_match
{}
[
errorstat ERR
]
assert_equal
[
s total_error_replies
]
0
catch
{
r eval
{
redis.pcall
(
'XGROUP', 'CREATECONSUMER', 's1', 'mygroup', 'consumer'
)
return
}
0
}
e
assert_match
{
*count=1*
}
[
errorstat ERR
]
assert_match
{
*calls=1,*,rejected_calls=0,failed_calls=1
}
[
cmdstat xgroup
]
assert_match
{
*calls=1,*,rejected_calls=0,failed_calls=0
}
[
cmdstat eval
]
# EVAL command errors should still be pinpointed to him
catch
{
r eval a
}
e
assert_match
{
ERR wrong*
}
$e
assert_match
{
*calls=1,*,rejected_calls=1,failed_calls=0
}
[
cmdstat eval
]
assert_match
{
*count=2*
}
[
errorstat ERR
]
assert_equal
[
s total_error_replies
]
2
}
test
{
errorstats: failed call NOGROUP error
}
{
r config resetstat
assert_match
{}
[
errorstat NOGROUP
]
r del mystream
r XADD mystream * f v
catch
{
r XGROUP CREATECONSUMER mystream mygroup consumer
}
e
assert_match
{
NOGROUP*
}
$e
assert_match
{
*count=1*
}
[
errorstat NOGROUP
]
assert_match
{
*calls=1,*,rejected_calls=0,failed_calls=1
}
[
cmdstat xgroup
]
r config resetstat
assert_match
{}
[
errorstat NOGROUP
]
}
test
{
errorstats: rejected call unknown command
}
{
r config resetstat
assert_equal
[
s total_error_replies
]
0
assert_match
{}
[
errorstat ERR
]
catch
{
r asdf
}
e
assert_match
{
ERR unknown*
}
$e
assert_match
{
*count=1*
}
[
errorstat ERR
]
assert_equal
[
s total_error_replies
]
1
r config resetstat
assert_match
{}
[
errorstat ERR
]
}
test
{
errorstats: rejected call within MULTI/EXEC
}
{
r config resetstat
assert_equal
[
s total_error_replies
]
0
assert_match
{}
[
errorstat ERR
]
r multi
catch
{
r set
}
e
assert_match
{
ERR wrong number of arguments*
}
$e
catch
{
r exec
}
e
assert_match
{
EXECABORT*
}
$e
assert_match
{
*count=1*
}
[
errorstat ERR
]
assert_equal
[
s total_error_replies
]
1
assert_match
{
*calls=0,*,rejected_calls=1,failed_calls=0
}
[
cmdstat set
]
assert_match
{
*calls=1,*,rejected_calls=0,failed_calls=0
}
[
cmdstat multi
]
assert_match
{
*calls=1,*,rejected_calls=0,failed_calls=0
}
[
cmdstat exec
]
assert_equal
[
s total_error_replies
]
1
r config resetstat
assert_match
{}
[
errorstat ERR
]
}
test
{
errorstats: rejected call due to wrong arity
}
{
r config resetstat
assert_equal
[
s total_error_replies
]
0
assert_match
{}
[
errorstat ERR
]
catch
{
r set k
}
e
assert_match
{
ERR wrong number of arguments*
}
$e
assert_match
{
*count=1*
}
[
errorstat ERR
]
assert_match
{
*calls=0,*,rejected_calls=1,failed_calls=0
}
[
cmdstat set
]
# ensure that after a rejected command, valid ones are counted properly
r set k1 v1
r set k2 v2
assert_match
{
calls=2,*,rejected_calls=1,failed_calls=0
}
[
cmdstat set
]
assert_equal
[
s total_error_replies
]
1
}
test
{
errorstats: rejected call by OOM error
}
{
r config resetstat
assert_equal
[
s total_error_replies
]
0
assert_match
{}
[
errorstat OOM
]
r config set maxmemory 1
catch
{
r set a b
}
e
assert_match
{
OOM*
}
$e
assert_match
{
*count=1*
}
[
errorstat OOM
]
assert_match
{
*calls=0,*,rejected_calls=1,failed_calls=0
}
[
cmdstat set
]
assert_equal
[
s total_error_replies
]
1
r config resetstat
assert_match
{}
[
errorstat OOM
]
}
test
{
errorstats: rejected call by authorization error
}
{
r config resetstat
assert_equal
[
s total_error_replies
]
0
assert_match
{}
[
errorstat NOPERM
]
r ACL SETUSER alice on >p1pp0 ~cached:* +get +info +config
r auth alice p1pp0
catch
{
r set a b
}
e
assert_match
{
NOPERM*
}
$e
assert_match
{
*count=1*
}
[
errorstat NOPERM
]
assert_match
{
*calls=0,*,rejected_calls=1,failed_calls=0
}
[
cmdstat set
]
assert_equal
[
s total_error_replies
]
1
r config resetstat
assert_match
{}
[
errorstat NOPERM
]
}
}
}
tests/unit/memefficiency.tcl
View file @
b34fc03e
...
...
@@ -38,7 +38,7 @@ start_server {tags {"memefficiency"}} {
run_solo
{
defrag
}
{
start_server
{
tags
{
"defrag"
}
overrides
{
appendonly yes auto-aof-rewrite-percentage 0 save
""
}}
{
if
{[
string match
{
*jemalloc*
}
[
s mem_allocator
]]}
{
if
{[
string match
{
*jemalloc*
}
[
s mem_allocator
]]
&&
[
r debug mallctl arenas.page
]
<= 8192
}
{
test
"Active defrag"
{
r config set hz 100
r config set activedefrag no
...
...
tests/unit/moduleapi/propagate.tcl
View file @
b34fc03e
...
...
@@ -14,25 +14,103 @@ tags "modules" {
# Start the replication process...
$replica replicaof $master_host $master_port
wait_for_sync $replica
after 1000
$master propagate-test
wait_for_condition 5000 10
{
([
$replica
get timer
]
eq
"10"
)
&&
\
([
$replica
get a-from-thread
]
eq
"10"
)
}
else
{
fail
"The two counters don't match the expected value."
test
{
module propagates from timer
}
{
set repl
[
attach_to_replication_stream
]
$master propagate-test.timer
wait_for_condition 5000 10
{
[
$replica
get timer
]
eq
"3"
}
else
{
fail
"The two counters don't match the expected value."
}
assert_replication_stream $repl
{
{
select *
}
{
multi
}
{
incr timer
}
{
exec
}
{
multi
}
{
incr timer
}
{
exec
}
{
multi
}
{
incr timer
}
{
exec
}
}
close_replication_stream $repl
}
$master propagate-test-2
$master propagate-test-3
$master multi
$master propagate-test-2
$master propagate-test-3
$master exec
wait_for_ofs_sync $master $replica
test
{
module propagates from thread
}
{
set repl
[
attach_to_replication_stream
]
$master propagate-test.thread
wait_for_condition 5000 10
{
[
$replica
get a-from-thread
]
eq
"3"
}
else
{
fail
"The two counters don't match the expected value."
}
assert_replication_stream $repl
{
{
select *
}
{
incr a-from-thread
}
{
incr b-from-thread
}
{
incr a-from-thread
}
{
incr b-from-thread
}
{
incr a-from-thread
}
{
incr b-from-thread
}
}
close_replication_stream $repl
}
test
{
module propagates from from command
}
{
set repl
[
attach_to_replication_stream
]
$master propagate-test.simple
$master propagate-test.mixed
# Note the 'after-call' propagation below is out of order
(
known limitation
)
assert_replication_stream $repl
{
{
select *
}
{
multi
}
{
incr counter-1
}
{
incr counter-2
}
{
exec
}
{
multi
}
{
incr using-call
}
{
incr after-call
}
{
incr counter-1
}
{
incr counter-2
}
{
exec
}
}
close_replication_stream $repl
}
test
{
module propagates from from multi-exec
}
{
set repl
[
attach_to_replication_stream
]
$master multi
$master propagate-test.simple
$master propagate-test.mixed
$master exec
wait_for_ofs_sync $master $replica
# Note the 'after-call' propagation below is out of order
(
known limitation
)
assert_replication_stream $repl
{
{
select *
}
{
multi
}
{
incr counter-1
}
{
incr counter-2
}
{
incr using-call
}
{
incr after-call
}
{
incr counter-1
}
{
incr counter-2
}
{
exec
}
}
close_replication_stream $repl
}
assert_equal
[
s -1 unexpected_error_replies
]
0
}
}
...
...
@@ -47,11 +125,11 @@ tags "modules aof" {
r config set auto-aof-rewrite-percentage 0
;
# Disable auto-rewrite.
waitForBgrewriteaof r
r propagate-test
-2
r propagate-test
-3
r propagate-test
.simple
r propagate-test
.mixed
r multi
r propagate-test
-2
r propagate-test
-3
r propagate-test
.simple
r propagate-test
.mixed
r exec
# Load the AOF
...
...
tests/unit/multi.tcl
View file @
b34fc03e
...
...
@@ -196,6 +196,29 @@ start_server {tags {"multi"}} {
r exec
}
{
PONG
}
test
{
SWAPDB is able to touch the watched keys that exist
}
{
r flushall
r select 0
r set x 30
r watch x
;
# make sure x
(
set to 30
)
doesn't change
(
SWAPDB will
"delete"
it
)
r swapdb 0 1
r multi
r ping
r exec
}
{}
test
{
SWAPDB is able to touch the watched keys that do not exist
}
{
r flushall
r select 1
r set x 30
r select 0
r watch x
;
# make sure the key x
(
currently missing
)
doesn't change
(
SWAPDB will create it
)
r swapdb 0 1
r multi
r ping
r exec
}
{}
test
{
WATCH is able to remember the DB a key belongs to
}
{
r select 5
r set x 30
...
...
@@ -299,10 +322,14 @@ start_server {tags {"multi"}} {
r multi
r del foo
r exec
# add another command so that when we see it we know multi-exec wasn't
# propagated
r incr foo
assert_replication_stream $repl
{
{
select *
}
{
multi
}
{
exec
}
{
incr foo
}
}
close_replication_stream $repl
}
...
...
@@ -521,4 +548,83 @@ start_server {tags {"multi"}} {
list $m $res
}
{
OK
{{}
{}
{}
{}
{}
{}
{}
{}}}
test
{
MULTI propagation of PUBLISH
}
{
set repl
[
attach_to_replication_stream
]
# make sure that PUBLISH inside MULTI is propagated in a transaction
r multi
r publish bla bla
r exec
assert_replication_stream $repl
{
{
select *
}
{
multi
}
{
publish bla bla
}
{
exec
}
}
close_replication_stream $repl
}
test
{
MULTI propagation of SCRIPT LOAD
}
{
set repl
[
attach_to_replication_stream
]
# make sure that SCRIPT LOAD inside MULTI is propagated in a transaction
r multi
r script load
{
redis.call
(
'set', KEYS
[
1
]
, 'foo'
)}
set res
[
r exec
]
set sha
[
lindex $res 0
]
assert_replication_stream $repl
{
{
select *
}
{
multi
}
{
script load *
}
{
exec
}
}
close_replication_stream $repl
}
test
{
MULTI propagation of SCRIPT LOAD
}
{
set repl
[
attach_to_replication_stream
]
# make sure that EVAL inside MULTI is propagated in a transaction
r config set lua-replicate-commands no
r multi
r eval
{
redis.call
(
'set', KEYS
[
1
]
, 'bar'
)}
1 bar
r exec
assert_replication_stream $repl
{
{
select *
}
{
multi
}
{
eval *
}
{
exec
}
}
close_replication_stream $repl
}
tags
{
"stream"
}
{
test
{
MULTI propagation of XREADGROUP
}
{
# stream is a special case because it calls propagate
()
directly for XREADGROUP
set repl
[
attach_to_replication_stream
]
r XADD mystream * foo bar
r XGROUP CREATE mystream mygroup 0
# make sure the XCALIM
(
propagated by XREADGROUP
)
is indeed inside MULTI/EXEC
r multi
r XREADGROUP GROUP mygroup consumer1 STREAMS mystream
">"
r exec
assert_replication_stream $repl
{
{
select *
}
{
xadd *
}
{
xgroup CREATE *
}
{
multi
}
{
xclaim *
}
{
exec
}
}
close_replication_stream $repl
}
}
}
tests/unit/pause.tcl
0 → 100644
View file @
b34fc03e
start_server
{
tags
{
"pause"
}}
{
test
"Test read commands are not blocked by client pause"
{
r client PAUSE 100000000 WRITE
set rd
[
redis_deferring_client
]
$rd GET FOO
$rd PING
$rd INFO
assert_equal
[
s 0 blocked_clients
]
0
r client unpause
$rd close
}
test
"Test write commands are paused by RO"
{
r client PAUSE 100000000 WRITE
set rd
[
redis_deferring_client
]
$rd SET FOO BAR
wait_for_condition 50 100
{
[
s 0 blocked_clients
]
eq
{
1
}
}
else
{
fail
"Clients are not blocked"
}
r client unpause
assert_match
"OK"
[
$rd
read
]
$rd close
}
test
"Test special commands are paused by RO"
{
r PFADD pause-hll test
r client PAUSE 100000000 WRITE
# Test that pfcount, which can replicate, is also blocked
set rd
[
redis_deferring_client
]
$rd PFCOUNT pause-hll
wait_for_condition 50 100
{
[
s 0 blocked_clients
]
eq
{
1
}
}
else
{
fail
"Clients are not blocked"
}
# Test that publish, which adds the message to the replication
# stream is blocked.
set rd2
[
redis_deferring_client
]
$rd2 publish foo bar
wait_for_condition 50 100
{
[
s 0 blocked_clients
]
eq
{
2
}
}
else
{
fail
"Clients are not blocked"
}
# Test that SCRIPT LOAD, which is replicated.
set rd3
[
redis_deferring_client
]
$rd3 script load
"return 1"
wait_for_condition 50 100
{
[
s 0 blocked_clients
]
eq
{
3
}
}
else
{
fail
"Clients are not blocked"
}
r client unpause
assert_match
"1"
[
$rd
read
]
assert_match
"0"
[
$rd2
read
]
assert_match
"*"
[
$rd3
read
]
$rd close
$rd2 close
$rd3 close
}
test
"Test read/admin mutli-execs are not blocked by pause RO"
{
r SET FOO BAR
r client PAUSE 100000000 WRITE
set rd
[
redis_deferring_client
]
$rd MULTI
assert_equal
[
$rd
read
]
"OK"
$rd PING
assert_equal
[
$rd
read
]
"QUEUED"
$rd GET FOO
assert_equal
[
$rd
read
]
"QUEUED"
$rd EXEC
assert_equal
[
s 0 blocked_clients
]
0
r client unpause
assert_match
"PONG BAR"
[
$rd
read
]
$rd close
}
test
"Test write mutli-execs are blocked by pause RO"
{
set rd
[
redis_deferring_client
]
$rd MULTI
assert_equal
[
$rd
read
]
"OK"
$rd SET FOO BAR
r client PAUSE 100000000 WRITE
assert_equal
[
$rd
read
]
"QUEUED"
$rd EXEC
wait_for_condition 50 100
{
[
s 0 blocked_clients
]
eq
{
1
}
}
else
{
fail
"Clients are not blocked"
}
r client unpause
assert_match
"OK"
[
$rd
read
]
$rd close
}
test
"Test scripts are blocked by pause RO"
{
r client PAUSE 100000000 WRITE
set rd
[
redis_deferring_client
]
$rd EVAL
"return 1"
0
wait_for_condition 50 100
{
[
s 0 blocked_clients
]
eq
{
1
}
}
else
{
fail
"Clients are not blocked"
}
r client unpause
assert_match
"1"
[
$rd
read
]
$rd close
}
test
"Test multiple clients can be queued up and unblocked"
{
r client PAUSE 100000000 WRITE
set clients
[
list
[
redis_deferring_client
]
[
redis_deferring_client
]
[
redis_deferring_client
]]
foreach client $clients
{
$client SET FOO BAR
}
wait_for_condition 50 100
{
[
s 0 blocked_clients
]
eq
{
3
}
}
else
{
fail
"Clients are not blocked"
}
r client unpause
foreach client $clients
{
assert_match
"OK"
[
$client
read
]
$client close
}
}
test
"Test clients with syntax errors will get responses immediately"
{
r client PAUSE 100000000 WRITE
catch
{
r set FOO
}
err
assert_match
"ERR wrong number of arguments for *"
$err
r client unpause
}
test
"Test both active and passive expiries are skipped during client pause"
{
set expired_keys
[
s 0 expired_keys
]
r multi
r set foo bar PX 10
r set bar foo PX 10
r client PAUSE 100000000 WRITE
r exec
wait_for_condition 10 100
{
[
r get foo
]
==
{}
&&
[
r get bar
]
==
{}
}
else
{
fail
"Keys were never logically expired"
}
# No keys should actually have been expired
assert_match $expired_keys
[
s 0 expired_keys
]
r client unpause
# Force the keys to expire
r get foo
r get bar
# Now that clients have been unpaused, expires should go through
assert_match
[
expr $expired_keys + 2
]
[
s 0 expired_keys
]
}
test
"Test that client pause starts at the end of a transaction"
{
r MULTI
r SET FOO1 BAR
r client PAUSE 100000000 WRITE
r SET FOO2 BAR
r exec
set rd
[
redis_deferring_client
]
$rd SET FOO3 BAR
wait_for_condition 50 100
{
[
s 0 blocked_clients
]
eq
{
1
}
}
else
{
fail
"Clients are not blocked"
}
assert_match
"BAR"
[
r GET FOO1
]
assert_match
"BAR"
[
r GET FOO2
]
assert_match
""
[
r GET FOO3
]
r client unpause
assert_match
"OK"
[
$rd
read
]
$rd close
}
# Make sure we unpause at the end
r client unpause
}
tests/unit/scripting.tcl
View file @
b34fc03e
...
...
@@ -563,6 +563,30 @@ start_server {tags {"scripting"}} {
}
e
set e
}
{
*wrong number*
}
test
{
Script with RESP3 map
}
{
set expected_dict
[
dict create field value
]
set expected_list
[
list field value
]
# Sanity test for RESP3 without scripts
r HELLO 3
r hset hash field value
set res
[
r hgetall hash
]
assert_equal $res $expected_dict
# Test RESP3 client with script in both RESP2 and RESP3 modes
set res
[
r eval
{
redis.setresp
(
3
);
return redis.call
(
'hgetall', KEYS
[
1
])}
1 hash
]
assert_equal $res $expected_dict
set res
[
r eval
{
redis.setresp
(
2
);
return redis.call
(
'hgetall', KEYS
[
1
])}
1 hash
]
assert_equal $res $expected_list
# Test RESP2 client with script in both RESP2 and RESP3 modes
r HELLO 2
set res
[
r eval
{
redis.setresp
(
3
);
return redis.call
(
'hgetall', KEYS
[
1
])}
1 hash
]
assert_equal $res $expected_list
set res
[
r eval
{
redis.setresp
(
2
);
return redis.call
(
'hgetall', KEYS
[
1
])}
1 hash
]
assert_equal $res $expected_list
}
}
# Start a new server since the last test in this stanza will kill the
...
...
Prev
1
2
3
4
5
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