Unverified Commit 959d6035 authored by Oran Agra's avatar Oran Agra Committed by GitHub
Browse files

Merge 6.2.2 release

Release 6.2.2
parents 92bde124 aa730ef1
...@@ -31,7 +31,7 @@ proc zlistAlikeSort {a b} { ...@@ -31,7 +31,7 @@ proc zlistAlikeSort {a b} {
# Return all log lines starting with the first line that contains a warning. # Return all log lines starting with the first line that contains a warning.
# Generally, this will be an assertion error with a stack trace. # Generally, this will be an assertion error with a stack trace.
proc warnings_from_file {filename} { proc crashlog_from_file {filename} {
set lines [split [exec cat $filename] "\n"] set lines [split [exec cat $filename] "\n"]
set matched 0 set matched 0
set logall 0 set logall 0
...@@ -506,18 +506,18 @@ proc stop_write_load {handle} { ...@@ -506,18 +506,18 @@ proc stop_write_load {handle} {
proc K { x y } { set x } proc K { x y } { set x }
# Shuffle a list. From Tcl wiki. Originally from Steve Cohen that improved # Shuffle a list with Fisher-Yates algorithm.
# other versions. Code should be under public domain.
proc lshuffle {list} { proc lshuffle {list} {
set n [llength $list] set n [llength $list]
while {$n>0} { while {$n>1} {
set j [expr {int(rand()*$n)}] set j [expr {int(rand()*$n)}]
lappend slist [lindex $list $j]
incr n -1 incr n -1
set temp [lindex $list $n] if {$n==$j} continue
set list [lreplace [K $list [set list {}]] $j $j $temp] set v [lindex $list $j]
lset list $j [lindex $list $n]
lset list $n $v
} }
return $slist return $list
} }
# Execute a background process writing complex data for the specified number # Execute a background process writing complex data for the specified number
...@@ -682,20 +682,83 @@ proc string2printable s { ...@@ -682,20 +682,83 @@ proc string2printable s {
return $res return $res
} }
# Check that probability of each element are between {min_prop} and {max_prop}. # Calculation value of Chi-Square Distribution. By this value
proc check_histogram_distribution {res min_prop max_prop} { # we can verify the random distribution sample confidence.
# Based on the following wiki:
# https://en.wikipedia.org/wiki/Chi-square_distribution
#
# param res Random sample list
# return Value of Chi-Square Distribution
#
# x2_value: return of chi_square_value function
# df: Degrees of freedom, Number of independent values minus 1
#
# By using x2_value and df to back check the cardinality table,
# we can know the confidence of the random sample.
proc chi_square_value {res} {
unset -nocomplain mydict unset -nocomplain mydict
foreach key $res { foreach key $res {
dict incr mydict $key 1 dict incr mydict $key 1
} }
set x2_value 0
set p [expr [llength $res] / [dict size $mydict]]
foreach key [dict keys $mydict] { foreach key [dict keys $mydict] {
set value [dict get $mydict $key] set value [dict get $mydict $key]
set probability [expr {double($value) / [llength $res]}]
if {$probability < $min_prop || $probability > $max_prop} { # Aggregate the chi-square value of each element
return false set v [expr {pow($value - $p, 2) / $p}]
set x2_value [expr {$x2_value + $v}]
}
return $x2_value
}
#subscribe to Pub/Sub channels
proc consume_subscribe_messages {client type channels} {
set numsub -1
set counts {}
for {set i [llength $channels]} {$i > 0} {incr i -1} {
set msg [$client read]
assert_equal $type [lindex $msg 0]
# when receiving subscribe messages the channels names
# are ordered. when receiving unsubscribe messages
# they are unordered
set idx [lsearch -exact $channels [lindex $msg 1]]
if {[string match "*unsubscribe" $type]} {
assert {$idx >= 0}
} else {
assert {$idx == 0}
} }
set channels [lreplace $channels $idx $idx]
# aggregate the subscription count to return to the caller
lappend counts [lindex $msg 2]
} }
return true # we should have received messages for channels
assert {[llength $channels] == 0}
return $counts
}
proc subscribe {client channels} {
$client subscribe {*}$channels
consume_subscribe_messages $client subscribe $channels
}
proc unsubscribe {client {channels {}}} {
$client unsubscribe {*}$channels
consume_subscribe_messages $client unsubscribe $channels
}
proc psubscribe {client channels} {
$client psubscribe {*}$channels
consume_subscribe_messages $client psubscribe $channels
} }
proc punsubscribe {client {channels {}}} {
$client punsubscribe {*}$channels
consume_subscribe_messages $client punsubscribe $channels
}
\ No newline at end of file
...@@ -113,6 +113,46 @@ start_server {tags {"acl"}} { ...@@ -113,6 +113,46 @@ start_server {tags {"acl"}} {
set e set e
} {*NOPERM*channel*} } {*NOPERM*channel*}
test {Validate subset of channels is prefixed with resetchannels flag} {
r ACL setuser hpuser on nopass resetchannels &foo +@all
# Verify resetchannels flag is prefixed before the channel name(s)
set users [r ACL LIST]
set curruser "hpuser"
foreach user [lshuffle $users] {
if {[string first $curruser $user] != -1} {
assert_equal {user hpuser on nopass resetchannels &foo +@all} $user
}
}
# authenticate as hpuser
r AUTH hpuser pass
assert_equal {0} [r PUBLISH foo bar]
catch {r PUBLISH bar game} e
# Falling back to psuser for the below tests
r AUTH psuser pspass
r ACL deluser hpuser
set e
} {*NOPERM*channel*}
test {In transaction queue publish/subscribe/psubscribe to unauthorized channel will fail} {
r ACL setuser psuser +multi +discard
r MULTI
catch {r PUBLISH notexits helloworld} e
r DISCARD
assert_match {*NOPERM*} $e
r MULTI
catch {r SUBSCRIBE notexits foo:1} e
r DISCARD
assert_match {*NOPERM*} $e
r MULTI
catch {r PSUBSCRIBE notexits:* bar:*} e
r DISCARD
assert_match {*NOPERM*} $e
}
test {It's possible to allow subscribing to a subset of channels} { test {It's possible to allow subscribing to a subset of channels} {
set rd [redis_deferring_client] set rd [redis_deferring_client]
$rd AUTH psuser pspass $rd AUTH psuser pspass
...@@ -409,6 +449,14 @@ start_server {tags {"acl"}} { ...@@ -409,6 +449,14 @@ start_server {tags {"acl"}} {
set e set e
} {*NOAUTH*} } {*NOAUTH*}
test {When default user has no command permission, hello command still works for other users} {
r ACL setuser secure-user >supass on +@all
r ACL setuser default -@all
r HELLO 2 AUTH secure-user supass
r ACL setuser default nopass +@all
r AUTH default ""
}
test {ACL HELP should not have unexpected options} { test {ACL HELP should not have unexpected options} {
catch {r ACL help xxx} e catch {r ACL help xxx} e
assert_match "*Unknown subcommand or wrong number of arguments*" $e assert_match "*Unknown subcommand or wrong number of arguments*" $e
...@@ -437,14 +485,44 @@ exec cp -f tests/assets/user.acl $server_path ...@@ -437,14 +485,44 @@ exec cp -f tests/assets/user.acl $server_path
start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"]] { start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"]] {
# user alice on allcommands allkeys >alice # user alice on allcommands allkeys >alice
# user bob on -@all +@set +acl ~set* >bob # user bob on -@all +@set +acl ~set* >bob
# user default on nopass ~* +@all
test {default: load from include file, can access any channels} {
r SUBSCRIBE foo
r PSUBSCRIBE bar*
r UNSUBSCRIBE
r PUNSUBSCRIBE
r PUBLISH hello world
}
test "Alice: can excute all command" { test {default: with config acl-pubsub-default allchannels after reset, can access any channels} {
r ACL setuser default reset on nopass ~* +@all
r SUBSCRIBE foo
r PSUBSCRIBE bar*
r UNSUBSCRIBE
r PUNSUBSCRIBE
r PUBLISH hello world
}
test {default: with config acl-pubsub-default resetchannels after reset, can not access any channels} {
r CONFIG SET acl-pubsub-default resetchannels
r ACL setuser default reset on nopass ~* +@all
catch {r SUBSCRIBE foo} e
assert_match {*NOPERM*} $e
catch {r PSUBSCRIBE bar*} e
assert_match {*NOPERM*} $e
catch {r PUBLISH hello world} e
assert_match {*NOPERM*} $e
r CONFIG SET acl-pubsub-default resetchannels
}
test {Alice: can execute all command} {
r AUTH alice alice r AUTH alice alice
assert_equal "alice" [r acl whoami] assert_equal "alice" [r acl whoami]
r SET key value r SET key value
} }
test "Bob: just excute @set and acl command" { test {Bob: just execute @set and acl command} {
r AUTH bob bob r AUTH bob bob
assert_equal "bob" [r acl whoami] assert_equal "bob" [r acl whoami]
assert_equal "3" [r sadd set 1 2 3] assert_equal "3" [r sadd set 1 2 3]
...@@ -452,7 +530,7 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"]] { ...@@ -452,7 +530,7 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"]] {
set e set e
} {*NOPERM*} } {*NOPERM*}
test "ACL load and save" { test {ACL load and save} {
r ACL setuser eve +get allkeys >eve on r ACL setuser eve +get allkeys >eve on
r ACL save r ACL save
...@@ -469,4 +547,85 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"]] { ...@@ -469,4 +547,85 @@ start_server [list overrides [list "dir" $server_path "aclfile" "user.acl"]] {
catch {r SET key value} e catch {r SET key value} e
set e set e
} {*NOPERM*} } {*NOPERM*}
test {ACL load and save with restricted channels} {
r AUTH alice alice
r ACL setuser harry on nopass resetchannels &test +@all ~*
r ACL save
# ACL load will free user and kill clients
r ACL load
catch {r ACL LIST} e
assert_match {*I/O error*} $e
reconnect
r AUTH harry anything
r publish test bar
catch {r publish test1 bar} e
r ACL deluser harry
set e
} {*NOPERM*}
}
set server_path [tmpdir "resetchannels.acl"]
exec cp -f tests/assets/nodefaultuser.acl $server_path
exec cp -f tests/assets/default.conf $server_path
start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "resetchannels" "aclfile" "nodefaultuser.acl"]] {
test {Default user has access to all channels irrespective of flag} {
set channelinfo [dict get [r ACL getuser default] channels]
assert_equal "*" $channelinfo
set channelinfo [dict get [r ACL getuser alice] channels]
assert_equal "" $channelinfo
}
test {Update acl-pubsub-default, existing users shouldn't get affected} {
set channelinfo [dict get [r ACL getuser default] channels]
assert_equal "*" $channelinfo
r CONFIG set acl-pubsub-default allchannels
r ACL setuser mydefault
set channelinfo [dict get [r ACL getuser mydefault] channels]
assert_equal "*" $channelinfo
r CONFIG set acl-pubsub-default resetchannels
set channelinfo [dict get [r ACL getuser mydefault] channels]
assert_equal "*" $channelinfo
}
test {Single channel is valid} {
r ACL setuser onechannel &test
set channelinfo [dict get [r ACL getuser onechannel] channels]
assert_equal test $channelinfo
r ACL deluser onechannel
}
test {Single channel is not valid with allchannels} {
r CONFIG set acl-pubsub-default allchannels
catch {r ACL setuser onechannel &test} err
r CONFIG set acl-pubsub-default resetchannels
set err
} {*start with an empty list of channels*}
}
set server_path [tmpdir "resetchannels.acl"]
exec cp -f tests/assets/nodefaultuser.acl $server_path
exec cp -f tests/assets/default.conf $server_path
start_server [list overrides [list "dir" $server_path "acl-pubsub-default" "resetchannels" "aclfile" "nodefaultuser.acl"]] {
test {Only default user has access to all channels irrespective of flag} {
set channelinfo [dict get [r ACL getuser default] channels]
assert_equal "*" $channelinfo
set channelinfo [dict get [r ACL getuser alice] channels]
assert_equal "" $channelinfo
}
}
start_server {overrides {user "default on nopass ~* +@all"}} {
test {default: load from config file, can access any channels} {
r SUBSCRIBE foo
r PSUBSCRIBE bar*
r UNSUBSCRIBE
r PUNSUBSCRIBE
r PUBLISH hello world
}
} }
...@@ -76,7 +76,7 @@ start_server {tags {"expire"}} { ...@@ -76,7 +76,7 @@ start_server {tags {"expire"}} {
# This test is very likely to do a false positive if the # This test is very likely to do a false positive if the
# server is under pressure, so if it does not work give it a few more # server is under pressure, so if it does not work give it a few more
# chances. # chances.
for {set j 0} {$j < 3} {incr j} { for {set j 0} {$j < 10} {incr j} {
r del x r del x
r setex x 1 somevalue r setex x 1 somevalue
after 900 after 900
...@@ -85,6 +85,9 @@ start_server {tags {"expire"}} { ...@@ -85,6 +85,9 @@ start_server {tags {"expire"}} {
set b [r get x] set b [r get x]
if {$a eq {somevalue} && $b eq {}} break if {$a eq {somevalue} && $b eq {}} break
} }
if {$::verbose} {
puts "millisecond expire test attempts: $j"
}
list $a $b list $a $b
} {somevalue {}} } {somevalue {}}
......
...@@ -180,6 +180,26 @@ start_server {tags {"introspection"}} { ...@@ -180,6 +180,26 @@ start_server {tags {"introspection"}} {
} }
} }
test {CONFIG REWRITE handles save properly} {
r config set save "3600 1 300 100 60 10000"
r config rewrite
restart_server 0 true false
assert_equal [r config get save] {save {3600 1 300 100 60 10000}}
r config set save ""
r config rewrite
restart_server 0 true false
assert_equal [r config get save] {save {}}
start_server {config "minimal.conf"} {
assert_equal [r config get save] {save {3600 1 300 100 60 10000}}
r config set save ""
r config rewrite
restart_server 0 true false
assert_equal [r config get save] {save {}}
}
}
# Config file at this point is at a wierd state, and includes all # Config file at this point is at a wierd state, and includes all
# known keywords. Might be a good idea to avoid adding tests here. # known keywords. Might be a good idea to avoid adding tests here.
} }
...@@ -178,7 +178,7 @@ proc test_slave_buffers {test_name cmd_count payload_len limit_memory pipeline} ...@@ -178,7 +178,7 @@ proc test_slave_buffers {test_name cmd_count payload_len limit_memory pipeline}
set orig_client_buf [s -1 mem_clients_normal] set orig_client_buf [s -1 mem_clients_normal]
set orig_mem_not_counted_for_evict [s -1 mem_not_counted_for_evict] set orig_mem_not_counted_for_evict [s -1 mem_not_counted_for_evict]
set orig_used_no_repl [expr {$orig_used - $orig_mem_not_counted_for_evict}] set orig_used_no_repl [expr {$orig_used - $orig_mem_not_counted_for_evict}]
set limit [expr {$orig_used - $orig_mem_not_counted_for_evict + 20*1024}] set limit [expr {$orig_used - $orig_mem_not_counted_for_evict + 32*1024}]
if {$limit_memory==1} { if {$limit_memory==1} {
$master config set maxmemory $limit $master config set maxmemory $limit
......
...@@ -67,5 +67,20 @@ tags "modules" { ...@@ -67,5 +67,20 @@ tags "modules" {
assert_equal {1} [r get lua] assert_equal {1} [r get lua]
r get x r get x
} {3} } {3}
test {Test module key space event} {
r keyspace.notify x
assert_equal {1 x} [r keyspace.is_module_key_notified x]
}
test "Keyspace notifications: module events test" {
r config set notify-keyspace-events Kd
r del x
set rd1 [redis_deferring_client]
assert_equal {1} [psubscribe $rd1 *]
r keyspace.notify x
assert_equal {pmessage * __keyspace@9__:x notify} [$rd1 read]
$rd1 close
}
} }
} }
...@@ -2,7 +2,7 @@ set testmodule [file normalize tests/modules/propagate.so] ...@@ -2,7 +2,7 @@ set testmodule [file normalize tests/modules/propagate.so]
tags "modules" { tags "modules" {
test {Modules can propagate in async and threaded contexts} { test {Modules can propagate in async and threaded contexts} {
start_server {} { start_server [list overrides [list loadmodule "$testmodule"]] {
set replica [srv 0 client] set replica [srv 0 client]
set replica_host [srv 0 host] set replica_host [srv 0 host]
set replica_port [srv 0 port] set replica_port [srv 0 port]
...@@ -42,6 +42,59 @@ tags "modules" { ...@@ -42,6 +42,59 @@ tags "modules" {
close_replication_stream $repl close_replication_stream $repl
} }
test {module propagates nested ctx case1} {
set repl [attach_to_replication_stream]
$master del timer-nested-start
$master del timer-nested-end
$master propagate-test.timer-nested
wait_for_condition 5000 10 {
[$replica get timer-nested-end] eq "1"
} else {
fail "The two counters don't match the expected value."
}
assert_replication_stream $repl {
{select *}
{multi}
{incrby timer-nested-start 1}
{incrby timer-nested-end 1}
{exec}
}
close_replication_stream $repl
}
test {module propagates nested ctx case2} {
set repl [attach_to_replication_stream]
$master del timer-nested-start
$master del timer-nested-end
$master propagate-test.timer-nested-repl
wait_for_condition 5000 10 {
[$replica get timer-nested-end] eq "1"
} else {
fail "The two counters don't match the expected value."
}
# Note the 'after-call' and 'timer-nested-start' propagation below is out of order (known limitation)
assert_replication_stream $repl {
{select *}
{multi}
{incr using-call}
{incr counter-1}
{incr counter-2}
{incr after-call}
{incr counter-3}
{incr counter-4}
{incrby timer-nested-start 1}
{incrby timer-nested-end 1}
{exec}
}
close_replication_stream $repl
}
test {module propagates from thread} { test {module propagates from thread} {
set repl [attach_to_replication_stream] set repl [attach_to_replication_stream]
...@@ -88,6 +141,55 @@ tags "modules" { ...@@ -88,6 +141,55 @@ tags "modules" {
close_replication_stream $repl close_replication_stream $repl
} }
test {module propagates from from command after good EVAL} {
set repl [attach_to_replication_stream]
assert_equal [ $master eval { return "hello" } 0 ] {hello}
$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 command after bad EVAL} {
set repl [attach_to_replication_stream]
catch { $master eval { return "hello" } -12 } e
assert_equal $e {ERR Number of keys can't be negative}
$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} { test {module propagates from from multi-exec} {
set repl [attach_to_replication_stream] set repl [attach_to_replication_stream]
...@@ -111,6 +213,31 @@ tags "modules" { ...@@ -111,6 +213,31 @@ tags "modules" {
} }
close_replication_stream $repl close_replication_stream $repl
} }
test {module RM_Call of expired key propagation} {
$master debug set-active-expire 0
$master set k1 900 px 100
wait_for_ofs_sync $master $replica
after 110
set repl [attach_to_replication_stream]
$master propagate-test.incr k1
wait_for_ofs_sync $master $replica
assert_replication_stream $repl {
{select *}
{del k1}
{propagate-test.incr k1}
}
close_replication_stream $repl
assert_equal [$master get k1] 1
assert_equal [$master ttl k1] -1
assert_equal [$replica get k1] 1
assert_equal [$replica ttl k1] -1
}
assert_equal [s -1 unexpected_error_replies] 0 assert_equal [s -1 unexpected_error_replies] 0
} }
} }
......
...@@ -31,7 +31,11 @@ start_server {tags {"obuf-limits"}} { ...@@ -31,7 +31,11 @@ start_server {tags {"obuf-limits"}} {
set start_time 0 set start_time 0
set time_elapsed 0 set time_elapsed 0
while 1 { while 1 {
r publish foo bar if {$start_time != 0} {
# Slow down loop when omen has reached the limit.
after 10
}
r publish foo [string repeat "x" 1000]
set clients [split [r client list] "\r\n"] set clients [split [r client list] "\r\n"]
set c [split [lindex $clients 1] " "] set c [split [lindex $clients 1] " "]
if {![regexp {omem=([0-9]+)} $c - omem]} break if {![regexp {omem=([0-9]+)} $c - omem]} break
...@@ -57,7 +61,11 @@ start_server {tags {"obuf-limits"}} { ...@@ -57,7 +61,11 @@ start_server {tags {"obuf-limits"}} {
set start_time 0 set start_time 0
set time_elapsed 0 set time_elapsed 0
while 1 { while 1 {
r publish foo bar if {$start_time != 0} {
# Slow down loop when omen has reached the limit.
after 10
}
r publish foo [string repeat "x" 1000]
set clients [split [r client list] "\r\n"] set clients [split [r client list] "\r\n"]
set c [split [lindex $clients 1] " "] set c [split [lindex $clients 1] " "]
if {![regexp {omem=([0-9]+)} $c - omem]} break if {![regexp {omem=([0-9]+)} $c - omem]} break
......
start_server {tags {"other"}} { start_server {overrides {save ""} tags {"other"}} {
if {$::force_failure} { if {$::force_failure} {
# This is used just for test suite development purposes. # This is used just for test suite development purposes.
test {Failing test} { test {Failing test} {
...@@ -309,6 +309,12 @@ start_server {tags {"other"}} { ...@@ -309,6 +309,12 @@ start_server {tags {"other"}} {
populate 4096 "" 1 populate 4096 "" 1
r bgsave r bgsave
wait_for_condition 10 100 {
[s rdb_bgsave_in_progress] eq 1
} else {
fail "bgsave did not start in time"
}
r mset k1 v1 k2 v2 r mset k1 v1 k2 v2
# Hash table should not rehash # Hash table should not rehash
assert_no_match "*table size: 8192*" [r debug HTSTATS 9] assert_no_match "*table size: 8192*" [r debug HTSTATS 9]
......
...@@ -25,11 +25,12 @@ start_server {} { ...@@ -25,11 +25,12 @@ start_server {} {
$slave slaveof $master_host $master_port $slave slaveof $master_host $master_port
set _v [prepare_value [expr 32*1024*1024]] set _v [prepare_value [expr 32*1024*1024]]
$master set key $_v $master set key $_v
after 2000 wait_for_ofs_sync $master $slave
set m_usedmemory [info_memory $master used_memory]
set s_usedmemory [info_memory $slave used_memory] wait_for_condition 50 100 {
if { $s_usedmemory > $m_usedmemory + 10*1024*1024 } { [info_memory $slave used_memory] <= [info_memory $master used_memory] + 10*1024*1024
fail "the used_memory of replica is much larger than master. Master:$m_usedmemory Replica:$s_usedmemory" } else {
fail "the used_memory of replica is much larger than master."
} }
} }
}} }}
start_server {tags {"pubsub network"}} { start_server {tags {"pubsub network"}} {
proc __consume_subscribe_messages {client type channels} {
set numsub -1
set counts {}
for {set i [llength $channels]} {$i > 0} {incr i -1} {
set msg [$client read]
assert_equal $type [lindex $msg 0]
# when receiving subscribe messages the channels names
# are ordered. when receiving unsubscribe messages
# they are unordered
set idx [lsearch -exact $channels [lindex $msg 1]]
if {[string match "*unsubscribe" $type]} {
assert {$idx >= 0}
} else {
assert {$idx == 0}
}
set channels [lreplace $channels $idx $idx]
# aggregate the subscription count to return to the caller
lappend counts [lindex $msg 2]
}
# we should have received messages for channels
assert {[llength $channels] == 0}
return $counts
}
proc subscribe {client channels} {
$client subscribe {*}$channels
__consume_subscribe_messages $client subscribe $channels
}
proc unsubscribe {client {channels {}}} {
$client unsubscribe {*}$channels
__consume_subscribe_messages $client unsubscribe $channels
}
proc psubscribe {client channels} {
$client psubscribe {*}$channels
__consume_subscribe_messages $client psubscribe $channels
}
proc punsubscribe {client {channels {}}} {
$client punsubscribe {*}$channels
__consume_subscribe_messages $client punsubscribe $channels
}
test "Pub/Sub PING" { test "Pub/Sub PING" {
set rd1 [redis_deferring_client] set rd1 [redis_deferring_client]
subscribe $rd1 somechannel subscribe $rd1 somechannel
......
...@@ -612,6 +612,71 @@ start_server {tags {"scripting"}} { ...@@ -612,6 +612,71 @@ start_server {tags {"scripting"}} {
assert_equal [r ping] "PONG" assert_equal [r ping] "PONG"
} }
test {Timedout read-only scripts can be killed by SCRIPT KILL even when use pcall} {
set rd [redis_deferring_client]
r config set lua-time-limit 10
$rd eval {local f = function() while 1 do redis.call('ping') end end while 1 do pcall(f) end} 0
wait_for_condition 50 100 {
[catch {r ping} e] == 1
} else {
fail "Can't wait for script to start running"
}
catch {r ping} e
assert_match {BUSY*} $e
r script kill
wait_for_condition 50 100 {
[catch {r ping} e] == 0
} else {
fail "Can't wait for script to be killed"
}
assert_equal [r ping] "PONG"
catch {$rd read} res
$rd close
assert_match {*killed by user*} $res
}
test {Timedout script does not cause a false dead client} {
set rd [redis_deferring_client]
r config set lua-time-limit 10
# senging (in a pipeline):
# 1. eval "while 1 do redis.call('ping') end" 0
# 2. ping
set buf "*3\r\n\$4\r\neval\r\n\$33\r\nwhile 1 do redis.call('ping') end\r\n\$1\r\n0\r\n"
append buf "*1\r\n\$4\r\nping\r\n"
$rd write $buf
$rd flush
wait_for_condition 50 100 {
[catch {r ping} e] == 1
} else {
fail "Can't wait for script to start running"
}
catch {r ping} e
assert_match {BUSY*} $e
r script kill
wait_for_condition 50 100 {
[catch {r ping} e] == 0
} else {
fail "Can't wait for script to be killed"
}
assert_equal [r ping] "PONG"
catch {$rd read} res
assert_match {*killed by user*} $res
set res [$rd read]
assert_match {*PONG*} $res
$rd close
}
test {Timedout script link is still usable after Lua returns} { test {Timedout script link is still usable after Lua returns} {
r config set lua-time-limit 10 r config set lua-time-limit 10
r eval {for i=1,100000 do redis.call('ping') end return 'ok'} 0 r eval {for i=1,100000 do redis.call('ping') end return 'ok'} 0
......
...@@ -41,6 +41,22 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} { ...@@ -41,6 +41,22 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} {
assert_equal {foobar} [lindex $e 5] assert_equal {foobar} [lindex $e 5]
} }
test {SLOWLOG - Certain commands are omitted that contain sensitive information} {
r config set slowlog-log-slower-than 0
r slowlog reset
r config set masterauth ""
r acl setuser slowlog-test-user
r config set slowlog-log-slower-than 0
r config set slowlog-log-slower-than 10000
set slowlog_resp [r slowlog get]
# Make sure normal configs work, but the two sensitive
# commands are omitted
assert_equal 2 [llength $slowlog_resp]
assert_equal {slowlog reset} [lindex [lindex [r slowlog get] 1] 3]
assert_equal {config set slowlog-log-slower-than 0} [lindex [lindex [r slowlog get] 0] 3]
}
test {SLOWLOG - Rewritten commands are logged as their original command} { test {SLOWLOG - Rewritten commands are logged as their original command} {
r config set slowlog-log-slower-than 0 r config set slowlog-log-slower-than 0
...@@ -74,6 +90,22 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} { ...@@ -74,6 +90,22 @@ start_server {tags {"slowlog"} overrides {slowlog-log-slower-than 1000000}} {
# INCRBYFLOAT is replicated as SET # INCRBYFLOAT is replicated as SET
r INCRBYFLOAT A 1.0 r INCRBYFLOAT A 1.0
assert_equal {INCRBYFLOAT A 1.0} [lindex [lindex [r slowlog get] 0] 3] assert_equal {INCRBYFLOAT A 1.0} [lindex [lindex [r slowlog get] 0] 3]
# blocked BLPOP is replicated as LPOP
set rd [redis_deferring_client]
$rd blpop l 0
wait_for_condition 50 100 {
[s blocked_clients] eq {1}
} else {
fail "Clients are not blocked"
}
r multi
r lpush l foo
r slowlog reset
r exec
$rd read
$rd close
assert_equal {blpop l 0} [lindex [lindex [r slowlog get] 0] 3]
} }
test {SLOWLOG - commands with too many arguments are trimmed} { test {SLOWLOG - commands with too many arguments are trimmed} {
......
...@@ -139,5 +139,20 @@ start_server {tags {"tls"}} { ...@@ -139,5 +139,20 @@ start_server {tags {"tls"}} {
$rd PING $rd PING
$rd close $rd close
} }
test {TLS: Working with an encrypted keyfile} {
# Create an encrypted version
set keyfile [lindex [r config get tls-key-file] 1]
set keyfile_encrypted "$keyfile.encrypted"
exec -ignorestderr openssl rsa -in $keyfile -out $keyfile_encrypted -aes256 -passout pass:1234 2>/dev/null
# Using it without a password fails
catch {r config set tls-key-file $keyfile_encrypted} e
assert_match {*Unable to update TLS*} $e
# Now use a password
r config set tls-key-file-pass 1234
r config set tls-key-file $keyfile_encrypted
}
} }
} }
...@@ -105,8 +105,9 @@ start_server {tags {"hash"}} { ...@@ -105,8 +105,9 @@ start_server {tags {"hash"}} {
assert_equal [llength $res] 2002 assert_equal [llength $res] 2002
# Test random uniform distribution # Test random uniform distribution
# df = 9, 40 means 0.00001 probability
set res [r hrandfield myhash -1000] set res [r hrandfield myhash -1000]
assert_equal [check_histogram_distribution $res 0.05 0.15] true assert_lessthan [chi_square_value $res] 40
# 2) Check that all the elements actually belong to the original hash. # 2) Check that all the elements actually belong to the original hash.
foreach {key val} $res { foreach {key val} $res {
...@@ -199,7 +200,8 @@ start_server {tags {"hash"}} { ...@@ -199,7 +200,8 @@ start_server {tags {"hash"}} {
} }
} }
assert_equal $all_ele_return true assert_equal $all_ele_return true
assert_equal [check_histogram_distribution $allkey 0.05 0.15] true # df = 9, 40 means 0.00001 probability
assert_lessthan [chi_square_value $allkey] 40
} }
} }
r config set hash-max-ziplist-value $original_max_value r config set hash-max-ziplist-value $original_max_value
......
...@@ -533,8 +533,9 @@ start_server { ...@@ -533,8 +533,9 @@ start_server {
} }
# Use negative count (PATH 1). # Use negative count (PATH 1).
# df = 9, 40 means 0.00001 probability
set res [r srandmember myset -1000] set res [r srandmember myset -1000]
assert_equal [check_histogram_distribution $res 0.05 0.15] true assert_lessthan [chi_square_value $res] 40
# Use positive count (both PATH 3 and PATH 4). # Use positive count (both PATH 3 and PATH 4).
foreach size {8 2} { foreach size {8 2} {
...@@ -547,7 +548,8 @@ start_server { ...@@ -547,7 +548,8 @@ start_server {
lappend allkey $ele lappend allkey $ele
} }
} }
assert_equal [check_histogram_distribution $allkey 0.05 0.15] true # df = 9, 40 means 0.00001 probability
assert_lessthan [chi_square_value $allkey] 40
} }
} }
} }
......
...@@ -373,7 +373,7 @@ start_server { ...@@ -373,7 +373,7 @@ start_server {
after 200 after 200
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - COUNT 1] set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - COUNT 1]
assert_equal [llength $reply] 2 assert_equal [llength $reply] 2
assert_equal [lindex $reply 0] $id1 assert_equal [lindex $reply 0] "0-0"
assert_equal [llength [lindex $reply 1]] 1 assert_equal [llength [lindex $reply 1]] 1
assert_equal [llength [lindex $reply 1 0]] 2 assert_equal [llength [lindex $reply 1 0]] 2
assert_equal [llength [lindex $reply 1 0 1]] 2 assert_equal [llength [lindex $reply 1 0 1]] 2
...@@ -392,7 +392,7 @@ start_server { ...@@ -392,7 +392,7 @@ start_server {
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - COUNT 2] set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - COUNT 2]
# id1 is self-claimed here but not id2 ('count' was set to 2) # id1 is self-claimed here but not id2 ('count' was set to 2)
assert_equal [llength $reply] 2 assert_equal [llength $reply] 2
assert_equal [lindex $reply 0] $id2 assert_equal [lindex $reply 0] $id3
assert_equal [llength [lindex $reply 1]] 2 assert_equal [llength [lindex $reply 1]] 2
assert_equal [llength [lindex $reply 1 0]] 2 assert_equal [llength [lindex $reply 1 0]] 2
assert_equal [llength [lindex $reply 1 0 1]] 2 assert_equal [llength [lindex $reply 1 0 1]] 2
...@@ -438,22 +438,22 @@ start_server { ...@@ -438,22 +438,22 @@ start_server {
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - COUNT 2] set reply [r XAUTOCLAIM mystream mygroup consumer2 10 - COUNT 2]
assert_equal [llength $reply] 2 assert_equal [llength $reply] 2
set cursor [lindex $reply 0] set cursor [lindex $reply 0]
assert_equal $cursor $id2 assert_equal $cursor $id3
assert_equal [llength [lindex $reply 1]] 2 assert_equal [llength [lindex $reply 1]] 2
assert_equal [llength [lindex $reply 1 0 1]] 2 assert_equal [llength [lindex $reply 1 0 1]] 2
assert_equal [lindex $reply 1 0 1] {a 1} assert_equal [lindex $reply 1 0 1] {a 1}
# Claim 2 more entries # Claim 2 more entries
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 ($cursor COUNT 2] set reply [r XAUTOCLAIM mystream mygroup consumer2 10 $cursor COUNT 2]
assert_equal [llength $reply] 2 assert_equal [llength $reply] 2
set cursor [lindex $reply 0] set cursor [lindex $reply 0]
assert_equal $cursor $id4 assert_equal $cursor $id5
assert_equal [llength [lindex $reply 1]] 2 assert_equal [llength [lindex $reply 1]] 2
assert_equal [llength [lindex $reply 1 0 1]] 2 assert_equal [llength [lindex $reply 1 0 1]] 2
assert_equal [lindex $reply 1 0 1] {c 3} assert_equal [lindex $reply 1 0 1] {c 3}
# Claim last entry # Claim last entry
set reply [r XAUTOCLAIM mystream mygroup consumer2 10 ($cursor COUNT 2] set reply [r XAUTOCLAIM mystream mygroup consumer2 10 $cursor COUNT 1]
assert_equal [llength $reply] 2 assert_equal [llength $reply] 2
set cursor [lindex $reply 0] set cursor [lindex $reply 0]
assert_equal $cursor {0-0} assert_equal $cursor {0-0}
...@@ -462,6 +462,10 @@ start_server { ...@@ -462,6 +462,10 @@ start_server {
assert_equal [lindex $reply 1 0 1] {e 5} assert_equal [lindex $reply 1 0 1] {e 5}
} }
test {XAUTOCLAIM COUNT must be > 0} {
assert_error "ERR COUNT must be > 0" {r XAUTOCLAIM key group consumer 1 1 COUNT 0}
}
test {XINFO FULL output} { test {XINFO FULL output} {
r del x r del x
r XADD x 100 a 1 r XADD x 100 a 1
......
...@@ -41,11 +41,11 @@ start_server {tags {"zset"}} { ...@@ -41,11 +41,11 @@ start_server {tags {"zset"}} {
assert_error "*not*float*" {r zadd myzset nan abc} assert_error "*not*float*" {r zadd myzset nan abc}
} }
test "ZSET element can't be set to NaN with ZINCRBY" { test "ZSET element can't be set to NaN with ZINCRBY - $encoding" {
assert_error "*not*float*" {r zadd myzset nan abc} assert_error "*not*float*" {r zadd myzset nan abc}
} }
test "ZADD with options syntax error with incomplete pair" { test "ZADD with options syntax error with incomplete pair - $encoding" {
r del ztmp r del ztmp
catch {r zadd ztmp xx 10 x 20} err catch {r zadd ztmp xx 10 x 20} err
set err set err
...@@ -64,14 +64,14 @@ start_server {tags {"zset"}} { ...@@ -64,14 +64,14 @@ start_server {tags {"zset"}} {
assert {[r zcard ztmp] == 1} assert {[r zcard ztmp] == 1}
} }
test "ZADD XX returns the number of elements actually added" { test "ZADD XX returns the number of elements actually added - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x r zadd ztmp 10 x
set retval [r zadd ztmp 10 x 20 y 30 z] set retval [r zadd ztmp 10 x 20 y 30 z]
assert {$retval == 2} assert {$retval == 2}
} }
test "ZADD XX updates existing elements score" { test "ZADD XX updates existing elements score - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x 20 y 30 z r zadd ztmp 10 x 20 y 30 z
r zadd ztmp xx 5 foo 11 x 21 y 40 zap r zadd ztmp xx 5 foo 11 x 21 y 40 zap
...@@ -80,7 +80,7 @@ start_server {tags {"zset"}} { ...@@ -80,7 +80,7 @@ start_server {tags {"zset"}} {
assert {[r zscore ztmp y] == 21} assert {[r zscore ztmp y] == 21}
} }
test "ZADD GT updates existing elements when new scores are greater" { test "ZADD GT updates existing elements when new scores are greater - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x 20 y 30 z r zadd ztmp 10 x 20 y 30 z
assert {[r zadd ztmp gt ch 5 foo 11 x 21 y 29 z] == 3} assert {[r zadd ztmp gt ch 5 foo 11 x 21 y 29 z] == 3}
...@@ -90,7 +90,7 @@ start_server {tags {"zset"}} { ...@@ -90,7 +90,7 @@ start_server {tags {"zset"}} {
assert {[r zscore ztmp z] == 30} assert {[r zscore ztmp z] == 30}
} }
test "ZADD LT updates existing elements when new scores are lower" { test "ZADD LT updates existing elements when new scores are lower - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x 20 y 30 z r zadd ztmp 10 x 20 y 30 z
assert {[r zadd ztmp lt ch 5 foo 11 x 21 y 29 z] == 2} assert {[r zadd ztmp lt ch 5 foo 11 x 21 y 29 z] == 2}
...@@ -100,7 +100,7 @@ start_server {tags {"zset"}} { ...@@ -100,7 +100,7 @@ start_server {tags {"zset"}} {
assert {[r zscore ztmp z] == 29} assert {[r zscore ztmp z] == 29}
} }
test "ZADD GT XX updates existing elements when new scores are greater and skips new elements" { test "ZADD GT XX updates existing elements when new scores are greater and skips new elements - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x 20 y 30 z r zadd ztmp 10 x 20 y 30 z
assert {[r zadd ztmp gt xx ch 5 foo 11 x 21 y 29 z] == 2} assert {[r zadd ztmp gt xx ch 5 foo 11 x 21 y 29 z] == 2}
...@@ -110,7 +110,7 @@ start_server {tags {"zset"}} { ...@@ -110,7 +110,7 @@ start_server {tags {"zset"}} {
assert {[r zscore ztmp z] == 30} assert {[r zscore ztmp z] == 30}
} }
test "ZADD LT XX updates existing elements when new scores are lower and skips new elements" { test "ZADD LT XX updates existing elements when new scores are lower and skips new elements - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x 20 y 30 z r zadd ztmp 10 x 20 y 30 z
assert {[r zadd ztmp lt xx ch 5 foo 11 x 21 y 29 z] == 1} assert {[r zadd ztmp lt xx ch 5 foo 11 x 21 y 29 z] == 1}
...@@ -120,19 +120,19 @@ start_server {tags {"zset"}} { ...@@ -120,19 +120,19 @@ start_server {tags {"zset"}} {
assert {[r zscore ztmp z] == 29} assert {[r zscore ztmp z] == 29}
} }
test "ZADD XX and NX are not compatible" { test "ZADD XX and NX are not compatible - $encoding" {
r del ztmp r del ztmp
catch {r zadd ztmp xx nx 10 x} err catch {r zadd ztmp xx nx 10 x} err
set err set err
} {ERR*} } {ERR*}
test "ZADD NX with non existing key" { test "ZADD NX with non existing key - $encoding" {
r del ztmp r del ztmp
r zadd ztmp nx 10 x 20 y 30 z r zadd ztmp nx 10 x 20 y 30 z
assert {[r zcard ztmp] == 3} assert {[r zcard ztmp] == 3}
} }
test "ZADD NX only add new elements without updating old ones" { test "ZADD NX only add new elements without updating old ones - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x 20 y 30 z r zadd ztmp 10 x 20 y 30 z
assert {[r zadd ztmp nx 11 x 21 y 100 a 200 b] == 2} assert {[r zadd ztmp nx 11 x 21 y 100 a 200 b] == 2}
...@@ -142,73 +142,105 @@ start_server {tags {"zset"}} { ...@@ -142,73 +142,105 @@ start_server {tags {"zset"}} {
assert {[r zscore ztmp b] == 200} assert {[r zscore ztmp b] == 200}
} }
test "ZADD GT and NX are not compatible" { test "ZADD GT and NX are not compatible - $encoding" {
r del ztmp r del ztmp
catch {r zadd ztmp gt nx 10 x} err catch {r zadd ztmp gt nx 10 x} err
set err set err
} {ERR*} } {ERR*}
test "ZADD LT and NX are not compatible" { test "ZADD LT and NX are not compatible - $encoding" {
r del ztmp r del ztmp
catch {r zadd ztmp lt nx 10 x} err catch {r zadd ztmp lt nx 10 x} err
set err set err
} {ERR*} } {ERR*}
test "ZADD LT and GT are not compatible" { test "ZADD LT and GT are not compatible - $encoding" {
r del ztmp r del ztmp
catch {r zadd ztmp lt gt 10 x} err catch {r zadd ztmp lt gt 10 x} err
set err set err
} {ERR*} } {ERR*}
test "ZADD INCR works like ZINCRBY" { test "ZADD INCR LT/GT replies with nill if score not updated - $encoding" {
r del ztmp
r zadd ztmp 28 x
assert {[r zadd ztmp lt incr 1 x] eq {}}
assert {[r zscore ztmp x] == 28}
assert {[r zadd ztmp gt incr -1 x] eq {}}
assert {[r zscore ztmp x] == 28}
}
test "ZADD INCR LT/GT with inf - $encoding" {
r del ztmp
r zadd ztmp +inf x -inf y
assert {[r zadd ztmp lt incr 1 x] eq {}}
assert {[r zscore ztmp x] == inf}
assert {[r zadd ztmp gt incr -1 x] eq {}}
assert {[r zscore ztmp x] == inf}
assert {[r zadd ztmp lt incr -1 x] eq {}}
assert {[r zscore ztmp x] == inf}
assert {[r zadd ztmp gt incr 1 x] eq {}}
assert {[r zscore ztmp x] == inf}
assert {[r zadd ztmp lt incr 1 y] eq {}}
assert {[r zscore ztmp y] == -inf}
assert {[r zadd ztmp gt incr -1 y] eq {}}
assert {[r zscore ztmp y] == -inf}
assert {[r zadd ztmp lt incr -1 y] eq {}}
assert {[r zscore ztmp y] == -inf}
assert {[r zadd ztmp gt incr 1 y] eq {}}
assert {[r zscore ztmp y] == -inf}
}
test "ZADD INCR works like ZINCRBY - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x 20 y 30 z r zadd ztmp 10 x 20 y 30 z
r zadd ztmp INCR 15 x r zadd ztmp INCR 15 x
assert {[r zscore ztmp x] == 25} assert {[r zscore ztmp x] == 25}
} }
test "ZADD INCR works with a single score-elemenet pair" { test "ZADD INCR works with a single score-elemenet pair - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x 20 y 30 z r zadd ztmp 10 x 20 y 30 z
catch {r zadd ztmp INCR 15 x 10 y} err catch {r zadd ztmp INCR 15 x 10 y} err
set err set err
} {ERR*} } {ERR*}
test "ZADD CH option changes return value to all changed elements" { test "ZADD CH option changes return value to all changed elements - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x 20 y 30 z r zadd ztmp 10 x 20 y 30 z
assert {[r zadd ztmp 11 x 21 y 30 z] == 0} assert {[r zadd ztmp 11 x 21 y 30 z] == 0}
assert {[r zadd ztmp ch 12 x 22 y 30 z] == 2} assert {[r zadd ztmp ch 12 x 22 y 30 z] == 2}
} }
test "ZINCRBY calls leading to NaN result in error" { test "ZINCRBY calls leading to NaN result in error - $encoding" {
r zincrby myzset +inf abc r zincrby myzset +inf abc
assert_error "*NaN*" {r zincrby myzset -inf abc} assert_error "*NaN*" {r zincrby myzset -inf abc}
} }
test {ZADD - Variadic version base case} { test {ZADD - Variadic version base case - $encoding} {
r del myzset r del myzset
list [r zadd myzset 10 a 20 b 30 c] [r zrange myzset 0 -1 withscores] list [r zadd myzset 10 a 20 b 30 c] [r zrange myzset 0 -1 withscores]
} {3 {a 10 b 20 c 30}} } {3 {a 10 b 20 c 30}}
test {ZADD - Return value is the number of actually added items} { test {ZADD - Return value is the number of actually added items - $encoding} {
list [r zadd myzset 5 x 20 b 30 c] [r zrange myzset 0 -1 withscores] list [r zadd myzset 5 x 20 b 30 c] [r zrange myzset 0 -1 withscores]
} {1 {x 5 a 10 b 20 c 30}} } {1 {x 5 a 10 b 20 c 30}}
test {ZADD - Variadic version does not add nothing on single parsing err} { test {ZADD - Variadic version does not add nothing on single parsing err - $encoding} {
r del myzset r del myzset
catch {r zadd myzset 10 a 20 b 30.badscore c} e catch {r zadd myzset 10 a 20 b 30.badscore c} e
assert_match {*ERR*not*float*} $e assert_match {*ERR*not*float*} $e
r exists myzset r exists myzset
} {0} } {0}
test {ZADD - Variadic version will raise error on missing arg} { test {ZADD - Variadic version will raise error on missing arg - $encoding} {
r del myzset r del myzset
catch {r zadd myzset 10 a 20 b 30 c 40} e catch {r zadd myzset 10 a 20 b 30 c 40} e
assert_match {*ERR*syntax*} $e assert_match {*ERR*syntax*} $e
} }
test {ZINCRBY does not work variadic even if shares ZADD implementation} { test {ZINCRBY does not work variadic even if shares ZADD implementation - $encoding} {
r del myzset r del myzset
catch {r zincrby myzset 10 a 20 b 30 c} e catch {r zincrby myzset 10 a 20 b 30 c} e
assert_match {*ERR*wrong*number*arg*} $e assert_match {*ERR*wrong*number*arg*} $e
...@@ -221,7 +253,7 @@ start_server {tags {"zset"}} { ...@@ -221,7 +253,7 @@ start_server {tags {"zset"}} {
assert_equal 0 [r zcard zdoesntexist] assert_equal 0 [r zcard zdoesntexist]
} }
test "ZREM removes key after last element is removed" { test "ZREM removes key after last element is removed - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 x r zadd ztmp 10 x
r zadd ztmp 20 y r zadd ztmp 20 y
...@@ -233,7 +265,7 @@ start_server {tags {"zset"}} { ...@@ -233,7 +265,7 @@ start_server {tags {"zset"}} {
assert_equal 0 [r exists ztmp] assert_equal 0 [r exists ztmp]
} }
test "ZREM variadic version" { test "ZREM variadic version - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 a 20 b 30 c r zadd ztmp 10 a 20 b 30 c
assert_equal 2 [r zrem ztmp x y a b k] assert_equal 2 [r zrem ztmp x y a b k]
...@@ -242,7 +274,7 @@ start_server {tags {"zset"}} { ...@@ -242,7 +274,7 @@ start_server {tags {"zset"}} {
r exists ztmp r exists ztmp
} {0} } {0}
test "ZREM variadic version -- remove elements after key deletion" { test "ZREM variadic version -- remove elements after key deletion - $encoding" {
r del ztmp r del ztmp
r zadd ztmp 10 a 20 b 30 c r zadd ztmp 10 a 20 b 30 c
r zrem ztmp a b c d e f g r zrem ztmp a b c d e f g
...@@ -350,7 +382,7 @@ start_server {tags {"zset"}} { ...@@ -350,7 +382,7 @@ start_server {tags {"zset"}} {
assert_equal 6 [r zscore zset bar] assert_equal 6 [r zscore zset bar]
} }
test "ZINCRBY return value" { test "ZINCRBY return value - $encoding" {
r del ztmp r del ztmp
set retval [r zincrby ztmp 1.0 x] set retval [r zincrby ztmp 1.0 x]
assert {$retval == 1.0} assert {$retval == 1.0}
...@@ -360,7 +392,7 @@ start_server {tags {"zset"}} { ...@@ -360,7 +392,7 @@ start_server {tags {"zset"}} {
create_zset zset {-inf a 1 b 2 c 3 d 4 e 5 f +inf g} create_zset zset {-inf a 1 b 2 c 3 d 4 e 5 f +inf g}
} }
test "ZRANGEBYSCORE/ZREVRANGEBYSCORE/ZCOUNT basics" { test "ZRANGEBYSCORE/ZREVRANGEBYSCORE/ZCOUNT basics - $encoding" {
create_default_zset create_default_zset
# inclusive range # inclusive range
...@@ -412,13 +444,13 @@ start_server {tags {"zset"}} { ...@@ -412,13 +444,13 @@ start_server {tags {"zset"}} {
assert_equal {} [r zrangebyscore zset (2.4 (2.6] assert_equal {} [r zrangebyscore zset (2.4 (2.6]
} }
test "ZRANGEBYSCORE with WITHSCORES" { test "ZRANGEBYSCORE with WITHSCORES - $encoding" {
create_default_zset create_default_zset
assert_equal {b 1 c 2 d 3} [r zrangebyscore zset 0 3 withscores] assert_equal {b 1 c 2 d 3} [r zrangebyscore zset 0 3 withscores]
assert_equal {d 3 c 2 b 1} [r zrevrangebyscore zset 3 0 withscores] assert_equal {d 3 c 2 b 1} [r zrevrangebyscore zset 3 0 withscores]
} }
test "ZRANGEBYSCORE with LIMIT" { test "ZRANGEBYSCORE with LIMIT - $encoding" {
create_default_zset create_default_zset
assert_equal {b c} [r zrangebyscore zset 0 10 LIMIT 0 2] assert_equal {b c} [r zrangebyscore zset 0 10 LIMIT 0 2]
assert_equal {d e f} [r zrangebyscore zset 0 10 LIMIT 2 3] assert_equal {d e f} [r zrangebyscore zset 0 10 LIMIT 2 3]
...@@ -430,14 +462,14 @@ start_server {tags {"zset"}} { ...@@ -430,14 +462,14 @@ start_server {tags {"zset"}} {
assert_equal {} [r zrevrangebyscore zset 10 0 LIMIT 20 10] assert_equal {} [r zrevrangebyscore zset 10 0 LIMIT 20 10]
} }
test "ZRANGEBYSCORE with LIMIT and WITHSCORES" { test "ZRANGEBYSCORE with LIMIT and WITHSCORES - $encoding" {
create_default_zset create_default_zset
assert_equal {e 4 f 5} [r zrangebyscore zset 2 5 LIMIT 2 3 WITHSCORES] assert_equal {e 4 f 5} [r zrangebyscore zset 2 5 LIMIT 2 3 WITHSCORES]
assert_equal {d 3 c 2} [r zrevrangebyscore zset 5 2 LIMIT 2 3 WITHSCORES] assert_equal {d 3 c 2} [r zrevrangebyscore zset 5 2 LIMIT 2 3 WITHSCORES]
assert_equal {} [r zrangebyscore zset 2 5 LIMIT 12 13 WITHSCORES] assert_equal {} [r zrangebyscore zset 2 5 LIMIT 12 13 WITHSCORES]
} }
test "ZRANGEBYSCORE with non-value min or max" { test "ZRANGEBYSCORE with non-value min or max - $encoding" {
assert_error "*not*float*" {r zrangebyscore fooz str 1} assert_error "*not*float*" {r zrangebyscore fooz str 1}
assert_error "*not*float*" {r zrangebyscore fooz 1 str} assert_error "*not*float*" {r zrangebyscore fooz 1 str}
assert_error "*not*float*" {r zrangebyscore fooz 1 NaN} assert_error "*not*float*" {r zrangebyscore fooz 1 NaN}
...@@ -449,7 +481,7 @@ start_server {tags {"zset"}} { ...@@ -449,7 +481,7 @@ start_server {tags {"zset"}} {
0 omega} 0 omega}
} }
test "ZRANGEBYLEX/ZREVRANGEBYLEX/ZLEXCOUNT basics" { test "ZRANGEBYLEX/ZREVRANGEBYLEX/ZLEXCOUNT basics - $encoding" {
create_default_lex_zset create_default_lex_zset
# inclusive range # inclusive range
...@@ -478,7 +510,7 @@ start_server {tags {"zset"}} { ...@@ -478,7 +510,7 @@ start_server {tags {"zset"}} {
assert_equal {} [r zrevrangebylex zset (hill (omega] assert_equal {} [r zrevrangebylex zset (hill (omega]
} }
test "ZLEXCOUNT advanced" { test "ZLEXCOUNT advanced - $encoding" {
create_default_lex_zset create_default_lex_zset
assert_equal 9 [r zlexcount zset - +] assert_equal 9 [r zlexcount zset - +]
...@@ -494,7 +526,7 @@ start_server {tags {"zset"}} { ...@@ -494,7 +526,7 @@ start_server {tags {"zset"}} {
assert_equal 1 [r zlexcount zset (maxstring +] assert_equal 1 [r zlexcount zset (maxstring +]
} }
test "ZRANGEBYSLEX with LIMIT" { test "ZRANGEBYSLEX with LIMIT - $encoding" {
create_default_lex_zset create_default_lex_zset
assert_equal {alpha bar} [r zrangebylex zset - \[cool LIMIT 0 2] assert_equal {alpha bar} [r zrangebylex zset - \[cool LIMIT 0 2]
assert_equal {bar cool} [r zrangebylex zset - \[cool LIMIT 1 2] assert_equal {bar cool} [r zrangebylex zset - \[cool LIMIT 1 2]
...@@ -507,7 +539,7 @@ start_server {tags {"zset"}} { ...@@ -507,7 +539,7 @@ start_server {tags {"zset"}} {
assert_equal {omega hill great foo} [r zrevrangebylex zset + \[d LIMIT 0 4] assert_equal {omega hill great foo} [r zrevrangebylex zset + \[d LIMIT 0 4]
} }
test "ZRANGEBYLEX with invalid lex range specifiers" { test "ZRANGEBYLEX with invalid lex range specifiers - $encoding" {
assert_error "*not*string*" {r zrangebylex fooz foo bar} assert_error "*not*string*" {r zrangebylex fooz foo bar}
assert_error "*not*string*" {r zrangebylex fooz \[foo bar} assert_error "*not*string*" {r zrangebylex fooz \[foo bar}
assert_error "*not*string*" {r zrangebylex fooz foo \[bar} assert_error "*not*string*" {r zrangebylex fooz foo \[bar}
...@@ -515,7 +547,7 @@ start_server {tags {"zset"}} { ...@@ -515,7 +547,7 @@ start_server {tags {"zset"}} {
assert_error "*not*string*" {r zrangebylex fooz -x \[bar} assert_error "*not*string*" {r zrangebylex fooz -x \[bar}
} }
test "ZREMRANGEBYSCORE basics" { test "ZREMRANGEBYSCORE basics - $encoding" {
proc remrangebyscore {min max} { proc remrangebyscore {min max} {
create_zset zset {1 a 2 b 3 c 4 d 5 e} create_zset zset {1 a 2 b 3 c 4 d 5 e}
assert_equal 1 [r exists zset] assert_equal 1 [r exists zset]
...@@ -571,13 +603,13 @@ start_server {tags {"zset"}} { ...@@ -571,13 +603,13 @@ start_server {tags {"zset"}} {
assert_equal 0 [r exists zset] assert_equal 0 [r exists zset]
} }
test "ZREMRANGEBYSCORE with non-value min or max" { test "ZREMRANGEBYSCORE with non-value min or max - $encoding" {
assert_error "*not*float*" {r zremrangebyscore fooz str 1} assert_error "*not*float*" {r zremrangebyscore fooz str 1}
assert_error "*not*float*" {r zremrangebyscore fooz 1 str} assert_error "*not*float*" {r zremrangebyscore fooz 1 str}
assert_error "*not*float*" {r zremrangebyscore fooz 1 NaN} assert_error "*not*float*" {r zremrangebyscore fooz 1 NaN}
} }
test "ZREMRANGEBYRANK basics" { test "ZREMRANGEBYRANK basics - $encoding" {
proc remrangebyrank {min max} { proc remrangebyrank {min max} {
create_zset zset {1 a 2 b 3 c 4 d 5 e} create_zset zset {1 a 2 b 3 c 4 d 5 e}
assert_equal 1 [r exists zset] assert_equal 1 [r exists zset]
...@@ -774,7 +806,7 @@ start_server {tags {"zset"}} { ...@@ -774,7 +806,7 @@ start_server {tags {"zset"}} {
assert_equal -inf [r zscore zsetinf3 key] assert_equal -inf [r zscore zsetinf3 key]
} }
test "$cmd with NaN weights $encoding" { test "$cmd with NaN weights - $encoding" {
r del zsetinf1 zsetinf2 r del zsetinf1 zsetinf2
r zadd zsetinf1 1.0 key r zadd zsetinf1 1.0 key
...@@ -833,7 +865,7 @@ start_server {tags {"zset"}} { ...@@ -833,7 +865,7 @@ start_server {tags {"zset"}} {
assert_equal {a 1 e 5} [r zrange zsete 0 -1 withscores] assert_equal {a 1 e 5} [r zrange zsete 0 -1 withscores]
} }
test "ZDIFF fuzzing" { test "ZDIFF fuzzing - $encoding" {
for {set j 0} {$j < 100} {incr j} { for {set j 0} {$j < 100} {incr j} {
unset -nocomplain s unset -nocomplain s
array set s {} array set s {}
...@@ -1655,8 +1687,9 @@ start_server {tags {"zset"}} { ...@@ -1655,8 +1687,9 @@ start_server {tags {"zset"}} {
assert_equal [llength $res] 2002 assert_equal [llength $res] 2002
# Test random uniform distribution # Test random uniform distribution
# df = 9, 40 means 0.00001 probability
set res [r zrandmember myzset -1000] set res [r zrandmember myzset -1000]
assert_equal [check_histogram_distribution $res 0.05 0.15] true assert_lessthan [chi_square_value $res] 40
# 2) Check that all the elements actually belong to the original zset. # 2) Check that all the elements actually belong to the original zset.
foreach {key val} $res { foreach {key val} $res {
...@@ -1749,7 +1782,8 @@ start_server {tags {"zset"}} { ...@@ -1749,7 +1782,8 @@ start_server {tags {"zset"}} {
} }
} }
assert_equal $all_ele_return true assert_equal $all_ele_return true
assert_equal [check_histogram_distribution $allkey 0.05 0.15] true # df = 9, 40 means 0.00001 probability
assert_lessthan [chi_square_value $allkey] 40
} }
} }
r config set zset-max-ziplist-value $original_max_value r config set zset-max-ziplist-value $original_max_value
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Software Watchdog, which provides a similar functionality but in # Software Watchdog, which provides a similar functionality but in
# a more reliable / easy to use way. # a more reliable / easy to use way.
# #
# Check http://redis.io/topics/latency for more information. # Check https://redis.io/topics/latency for more information.
#!/bin/bash #!/bin/bash
nsamples=1 nsamples=1
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment